import * as React from 'react'; import { TextControl, tailwind } from '@tesseract-design/web-base'; import { useFallbackId } from '@modal-sh/react-utils'; const { tw } = tailwind; const ComboBoxDerivedElementComponent = 'input' as const; /** * Derived HTML element of the {@link ComboBox} component. */ export type ComboBoxDerivedElement = HTMLElementTagNameMap[ typeof ComboBoxDerivedElementComponent ]; /** * Props of the {@link ComboBox} component. */ export interface ComboBoxProps extends Omit, 'size' | 'type' | 'label' | 'list' | 'inputMode'> { /** * Short textual description indicating the nature of the component's value. */ label?: React.ReactNode, /** * Short textual description as guidelines for valid input values. */ hint?: React.ReactNode, /** * Size of the component. */ size?: TextControl.Size, /** * Additional description, usually graphical, indicating the nature of the component's value. */ indicator?: React.ReactNode, /** * Should the component display a border? */ border?: boolean, /** * Should the component occupy the whole width of its parent? */ block?: boolean, /** * Type of the component value. */ type?: TextControl.InputType, /** * Style of the component. */ variant?: TextControl.Variant, /** * Is the label hidden? */ hiddenLabel?: boolean, /** * Input mode of the component. */ inputMode?: TextControl.InputMode, /** * Visual length of the input. */ length?: number, } /** * Component for inputting textual values. * * This component supports multiline input and adjusts its layout accordingly. */ export const ComboBox = React.forwardRef(( { label, hint, indicator, size = 'medium' as const, border = false as const, block = false as const, type = 'text' as const, variant = 'default' as const, hiddenLabel = false as const, className, children, inputMode = 'text' as const, id: idProp, style, length, ...etcProps }: ComboBoxProps, forwardedRef, ) => { const labelId = React.useId(); const datalistId = React.useId(); const id = useFallbackId(idProp); let resultInputMode = inputMode as React.HTMLProps['inputMode']; if (type === 'text' && resultInputMode === 'search') { resultInputMode = 'text'; } else if (type === 'search' && resultInputMode === 'text') { resultInputMode = 'search'; } return ( <> {children}
{label && ( <> {' '} )} {hint && (
{hint}
)} {indicator && (
{indicator}
)} {border && ( )}
); }); ComboBox.displayName = 'ComboBox' as const; ComboBox.defaultProps = { label: undefined, hint: undefined, indicator: undefined, size: 'medium' as const, border: false as const, block: false as const, type: 'text' as const, variant: 'default' as const, hiddenLabel: false as const, inputMode: 'text' as const, length: undefined, };