import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { forwardRef, InputHTMLAttributes, ReactNode, useRef } from 'react'; import 'react-phone-number-input/style.css'; import { TEXT_INPUT_STYLE } from 'twenty-ui'; import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents'; import { useCombinedRefs } from '~/hooks/useCombinedRefs'; const StyledInput = styled.input<{ withRightComponent?: boolean; hasError?: boolean; }>` ${TEXT_INPUT_STYLE} border: 1px solid ${({ theme, hasError }) => hasError ? theme.border.color.danger : theme.border.color.medium}; background-color: ${({ theme }) => theme.background.transparent.secondary}; backdrop-filter: ${({ theme }) => theme.blur.medium}; border-radius: ${({ theme }) => theme.border.radius.sm}; box-sizing: border-box; font-weight: ${({ theme }) => theme.font.weight.medium}; height: 32px; position: relative; width: 100%; ${({ withRightComponent }) => withRightComponent && css` padding-right: 32px; `} `; const StyledInputContainer = styled.div` background-color: transparent; box-sizing: border-box; position: relative; width: 100%; &:not(:first-of-type) { padding: ${({ theme }) => theme.spacing(1)}; } `; const StyledRightContainer = styled.div` position: absolute; right: ${({ theme }) => theme.spacing(1)}; top: 50%; transform: translateY(-50%); `; const StyledErrorDiv = styled.div` color: ${({ theme }) => theme.color.red}; padding: 0 ${({ theme }) => theme.spacing(2)}; `; type HTMLInputProps = InputHTMLAttributes; export type DropdownMenuInputProps = HTMLInputProps & { hotkeyScope?: string; onClickOutside?: () => void; onEnter?: () => void; onEscape?: () => void; onShiftTab?: () => void; onTab?: () => void; rightComponent?: ReactNode; renderInput?: (props: { value: HTMLInputProps['value']; onChange: HTMLInputProps['onChange']; autoFocus: HTMLInputProps['autoFocus']; placeholder: HTMLInputProps['placeholder']; }) => React.ReactNode; error?: string | null; hasError?: boolean; }; export const DropdownMenuInput = forwardRef< HTMLInputElement, DropdownMenuInputProps >( ( { autoFocus, className, value, placeholder, hotkeyScope = 'dropdown-menu-input', onChange, onClickOutside, onEnter = () => {}, onEscape = () => {}, onShiftTab, onTab, rightComponent, renderInput, error = '', hasError = false, }, ref, ) => { const inputRef = useRef(null); const combinedRef = useCombinedRefs(ref, inputRef); useRegisterInputEvents({ inputRef, inputValue: value, onEnter, onEscape, onClickOutside, onTab, onShiftTab, hotkeyScope, }); return ( <> {renderInput ? ( renderInput({ value, onChange, autoFocus, placeholder, }) ) : ( )} {!!rightComponent && ( {rightComponent} )} {error && {error}} ); }, );