adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
13.1k stars 1.14k forks source link

(WIP) Refactor autocomplete logic to use custom events to update virtual focus #7378

Closed LFDanLu closed 1 week ago

LFDanLu commented 1 week ago

Closes

โœ… Pull Request Checklist:

๐Ÿ“ Test Instructions:

๐Ÿงข Your Project:

RSP

rspbot commented 1 week ago

Build successful! ๐ŸŽ‰

rspbot commented 1 week ago
## API Changes ### react-aria-components #### /react-aria-components:Checkbox ```diff Checkbox { aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode | ((CheckboxRenderProps & { defaultChildren: ReactNode | undefined })) => ReactNode className?: string | ((CheckboxRenderProps & { defaultClassName: string | undefined })) => string defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string inputRef?: RefObject isDisabled?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onHoverChange?: (boolean) => void onHoverEnd?: (HoverEvent) => void onHoverStart?: (HoverEvent) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void slot?: string | null style?: CSSProperties | ((CheckboxRenderProps & { defaultStyle: CSSProperties })) => CSSProperties | undefined - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'native' | 'aria' = 'native' value?: string } ``` #### /react-aria-components:CheckboxProps ```diff CheckboxProps { aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode | ((CheckboxRenderProps & { defaultChildren: ReactNode | undefined })) => ReactNode className?: string | ((CheckboxRenderProps & { defaultClassName: string | undefined })) => string defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string inputRef?: RefObject isDisabled?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onHoverChange?: (boolean) => void onHoverEnd?: (HoverEvent) => void onHoverStart?: (HoverEvent) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void slot?: string | null style?: CSSProperties | ((CheckboxRenderProps & { defaultStyle: CSSProperties })) => CSSProperties | undefined - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'native' | 'aria' = 'native' value?: string } ``` #### /react-aria-components:Autocomplete ```diff +Autocomplete { + aria-describedby?: string + aria-details?: string + aria-label?: string + aria-labelledby?: string + autoFocus?: boolean + children?: ReactNode | ((AutocompleteRenderProps & { + defaultChildren: ReactNode | undefined +})) => ReactNode + className?: string | ((AutocompleteRenderProps & { + defaultClassName: string | undefined +})) => string + defaultFilter?: (string, string) => boolean + defaultInputValue?: string + id?: string + inputValue?: string + isDisabled?: boolean + isReadOnly?: boolean + name?: string + onBlur?: (FocusEvent) => void + onFocus?: (FocusEvent) => void + onFocusChange?: (boolean) => void + onInputChange?: (string) => void + onKeyDown?: (KeyboardEvent) => void + onKeyUp?: (KeyboardEvent) => void + slot?: string | null + style?: CSSProperties | ((AutocompleteRenderProps & { + defaultStyle: CSSProperties +})) => CSSProperties | undefined +} ``` ----------------------------------- ### @react-aria/autocomplete #### /@react-aria/autocomplete:useAutocomplete ```diff +useAutocomplete { + props: AriaAutocompleteOptions + state: AutocompleteState + returnVal: undefined +} ``` #### /@react-aria/autocomplete:AriaAutocompleteProps ```diff +AriaAutocompleteProps { + aria-describedby?: string + aria-details?: string + aria-label?: string + aria-labelledby?: string + autoFocus?: boolean + children: ReactNode + defaultInputValue?: string + description?: ReactNode + errorMessage?: ReactNode | (ValidationResult) => ReactNode + id?: string + inputValue?: string + isDisabled?: boolean + isReadOnly?: boolean + label?: ReactNode + name?: string + onBlur?: (FocusEvent) => void + onFocus?: (FocusEvent) => void + onFocusChange?: (boolean) => void + onInputChange?: (string) => void + onKeyDown?: (KeyboardEvent) => void + onKeyUp?: (KeyboardEvent) => void + placeholder?: string +} ``` #### /@react-aria/autocomplete:AriaAutocompleteOptions ```diff +AriaAutocompleteOptions { + aria-describedby?: string + aria-details?: string + aria-label?: string + aria-labelledby?: string + autoFocus?: boolean + collectionRef: RefObject + defaultInputValue?: string + description?: ReactNode + errorMessage?: ReactNode | (ValidationResult) => ReactNode + id?: string + inputRef: RefObject + inputValue?: string + isDisabled?: boolean + isReadOnly?: boolean + label?: ReactNode + name?: string + onBlur?: (FocusEvent) => void + onFocus?: (FocusEvent) => void + onFocusChange?: (boolean) => void + onInputChange?: (string) => void + onKeyDown?: (KeyboardEvent) => void + onKeyUp?: (KeyboardEvent) => void + placeholder?: string +} ``` #### /@react-aria/autocomplete:AutocompleteAria ```diff +AutocompleteAria { + descriptionProps: DOMAttributes + inputProps: InputHTMLAttributes + labelProps: DOMAttributes + menuProps: AriaMenuOptions +} ``` ----------------------------------- ### @react-aria/checkbox #### /@react-aria/checkbox:AriaCheckboxGroupItemProps ```diff AriaCheckboxGroupItemProps { aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode excludeFromTabOrder?: boolean id?: string isDisabled?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value: string } ``` #### /@react-aria/checkbox:AriaCheckboxProps ```diff AriaCheckboxProps { aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string isDisabled?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value?: string } ``` ----------------------------------- ### @react-aria/collections #### /@react-aria/collections:BaseCollection ```diff BaseCollection { addNode: (CollectionNode) => void at: () => Node clone: () => this commit: (Key | null, Key | null, any) => void + filter: ((string) => boolean) => BaseCollection getChildren: (Key) => Iterable> getFirstKey: () => void getItem: (Key) => Node | null getKeyAfter: (Key) => void getKeys: () => void getLastKey: () => void removeNode: (Key) => void size: any undefined: () => void } ``` ----------------------------------- ### @react-aria/menu #### /@react-aria/menu:AriaMenuOptions ```diff AriaMenuOptions { aria-describedby?: string aria-details?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean | FocusStrategy defaultSelectedKeys?: 'all' | Iterable disabledKeys?: Iterable disallowEmptySelection?: boolean id?: string isVirtualized?: boolean items?: Iterable keyboardDelegate?: KeyboardDelegate onAction?: (Key) => void onClose?: () => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void onSelectionChange?: (Selection) => void selectedKeys?: 'all' | Iterable selectionMode?: SelectionMode shouldFocusWrap?: boolean + shouldUseVirtualFocus?: boolean } ``` #### /@react-aria/menu:getItemId ```diff +getItemId { + state: TreeState + itemKey: Key + returnVal: undefined +} ``` #### /@react-aria/menu:menuData ```diff +menuData { + UNTYPED +} ``` ----------------------------------- ### @react-aria/toggle #### /@react-aria/toggle:AriaToggleProps ```diff AriaToggleProps { aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string isDisabled?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value?: string } ``` ----------------------------------- ### @react-spectrum/checkbox #### /@react-spectrum/checkbox:Checkbox ```diff Checkbox { UNSAFE_className?: string UNSAFE_style?: CSSProperties alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'> aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean bottom?: Responsive children?: ReactNode defaultSelected?: boolean end?: Responsive excludeFromTabOrder?: boolean flex?: Responsive flexBasis?: Responsive flexGrow?: Responsive flexShrink?: Responsive gridArea?: Responsive gridColumn?: Responsive gridColumnEnd?: Responsive gridColumnStart?: Responsive gridRow?: Responsive gridRowEnd?: Responsive gridRowStart?: Responsive height?: Responsive id?: string isDisabled?: boolean isEmphasized?: boolean isHidden?: Responsive isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'> left?: Responsive margin?: Responsive marginBottom?: Responsive marginEnd?: Responsive marginStart?: Responsive marginTop?: Responsive marginX?: Responsive marginY?: Responsive maxHeight?: Responsive maxWidth?: Responsive minHeight?: Responsive minWidth?: Responsive name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void order?: Responsive position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'> right?: Responsive start?: Responsive top?: Responsive - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value?: string width?: Responsive zIndex?: Responsive ``` #### /@react-spectrum/checkbox:SpectrumCheckboxProps ```diff SpectrumCheckboxProps { UNSAFE_className?: string UNSAFE_style?: CSSProperties alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'> aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean bottom?: Responsive children?: ReactNode defaultSelected?: boolean end?: Responsive excludeFromTabOrder?: boolean flex?: Responsive flexBasis?: Responsive flexGrow?: Responsive flexShrink?: Responsive gridArea?: Responsive gridColumn?: Responsive gridColumnEnd?: Responsive gridColumnStart?: Responsive gridRow?: Responsive gridRowEnd?: Responsive gridRowStart?: Responsive height?: Responsive id?: string isDisabled?: boolean isEmphasized?: boolean isHidden?: Responsive isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'> left?: Responsive margin?: Responsive marginBottom?: Responsive marginEnd?: Responsive marginStart?: Responsive marginTop?: Responsive marginX?: Responsive marginY?: Responsive maxHeight?: Responsive maxWidth?: Responsive minHeight?: Responsive minWidth?: Responsive name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void order?: Responsive position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'> right?: Responsive start?: Responsive top?: Responsive - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value?: string width?: Responsive zIndex?: Responsive ``` ----------------------------------- ### @react-spectrum/s2 #### /@react-spectrum/s2:Checkbox ```diff Checkbox { UNSAFE_className?: string UNSAFE_style?: CSSProperties aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string inputRef?: RefObject isDisabled?: boolean isEmphasized?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void size?: 'S' | 'M' | 'L' | 'XL' = 'M' slot?: string | null styles?: StylesProp - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'native' | 'aria' = 'native' value?: string } ``` #### /@react-spectrum/s2:CheckboxProps ```diff CheckboxProps { UNSAFE_className?: string UNSAFE_style?: CSSProperties aria-controls?: string aria-describedby?: string aria-details?: string aria-errormessage?: string aria-label?: string aria-labelledby?: string autoFocus?: boolean children?: ReactNode defaultSelected?: boolean excludeFromTabOrder?: boolean id?: string inputRef?: RefObject isDisabled?: boolean isEmphasized?: boolean isIndeterminate?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean name?: string onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void size?: 'S' | 'M' | 'L' | 'XL' = 'M' slot?: string | null styles?: StylesProp - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'native' | 'aria' = 'native' value?: string } ``` ----------------------------------- ### @react-stately/toggle #### /@react-stately/toggle:ToggleProps ```diff ToggleProps { autoFocus?: boolean children?: ReactNode defaultSelected?: boolean isDisabled?: boolean isInvalid?: boolean isReadOnly?: boolean isRequired?: boolean isSelected?: boolean onBlur?: (FocusEvent) => void onChange?: (boolean) => void onFocus?: (FocusEvent) => void onFocusChange?: (boolean) => void onKeyDown?: (KeyboardEvent) => void onKeyUp?: (KeyboardEvent) => void - validate?: (boolean) => ValidationError | boolean | null | undefined + validate?: (T) => ValidationError | boolean | null | undefined validationBehavior?: 'aria' | 'native' = 'aria' value?: string } ``` ----------------------------------- ### @react-stately/autocomplete #### /@react-stately/autocomplete:useAutocompleteState ```diff +useAutocompleteState { + props: AutocompleteStateOptions + returnVal: undefined +} ``` #### /@react-stately/autocomplete:AutocompleteProps ```diff +AutocompleteProps { + autoFocus?: boolean + defaultInputValue?: string + description?: ReactNode + errorMessage?: ReactNode | (ValidationResult) => ReactNode + inputValue?: string + isDisabled?: boolean + isReadOnly?: boolean + label?: ReactNode + onBlur?: (FocusEvent) => void + onFocus?: (FocusEvent) => void + onFocusChange?: (boolean) => void + onInputChange?: (string) => void + onKeyDown?: (KeyboardEvent) => void + onKeyUp?: (KeyboardEvent) => void + placeholder?: string +} ``` #### /@react-stately/autocomplete:AutocompleteStateOptions ```diff +AutocompleteStateOptions { + autoFocus?: boolean + defaultInputValue?: string + description?: ReactNode + errorMessage?: ReactNode | (ValidationResult) => ReactNode + inputValue?: string + isDisabled?: boolean + isReadOnly?: boolean + label?: ReactNode + onBlur?: (FocusEvent) => void + onFocus?: (FocusEvent) => void + onFocusChange?: (boolean) => void + onInputChange?: (string) => void + onKeyDown?: (KeyboardEvent) => void + onKeyUp?: (KeyboardEvent) => void + placeholder?: string +} ``` #### /@react-stately/autocomplete:AutocompleteState ```diff +AutocompleteState { + focusedNodeId: string | null + inputValue: string + setFocusedNodeId: (string | null) => void + setInputValue: (string) => void +} ``` -----------------------------------