/* eslint-disable jsx-a11y/no-autofocus */ /* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/no-static-element-interactions */ import { clsx } from 'clsx'; import { Component, createRef, ReactNode } from 'react'; import { Input } from '../../inputs/Input'; import { TypeaheadOption, TypeaheadProps } from '../Typeahead'; const DEFAULT_INPUT_MIN_WIDTH = 10; export type TypeaheadInputProps = { typeaheadId: string; value: string; selected: readonly TypeaheadOption[]; dropdownOpen?: boolean; autoComplete: string; onChange: React.ChangeEventHandler; onKeyDown: React.KeyboardEventHandler; onFocus: () => void; onPaste: React.ClipboardEventHandler; renderChip: (chip: TypeaheadOption, index: number) => ReactNode; ariaActivedescendant?: string; } & Pick, 'id' | 'name' | 'autoFocus' | 'multiple' | 'placeholder' | 'maxHeight'>; type TypeaheadInputState = { inputWidth: number; keyboardFocusedOptionIndex: number | null; }; export default class TypeaheadInput extends Component< TypeaheadInputProps, TypeaheadInputState > { inputRef = createRef(); sizerRef = createRef(); constructor(props: TypeaheadInputProps) { super(props); this.state = { inputWidth: DEFAULT_INPUT_MIN_WIDTH, keyboardFocusedOptionIndex: null, }; } componentDidMount() { const { autoFocus } = this.props; if (autoFocus) { // Autofocus after context code executions (e.g open Modal) is completed setTimeout(() => { this.inputRef.current?.focus(); }); } } componentDidUpdate(previousProps: TypeaheadInputProps) { if (previousProps.value !== this.props.value && this.props.multiple) { this.recalculateWidth(); } } recalculateWidth = () => { requestAnimationFrame(() => { this.setState({ inputWidth: Math.max(DEFAULT_INPUT_MIN_WIDTH, this.sizerRef.current?.scrollWidth ?? 0 + 10), }); }); }; renderInput = () => { const { typeaheadId, autoFocus, multiple, name, dropdownOpen, placeholder, selected, value, onChange, onKeyDown, onFocus, onPaste, autoComplete, ariaActivedescendant, // Declare the ariaActivedescendant variable } = this.props; const { inputWidth } = this.state; const hasPlaceholder = !multiple || selected.length === 0; return ( 0 ? { width: inputWidth } : {}} onChange={onChange} onKeyDown={onKeyDown} onClick={onFocus} onFocus={onFocus} onPaste={onPaste} /> ); }; render() { const { multiple, selected, value, maxHeight, renderChip } = this.props; return multiple ? (
{ this.inputRef.current?.focus(); }} >
{selected && selected.map((chip, idx) => renderChip(chip, idx))} {this.renderInput()}
{value}
) : ( this.renderInput() ); } }