@react-aria/autocomplete 3.0.0-nightly-e7053dd8f-250108 → 3.0.0-nightly-e4497fdb6-250110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types.d.ts.map +1 -1
- package/dist/useAutocomplete.main.js +8 -5
- package/dist/useAutocomplete.main.js.map +1 -1
- package/dist/useAutocomplete.mjs +8 -5
- package/dist/useAutocomplete.module.js +8 -5
- package/dist/useAutocomplete.module.js.map +1 -1
- package/package.json +12 -12
- package/src/useAutocomplete.ts +8 -5
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;AAsBA,wCAAwC,CAAC,CAAE,SAAQ,gBAAgB;IACjE,mCAAmC;IACnC,UAAU,EAAE,aAAa,CAAC;IAC1B,0CAA0C;IAC1C,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,6EAA6E;IAC7E,YAAY,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACpC,iDAAiD;IACjD,gBAAgB,EAAE,eAAe,CAAC;IAClC,qEAAqE;IACrE,gBAAgB,EAAE,aAAa,CAAC;IAChC,uEAAuE;IACvE,iBAAiB,EAAE,aAAa,CAAA;CACjC;AAED,+CAA+C,CAAC,CAAE,SAAQ,4BAA4B,CAAC,CAAC;IACtF,qCAAqC;IACrC,QAAQ,EAAE,UAAU,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC7C,wCAAwC;IACxC,UAAU,EAAE,UAAU,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7C,gCAAgC;IAChC,UAAU,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1C,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED;;;;;GAKG;AACH,sCAAsC,CAAC,EAAE,KAAK,EAAE,8BAA8B,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAwEpI;AC/GD,kCAAmC,SAAQ,QAAQ,EAAE,iBAAiB;IACpE,+FAA+F;IAC/F,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qCAAqC;IACrC,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AACD,sCAAuC,SAAQ,iBAAiB;IAC9D;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAA;CAC5D;AAED,wCAAyC,SAAQ,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC;IACtF,kDAAkD;IAClD,aAAa,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,6CAA6C;IAC7C,QAAQ,EAAE,UAAU,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAC7C;AAED;IACE,gDAAgD;IAChD,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,kGAAkG;IAClG,eAAe,EAAE,iBAAiB,CAAC;IACnC,+CAA+C;IAC/C,aAAa,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,+GAA+G;IAC/G,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAA;CAC9C;AAED;;;;;GAKG;AACH,yCAAyC,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,
|
|
1
|
+
{"mappings":";;;;;;;AAsBA,wCAAwC,CAAC,CAAE,SAAQ,gBAAgB;IACjE,mCAAmC;IACnC,UAAU,EAAE,aAAa,CAAC;IAC1B,0CAA0C;IAC1C,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,6EAA6E;IAC7E,YAAY,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACpC,iDAAiD;IACjD,gBAAgB,EAAE,eAAe,CAAC;IAClC,qEAAqE;IACrE,gBAAgB,EAAE,aAAa,CAAC;IAChC,uEAAuE;IACvE,iBAAiB,EAAE,aAAa,CAAA;CACjC;AAED,+CAA+C,CAAC,CAAE,SAAQ,4BAA4B,CAAC,CAAC;IACtF,qCAAqC;IACrC,QAAQ,EAAE,UAAU,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC7C,wCAAwC;IACxC,UAAU,EAAE,UAAU,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7C,gCAAgC;IAChC,UAAU,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1C,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED;;;;;GAKG;AACH,sCAAsC,CAAC,EAAE,KAAK,EAAE,8BAA8B,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAwEpI;AC/GD,kCAAmC,SAAQ,QAAQ,EAAE,iBAAiB;IACpE,+FAA+F;IAC/F,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qCAAqC;IACrC,iBAAiB,EAAE,OAAO,CAAA;CAC3B;AACD,sCAAuC,SAAQ,iBAAiB;IAC9D;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAA;CAC5D;AAED,wCAAyC,SAAQ,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC;IACtF,kDAAkD;IAClD,aAAa,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,6CAA6C;IAC7C,QAAQ,EAAE,UAAU,gBAAgB,GAAG,IAAI,CAAC,CAAA;CAC7C;AAED;IACE,gDAAgD;IAChD,UAAU,EAAE,oBAAoB,gBAAgB,CAAC,CAAC;IAClD,kGAAkG;IAClG,eAAe,EAAE,iBAAiB,CAAC;IACnC,+CAA+C;IAC/C,aAAa,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,+GAA+G;IAC/G,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAA;CAC9C;AAED;;;;;GAKG;AACH,yCAAyC,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CA2OnH;ACvRD,YAAY,EAAC,2BAA2B,EAAC,MAAM,2BAA2B,CAAC","sources":["packages/@react-aria/autocomplete/src/packages/@react-aria/autocomplete/src/useSearchAutocomplete.ts","packages/@react-aria/autocomplete/src/packages/@react-aria/autocomplete/src/useAutocomplete.ts","packages/@react-aria/autocomplete/src/packages/@react-aria/autocomplete/src/index.ts","packages/@react-aria/autocomplete/src/index.ts"],"sourcesContent":[null,null,null,"/*\n * Copyright 2021 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useSearchAutocomplete} from './useSearchAutocomplete';\nexport {UNSTABLE_useAutocomplete} from './useAutocomplete';\n\nexport type {AriaSearchAutocompleteOptions, SearchAutocompleteAria} from './useSearchAutocomplete';\nexport type {AriaSearchAutocompleteProps} from '@react-types/autocomplete';\nexport type {AriaAutocompleteProps, AriaAutocompleteOptions, AutocompleteAria, CollectionOptions} from './useAutocomplete';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
|
@@ -161,7 +161,7 @@ function $d43aec1bf2be84e8$export$2d6947d4992da88e(props, state) {
|
|
|
161
161
|
item === null || item === void 0 ? void 0 : item.dispatchEvent(new KeyboardEvent(e.nativeEvent.type, e.nativeEvent));
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
|
-
let
|
|
164
|
+
let onKeyUpCapture = (0, $4yz2I$reactariautils.useEffectEvent)((e)=>{
|
|
165
165
|
// Dispatch simulated key up events for things like triggering links in listbox
|
|
166
166
|
// Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair
|
|
167
167
|
// is detected by usePress instead of the original keyup originating from the input
|
|
@@ -176,13 +176,13 @@ function $d43aec1bf2be84e8$export$2d6947d4992da88e(props, state) {
|
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
(0, $4yz2I$react.useEffect)(()=>{
|
|
179
|
-
document.addEventListener('keyup',
|
|
179
|
+
document.addEventListener('keyup', onKeyUpCapture, true);
|
|
180
180
|
return ()=>{
|
|
181
|
-
document.removeEventListener('keyup',
|
|
181
|
+
document.removeEventListener('keyup', onKeyUpCapture, true);
|
|
182
182
|
};
|
|
183
183
|
}, [
|
|
184
184
|
inputRef,
|
|
185
|
-
|
|
185
|
+
onKeyUpCapture
|
|
186
186
|
]);
|
|
187
187
|
let { keyboardProps: keyboardProps } = (0, $4yz2I$reactariainteractions.useKeyboard)({
|
|
188
188
|
onKeyDown: onKeyDown
|
|
@@ -219,7 +219,10 @@ function $d43aec1bf2be84e8$export$2d6947d4992da88e(props, state) {
|
|
|
219
219
|
collectionProps: (0, $4yz2I$reactariautils.mergeProps)(collectionProps, {
|
|
220
220
|
// TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?
|
|
221
221
|
shouldUseVirtualFocus: true,
|
|
222
|
-
disallowTypeAhead: true
|
|
222
|
+
disallowTypeAhead: true,
|
|
223
|
+
// Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally
|
|
224
|
+
// they've been handled by the input already
|
|
225
|
+
onKeyDown: (e)=>e.stopPropagation()
|
|
223
226
|
}),
|
|
224
227
|
collectionRef: mergedCollectionRef,
|
|
225
228
|
filterFn: filter != null ? filterFn : undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@react-aria/autocomplete/src/useAutocomplete.ts"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, BaseEvent, DOMProps, RefObject} from '@react-types/shared';\nimport {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete';\nimport {ChangeEvent, InputHTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect, useMemo, useRef} from 'react';\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, isCtrlKeyPressed, mergeProps, mergeRefs, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useId, useLabels, useObjectRef} from '@react-aria/utils';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useKeyboard} from '@react-aria/interactions';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\nexport interface CollectionOptions extends DOMProps, AriaLabelingProps {\n /** Whether the collection items should use virtual focus instead of being focused directly. */\n shouldUseVirtualFocus: boolean,\n /** Whether typeahead is disabled. */\n disallowTypeAhead: boolean\n}\nexport interface AriaAutocompleteProps extends AutocompleteProps {\n /**\n * An optional filter function used to determine if a option should be included in the autocomplete list.\n * Include this if the items you are providing to your wrapped collection aren't filtered by default.\n */\n filter?: (textValue: string, inputValue: string) => boolean\n}\n\nexport interface AriaAutocompleteOptions extends Omit<AriaAutocompleteProps, 'children'> {\n /** The ref for the wrapped collection element. */\n collectionRef: RefObject<HTMLElement | null>,\n /** The ref for the wrapped input element. */\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nexport interface AutocompleteAria {\n /** Props for the autocomplete input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */\n collectionProps: CollectionOptions,\n /** Ref to attach to the wrapped collection. */\n collectionRef: RefObject<HTMLElement | null>,\n /** A filter function that returns if the provided collection node should be filtered out of the collection. */\n filterFn?: (nodeTextValue: string) => boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for a autocomplete component.\n * A autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.\n * @param props - Props for the autocomplete.\n * @param state - State for the autocomplete, as returned by `useAutocompleteState`.\n */\nexport function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state: AutocompleteState): AutocompleteAria {\n let {\n collectionRef,\n filter,\n inputRef\n } = props;\n\n let collectionId = useId();\n let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n let delayNextActiveDescendant = useRef(false);\n let queuedActiveDescendant = useRef(null);\n let lastCollectionNode = useRef<HTMLElement>(null);\n\n let updateActiveDescendant = useEffectEvent((e) => {\n let {target} = e;\n if (queuedActiveDescendant.current === target.id) {\n return;\n }\n\n clearTimeout(timeout.current);\n e.stopPropagation();\n\n if (target !== collectionRef.current) {\n if (delayNextActiveDescendant.current) {\n queuedActiveDescendant.current = target.id;\n timeout.current = setTimeout(() => {\n state.setFocusedNodeId(target.id);\n queuedActiveDescendant.current = null;\n }, 500);\n } else {\n state.setFocusedNodeId(target.id);\n }\n } else {\n state.setFocusedNodeId(null);\n }\n\n delayNextActiveDescendant.current = false;\n });\n\n let callbackRef = useCallback((collectionNode) => {\n if (collectionNode != null) {\n // When typing forward, we want to delay the setting of active descendant to not interrupt the native screen reader announcement\n // of the letter you just typed. If we recieve another UPDATE_ACTIVEDESCENDANT call then we clear the queued update\n // We track lastCollectionNode to do proper cleanup since callbackRefs just pass null when unmounting. This also handles\n // React 19's extra call of the callback ref in strict mode\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n lastCollectionNode.current = collectionNode;\n collectionNode.addEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n } else {\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n }\n }, [updateActiveDescendant]);\n\n // Make sure to memo so that React doesn't keep registering a new event listeners on every rerender of the wrapped collection\n let mergedCollectionRef = useObjectRef(useMemo(() => mergeRefs(collectionRef, callbackRef), [collectionRef, callbackRef]));\n\n let focusFirstItem = useEffectEvent(() => {\n delayNextActiveDescendant.current = true;\n collectionRef.current?.dispatchEvent(\n new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true,\n detail: {\n focusStrategy: 'first'\n }\n })\n );\n });\n\n let clearVirtualFocus = useEffectEvent(() => {\n state.setFocusedNodeId(null);\n let clearFocusEvent = new CustomEvent(CLEAR_FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n clearTimeout(timeout.current);\n delayNextActiveDescendant.current = false;\n collectionRef.current?.dispatchEvent(clearFocusEvent);\n });\n\n // TODO: update to see if we can tell what kind of event (paste vs backspace vs typing) is happening instead\n let onChange = (e: ChangeEvent<HTMLInputElement>) => {\n // Tell wrapped collection to focus the first element in the list when typing forward and to clear focused key when deleting text\n // for screen reader announcements\n if (state.inputValue !== e.target.value && state.inputValue.length <= e.target.value.length) {\n focusFirstItem();\n } else {\n clearVirtualFocus();\n }\n\n state.setInputValue(e.target.value);\n };\n\n // For textfield specific keydown operations\n let onKeyDown = (e: BaseEvent<ReactKeyboardEvent<any>>) => {\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'a':\n if (isCtrlKeyPressed(e)) {\n return;\n }\n break;\n case 'Escape':\n // Early return for Escape here so it doesn't leak the Escape event from the simulated collection event below and\n // close the dialog prematurely. Ideally that should be up to the discretion of the input element hence the check\n // for isPropagationStopped\n // Also set the inputValue to '' to cover Firefox case where Esc doesn't actually clear searchfields. Normally we already\n // handle this in useSearchField, but we are directly setting the inputValue on the input element in RAC Autocomplete instead of\n // passing it to the SearchField via props. This means that a controlled value set on the Autocomplete isn't synced up with the\n // SearchField until the user makes a change to the field's value via typing\n if (e.isPropagationStopped()) {\n state.setInputValue('');\n return;\n }\n break;\n case ' ':\n // Space shouldn't trigger onAction so early return.\n\n return;\n case 'Home':\n case 'End':\n case 'PageDown':\n case 'PageUp':\n case 'ArrowUp':\n case 'ArrowDown': {\n if ((e.key === 'Home' || e.key === 'End') && state.focusedNodeId == null && e.shiftKey) {\n return;\n }\n\n // Prevent these keys from moving the text cursor in the input\n e.preventDefault();\n // Move virtual focus into the wrapped collection\n let focusCollection = new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n\n collectionRef.current?.dispatchEvent(focusCollection);\n break;\n }\n case 'ArrowLeft':\n case 'ArrowRight':\n // TODO: will need to special case this so it doesn't clear the focused key if we are currently\n // focused on a submenutrigger? May not need to since focus would\n // But what about wrapped grids where ArrowLeft and ArrowRight should navigate left/right\n clearVirtualFocus();\n break;\n }\n\n // Emulate the keyboard events that happen in the input field in the wrapped collection. This is for triggering things like onAction via Enter\n // or moving focus from one item to another\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n }\n };\n\n let onKeyUp = useEffectEvent((e) => {\n // Dispatch simulated key up events for things like triggering links in listbox\n // Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair\n // is detected by usePress instead of the original keyup originating from the input\n if (e.target === inputRef.current) {\n e.stopImmediatePropagation();\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n }\n }\n });\n\n useEffect(() => {\n document.addEventListener('keyup', onKeyUp, true);\n return () => {\n document.removeEventListener('keyup', onKeyUp, true);\n };\n }, [inputRef, onKeyUp]);\n\n let {keyboardProps} = useKeyboard({onKeyDown});\n\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/autocomplete');\n let collectionProps = useLabels({\n id: collectionId,\n 'aria-label': stringFormatter.format('collectionLabel')\n });\n\n let filterFn = useCallback((nodeTextValue: string) => {\n if (filter) {\n return filter(nodeTextValue, state.inputValue);\n }\n\n return true;\n }, [state.inputValue, filter]);\n\n return {\n inputProps: {\n value: state.inputValue,\n onChange,\n ...keyboardProps,\n autoComplete: 'off',\n 'aria-haspopup': 'listbox',\n 'aria-controls': collectionId,\n // TODO: readd proper logic for completionMode = complete (aria-autocomplete: both)\n 'aria-autocomplete': 'list',\n 'aria-activedescendant': state.focusedNodeId ?? undefined,\n // This disable's iOS's autocorrect suggestions, since the autocomplete provides its own suggestions.\n autoCorrect: 'off',\n // This disable's the macOS Safari spell check auto corrections.\n spellCheck: 'false'\n },\n collectionProps: mergeProps(collectionProps, {\n // TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?\n shouldUseVirtualFocus: true,\n disallowTypeAhead: true\n }),\n collectionRef: mergedCollectionRef,\n filterFn: filter != null ? filterFn : undefined\n };\n}\n"],"names":[],"version":3,"file":"useAutocomplete.main.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/autocomplete/src/useAutocomplete.ts"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, BaseEvent, DOMProps, RefObject} from '@react-types/shared';\nimport {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete';\nimport {ChangeEvent, InputHTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect, useMemo, useRef} from 'react';\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, isCtrlKeyPressed, mergeProps, mergeRefs, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useId, useLabels, useObjectRef} from '@react-aria/utils';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useKeyboard} from '@react-aria/interactions';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\nexport interface CollectionOptions extends DOMProps, AriaLabelingProps {\n /** Whether the collection items should use virtual focus instead of being focused directly. */\n shouldUseVirtualFocus: boolean,\n /** Whether typeahead is disabled. */\n disallowTypeAhead: boolean\n}\nexport interface AriaAutocompleteProps extends AutocompleteProps {\n /**\n * An optional filter function used to determine if a option should be included in the autocomplete list.\n * Include this if the items you are providing to your wrapped collection aren't filtered by default.\n */\n filter?: (textValue: string, inputValue: string) => boolean\n}\n\nexport interface AriaAutocompleteOptions extends Omit<AriaAutocompleteProps, 'children'> {\n /** The ref for the wrapped collection element. */\n collectionRef: RefObject<HTMLElement | null>,\n /** The ref for the wrapped input element. */\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nexport interface AutocompleteAria {\n /** Props for the autocomplete input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */\n collectionProps: CollectionOptions,\n /** Ref to attach to the wrapped collection. */\n collectionRef: RefObject<HTMLElement | null>,\n /** A filter function that returns if the provided collection node should be filtered out of the collection. */\n filterFn?: (nodeTextValue: string) => boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for a autocomplete component.\n * A autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.\n * @param props - Props for the autocomplete.\n * @param state - State for the autocomplete, as returned by `useAutocompleteState`.\n */\nexport function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state: AutocompleteState): AutocompleteAria {\n let {\n collectionRef,\n filter,\n inputRef\n } = props;\n\n let collectionId = useId();\n let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n let delayNextActiveDescendant = useRef(false);\n let queuedActiveDescendant = useRef(null);\n let lastCollectionNode = useRef<HTMLElement>(null);\n\n let updateActiveDescendant = useEffectEvent((e) => {\n let {target} = e;\n if (queuedActiveDescendant.current === target.id) {\n return;\n }\n\n clearTimeout(timeout.current);\n e.stopPropagation();\n\n if (target !== collectionRef.current) {\n if (delayNextActiveDescendant.current) {\n queuedActiveDescendant.current = target.id;\n timeout.current = setTimeout(() => {\n state.setFocusedNodeId(target.id);\n queuedActiveDescendant.current = null;\n }, 500);\n } else {\n state.setFocusedNodeId(target.id);\n }\n } else {\n state.setFocusedNodeId(null);\n }\n\n delayNextActiveDescendant.current = false;\n });\n\n let callbackRef = useCallback((collectionNode) => {\n if (collectionNode != null) {\n // When typing forward, we want to delay the setting of active descendant to not interrupt the native screen reader announcement\n // of the letter you just typed. If we recieve another UPDATE_ACTIVEDESCENDANT call then we clear the queued update\n // We track lastCollectionNode to do proper cleanup since callbackRefs just pass null when unmounting. This also handles\n // React 19's extra call of the callback ref in strict mode\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n lastCollectionNode.current = collectionNode;\n collectionNode.addEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n } else {\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n }\n }, [updateActiveDescendant]);\n\n // Make sure to memo so that React doesn't keep registering a new event listeners on every rerender of the wrapped collection\n let mergedCollectionRef = useObjectRef(useMemo(() => mergeRefs(collectionRef, callbackRef), [collectionRef, callbackRef]));\n\n let focusFirstItem = useEffectEvent(() => {\n delayNextActiveDescendant.current = true;\n collectionRef.current?.dispatchEvent(\n new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true,\n detail: {\n focusStrategy: 'first'\n }\n })\n );\n });\n\n let clearVirtualFocus = useEffectEvent(() => {\n state.setFocusedNodeId(null);\n let clearFocusEvent = new CustomEvent(CLEAR_FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n clearTimeout(timeout.current);\n delayNextActiveDescendant.current = false;\n collectionRef.current?.dispatchEvent(clearFocusEvent);\n });\n\n // TODO: update to see if we can tell what kind of event (paste vs backspace vs typing) is happening instead\n let onChange = (e: ChangeEvent<HTMLInputElement>) => {\n // Tell wrapped collection to focus the first element in the list when typing forward and to clear focused key when deleting text\n // for screen reader announcements\n if (state.inputValue !== e.target.value && state.inputValue.length <= e.target.value.length) {\n focusFirstItem();\n } else {\n clearVirtualFocus();\n }\n\n state.setInputValue(e.target.value);\n };\n\n // For textfield specific keydown operations\n let onKeyDown = (e: BaseEvent<ReactKeyboardEvent<any>>) => {\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'a':\n if (isCtrlKeyPressed(e)) {\n return;\n }\n break;\n case 'Escape':\n // Early return for Escape here so it doesn't leak the Escape event from the simulated collection event below and\n // close the dialog prematurely. Ideally that should be up to the discretion of the input element hence the check\n // for isPropagationStopped\n // Also set the inputValue to '' to cover Firefox case where Esc doesn't actually clear searchfields. Normally we already\n // handle this in useSearchField, but we are directly setting the inputValue on the input element in RAC Autocomplete instead of\n // passing it to the SearchField via props. This means that a controlled value set on the Autocomplete isn't synced up with the\n // SearchField until the user makes a change to the field's value via typing\n if (e.isPropagationStopped()) {\n state.setInputValue('');\n return;\n }\n break;\n case ' ':\n // Space shouldn't trigger onAction so early return.\n\n return;\n case 'Home':\n case 'End':\n case 'PageDown':\n case 'PageUp':\n case 'ArrowUp':\n case 'ArrowDown': {\n if ((e.key === 'Home' || e.key === 'End') && state.focusedNodeId == null && e.shiftKey) {\n return;\n }\n\n // Prevent these keys from moving the text cursor in the input\n e.preventDefault();\n // Move virtual focus into the wrapped collection\n let focusCollection = new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n\n collectionRef.current?.dispatchEvent(focusCollection);\n break;\n }\n case 'ArrowLeft':\n case 'ArrowRight':\n // TODO: will need to special case this so it doesn't clear the focused key if we are currently\n // focused on a submenutrigger? May not need to since focus would\n // But what about wrapped grids where ArrowLeft and ArrowRight should navigate left/right\n clearVirtualFocus();\n break;\n }\n\n // Emulate the keyboard events that happen in the input field in the wrapped collection. This is for triggering things like onAction via Enter\n // or moving focus from one item to another\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n }\n };\n\n let onKeyUpCapture = useEffectEvent((e) => {\n // Dispatch simulated key up events for things like triggering links in listbox\n // Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair\n // is detected by usePress instead of the original keyup originating from the input\n if (e.target === inputRef.current) {\n e.stopImmediatePropagation();\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n }\n }\n });\n\n useEffect(() => {\n document.addEventListener('keyup', onKeyUpCapture, true);\n return () => {\n document.removeEventListener('keyup', onKeyUpCapture, true);\n };\n }, [inputRef, onKeyUpCapture]);\n\n let {keyboardProps} = useKeyboard({onKeyDown});\n\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/autocomplete');\n let collectionProps = useLabels({\n id: collectionId,\n 'aria-label': stringFormatter.format('collectionLabel')\n });\n\n let filterFn = useCallback((nodeTextValue: string) => {\n if (filter) {\n return filter(nodeTextValue, state.inputValue);\n }\n\n return true;\n }, [state.inputValue, filter]);\n\n return {\n inputProps: {\n value: state.inputValue,\n onChange,\n ...keyboardProps,\n autoComplete: 'off',\n 'aria-haspopup': 'listbox',\n 'aria-controls': collectionId,\n // TODO: readd proper logic for completionMode = complete (aria-autocomplete: both)\n 'aria-autocomplete': 'list',\n 'aria-activedescendant': state.focusedNodeId ?? undefined,\n // This disable's iOS's autocorrect suggestions, since the autocomplete provides its own suggestions.\n autoCorrect: 'off',\n // This disable's the macOS Safari spell check auto corrections.\n spellCheck: 'false'\n },\n collectionProps: mergeProps(collectionProps, {\n // TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?\n shouldUseVirtualFocus: true,\n disallowTypeAhead: true,\n // Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally\n // they've been handled by the input already\n onKeyDown: (e) => e.stopPropagation()\n }),\n collectionRef: mergedCollectionRef,\n filterFn: filter != null ? filterFn : undefined\n };\n}\n"],"names":[],"version":3,"file":"useAutocomplete.main.js.map"}
|
package/dist/useAutocomplete.mjs
CHANGED
|
@@ -155,7 +155,7 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
155
155
|
item === null || item === void 0 ? void 0 : item.dispatchEvent(new KeyboardEvent(e.nativeEvent.type, e.nativeEvent));
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
|
-
let
|
|
158
|
+
let onKeyUpCapture = (0, $4ELxY$useEffectEvent)((e)=>{
|
|
159
159
|
// Dispatch simulated key up events for things like triggering links in listbox
|
|
160
160
|
// Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair
|
|
161
161
|
// is detected by usePress instead of the original keyup originating from the input
|
|
@@ -170,13 +170,13 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
172
|
(0, $4ELxY$useEffect)(()=>{
|
|
173
|
-
document.addEventListener('keyup',
|
|
173
|
+
document.addEventListener('keyup', onKeyUpCapture, true);
|
|
174
174
|
return ()=>{
|
|
175
|
-
document.removeEventListener('keyup',
|
|
175
|
+
document.removeEventListener('keyup', onKeyUpCapture, true);
|
|
176
176
|
};
|
|
177
177
|
}, [
|
|
178
178
|
inputRef,
|
|
179
|
-
|
|
179
|
+
onKeyUpCapture
|
|
180
180
|
]);
|
|
181
181
|
let { keyboardProps: keyboardProps } = (0, $4ELxY$useKeyboard)({
|
|
182
182
|
onKeyDown: onKeyDown
|
|
@@ -213,7 +213,10 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
213
213
|
collectionProps: (0, $4ELxY$mergeProps)(collectionProps, {
|
|
214
214
|
// TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?
|
|
215
215
|
shouldUseVirtualFocus: true,
|
|
216
|
-
disallowTypeAhead: true
|
|
216
|
+
disallowTypeAhead: true,
|
|
217
|
+
// Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally
|
|
218
|
+
// they've been handled by the input already
|
|
219
|
+
onKeyDown: (e)=>e.stopPropagation()
|
|
217
220
|
}),
|
|
218
221
|
collectionRef: mergedCollectionRef,
|
|
219
222
|
filterFn: filter != null ? filterFn : undefined
|
|
@@ -155,7 +155,7 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
155
155
|
item === null || item === void 0 ? void 0 : item.dispatchEvent(new KeyboardEvent(e.nativeEvent.type, e.nativeEvent));
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
|
-
let
|
|
158
|
+
let onKeyUpCapture = (0, $4ELxY$useEffectEvent)((e)=>{
|
|
159
159
|
// Dispatch simulated key up events for things like triggering links in listbox
|
|
160
160
|
// Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair
|
|
161
161
|
// is detected by usePress instead of the original keyup originating from the input
|
|
@@ -170,13 +170,13 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
172
|
(0, $4ELxY$useEffect)(()=>{
|
|
173
|
-
document.addEventListener('keyup',
|
|
173
|
+
document.addEventListener('keyup', onKeyUpCapture, true);
|
|
174
174
|
return ()=>{
|
|
175
|
-
document.removeEventListener('keyup',
|
|
175
|
+
document.removeEventListener('keyup', onKeyUpCapture, true);
|
|
176
176
|
};
|
|
177
177
|
}, [
|
|
178
178
|
inputRef,
|
|
179
|
-
|
|
179
|
+
onKeyUpCapture
|
|
180
180
|
]);
|
|
181
181
|
let { keyboardProps: keyboardProps } = (0, $4ELxY$useKeyboard)({
|
|
182
182
|
onKeyDown: onKeyDown
|
|
@@ -213,7 +213,10 @@ function $48f6ba390f8c5b59$export$2d6947d4992da88e(props, state) {
|
|
|
213
213
|
collectionProps: (0, $4ELxY$mergeProps)(collectionProps, {
|
|
214
214
|
// TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?
|
|
215
215
|
shouldUseVirtualFocus: true,
|
|
216
|
-
disallowTypeAhead: true
|
|
216
|
+
disallowTypeAhead: true,
|
|
217
|
+
// Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally
|
|
218
|
+
// they've been handled by the input already
|
|
219
|
+
onKeyDown: (e)=>e.stopPropagation()
|
|
217
220
|
}),
|
|
218
221
|
collectionRef: mergedCollectionRef,
|
|
219
222
|
filterFn: filter != null ? filterFn : undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;AAiDM,SAAS,0CAAyB,KAA8B,EAAE,KAAwB;IAC/F,IAAI,iBACF,aAAa,UACb,MAAM,YACN,QAAQ,EACT,GAAG;IAEJ,IAAI,eAAe,CAAA,GAAA,YAAI;IACvB,IAAI,UAAU,CAAA,GAAA,aAAK,EAA6C;IAChE,IAAI,4BAA4B,CAAA,GAAA,aAAK,EAAE;IACvC,IAAI,yBAAyB,CAAA,GAAA,aAAK,EAAE;IACpC,IAAI,qBAAqB,CAAA,GAAA,aAAK,EAAe;IAE7C,IAAI,yBAAyB,CAAA,GAAA,qBAAa,EAAE,CAAC;QAC3C,IAAI,UAAC,MAAM,EAAC,GAAG;QACf,IAAI,uBAAuB,OAAO,KAAK,OAAO,EAAE,EAC9C;QAGF,aAAa,QAAQ,OAAO;QAC5B,EAAE,eAAe;QAEjB,IAAI,WAAW,cAAc,OAAO;YAClC,IAAI,0BAA0B,OAAO,EAAE;gBACrC,uBAAuB,OAAO,GAAG,OAAO,EAAE;gBAC1C,QAAQ,OAAO,GAAG,WAAW;oBAC3B,MAAM,gBAAgB,CAAC,OAAO,EAAE;oBAChC,uBAAuB,OAAO,GAAG;gBACnC,GAAG;YACL,OACE,MAAM,gBAAgB,CAAC,OAAO,EAAE;eAGlC,MAAM,gBAAgB,CAAC;QAGzB,0BAA0B,OAAO,GAAG;IACtC;IAEA,IAAI,cAAc,CAAA,GAAA,kBAAU,EAAE,CAAC;YAU3B;QATF,IAAI,kBAAkB,MAAM;gBAC1B,gIAAgI;YAChI,mHAAmH;YACnH,wHAAwH;YACxH,2DAA2D;YAC3D;aAAA,+BAAA,mBAAmB,OAAO,cAA1B,mDAAA,6BAA4B,mBAAmB,CAAC,CAAA,GAAA,8BAAsB,GAAG;YACzE,mBAAmB,OAAO,GAAG;YAC7B,eAAe,gBAAgB,CAAC,CAAA,GAAA,8BAAsB,GAAG;QAC3D,QACE,8BAAA,mBAAmB,OAAO,cAA1B,kDAAA,4BAA4B,mBAAmB,CAAC,CAAA,GAAA,8BAAsB,GAAG;IAE7E,GAAG;QAAC;KAAuB;IAE3B,6HAA6H;IAC7H,IAAI,sBAAsB,CAAA,GAAA,mBAAW,EAAE,CAAA,GAAA,cAAM,EAAE,IAAM,CAAA,GAAA,gBAAQ,EAAE,eAAe,cAAc;QAAC;QAAe;KAAY;IAExH,IAAI,iBAAiB,CAAA,GAAA,qBAAa,EAAE;YAElC;QADA,0BAA0B,OAAO,GAAG;SACpC,yBAAA,cAAc,OAAO,cAArB,6CAAA,uBAAuB,aAAa,CAClC,IAAI,YAAY,CAAA,GAAA,kBAAU,GAAG;YAC3B,YAAY;YACZ,SAAS;YACT,QAAQ;gBACN,eAAe;YACjB;QACF;IAEJ;IAEA,IAAI,oBAAoB,CAAA,GAAA,qBAAa,EAAE;YAQrC;QAPA,MAAM,gBAAgB,CAAC;QACvB,IAAI,kBAAkB,IAAI,YAAY,CAAA,GAAA,wBAAgB,GAAG;YACvD,YAAY;YACZ,SAAS;QACX;QACA,aAAa,QAAQ,OAAO;QAC5B,0BAA0B,OAAO,GAAG;SACpC,yBAAA,cAAc,OAAO,cAArB,6CAAA,uBAAuB,aAAa,CAAC;IACvC;IAEA,4GAA4G;IAC5G,IAAI,WAAW,CAAC;QACd,iIAAiI;QACjI,kCAAkC;QAClC,IAAI,MAAM,UAAU,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,UAAU,CAAC,MAAM,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EACzF;aAEA;QAGF,MAAM,aAAa,CAAC,EAAE,MAAM,CAAC,KAAK;IACpC;IAEA,4CAA4C;IAC5C,IAAI,YAAY,CAAC;YA6Db;QA5DF,IAAI,EAAE,WAAW,CAAC,WAAW,EAC3B;QAGF,OAAQ,EAAE,GAAG;YACX,KAAK;gBACH,IAAI,CAAA,GAAA,uBAAe,EAAE,IACnB;gBAEF;YACF,KAAK;gBACH,iHAAiH;gBACjH,iHAAiH;gBACjH,2BAA2B;gBAC3B,yHAAyH;gBACzH,gIAAgI;gBAChI,+HAA+H;gBAC/H,4EAA4E;gBAC5E,IAAI,EAAE,oBAAoB,IAAI;oBAC5B,MAAM,aAAa,CAAC;oBACpB;gBACF;gBACA;YACF,KAAK;gBACH,oDAAoD;gBAEpD;YACF,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;YACL,KAAK;gBAAa;wBAahB;oBAZA,IAAI,AAAC,CAAA,EAAE,GAAG,KAAK,UAAU,EAAE,GAAG,KAAK,KAAI,KAAM,MAAM,aAAa,IAAI,QAAQ,EAAE,QAAQ,EACpF;oBAGF,8DAA8D;oBAC9D,EAAE,cAAc;oBAChB,iDAAiD;oBACjD,IAAI,kBAAkB,IAAI,YAAY,CAAA,GAAA,kBAAU,GAAG;wBACjD,YAAY;wBACZ,SAAS;oBACX;qBAEA,0BAAA,cAAc,OAAO,cAArB,8CAAA,wBAAuB,aAAa,CAAC;oBACrC;gBACF;YACA,KAAK;YACL,KAAK;gBACH,+FAA+F;gBAC/F,iEAAiE;gBACjE,yFAAyF;gBACzF;gBACA;QACJ;QAEA,8IAA8I;QAC9I,2CAA2C;QAC3C,IAAI,MAAM,aAAa,IAAI,OACzB,yBAAA,cAAc,OAAO,cAArB,6CAAA,uBAAuB,aAAa,CAClC,IAAI,cAAc,EAAE,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW;aAEhD;YACL,IAAI,OAAO,SAAS,cAAc,CAAC,MAAM,aAAa;YACtD,iBAAA,2BAAA,KAAM,aAAa,CACjB,IAAI,cAAc,EAAE,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW;QAEvD;IACF;IAEA,IAAI,UAAU,CAAA,GAAA,qBAAa,EAAE,CAAC;QAC5B,+EAA+E;QAC/E,mGAAmG;QACnG,mFAAmF;QACnF,IAAI,EAAE,MAAM,KAAK,SAAS,OAAO,EAAE;gBAG/B;YAFF,EAAE,wBAAwB;YAC1B,IAAI,MAAM,aAAa,IAAI,OACzB,yBAAA,cAAc,OAAO,cAArB,6CAAA,uBAAuB,aAAa,CAClC,IAAI,cAAc,EAAE,IAAI,EAAE;iBAEvB;gBACL,IAAI,OAAO,SAAS,cAAc,CAAC,MAAM,aAAa;gBACtD,iBAAA,2BAAA,KAAM,aAAa,CACjB,IAAI,cAAc,EAAE,IAAI,EAAE;YAE9B;QACF;IACF;IAEA,CAAA,GAAA,gBAAQ,EAAE;QACR,SAAS,gBAAgB,CAAC,SAAS,SAAS;QAC5C,OAAO;YACL,SAAS,mBAAmB,CAAC,SAAS,SAAS;QACjD;IACF,GAAG;QAAC;QAAU;KAAQ;IAEtB,IAAI,iBAAC,aAAa,EAAC,GAAG,CAAA,GAAA,kBAAU,EAAE;mBAAC;IAAS;IAE5C,IAAI,kBAAkB,CAAA,GAAA,kCAA0B,EAAE,CAAA,GAAA,oDAAW,GAAG;IAChE,IAAI,kBAAkB,CAAA,GAAA,gBAAQ,EAAE;QAC9B,IAAI;QACJ,cAAc,gBAAgB,MAAM,CAAC;IACvC;IAEA,IAAI,WAAW,CAAA,GAAA,kBAAU,EAAE,CAAC;QAC1B,IAAI,QACF,OAAO,OAAO,eAAe,MAAM,UAAU;QAG/C,OAAO;IACT,GAAG;QAAC,MAAM,UAAU;QAAE;KAAO;QAYA;IAV7B,OAAO;QACL,YAAY;YACV,OAAO,MAAM,UAAU;sBACvB;YACA,GAAG,aAAa;YAChB,cAAc;YACd,iBAAiB;YACjB,iBAAiB;YACjB,mFAAmF;YACnF,qBAAqB;YACrB,yBAAyB,CAAA,uBAAA,MAAM,aAAa,cAAnB,kCAAA,uBAAuB;YAChD,qGAAqG;YACrG,aAAa;YACb,gEAAgE;YAChE,YAAY;QACd;QACA,iBAAiB,CAAA,GAAA,iBAAS,EAAE,iBAAiB;YAC3C,wFAAwF;YACxF,uBAAuB;YACvB,mBAAmB;QACrB;QACA,eAAe;QACf,UAAU,UAAU,OAAO,WAAW;IACxC;AACF","sources":["packages/@react-aria/autocomplete/src/useAutocomplete.ts"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, BaseEvent, DOMProps, RefObject} from '@react-types/shared';\nimport {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete';\nimport {ChangeEvent, InputHTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect, useMemo, useRef} from 'react';\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, isCtrlKeyPressed, mergeProps, mergeRefs, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useId, useLabels, useObjectRef} from '@react-aria/utils';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useKeyboard} from '@react-aria/interactions';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\nexport interface CollectionOptions extends DOMProps, AriaLabelingProps {\n /** Whether the collection items should use virtual focus instead of being focused directly. */\n shouldUseVirtualFocus: boolean,\n /** Whether typeahead is disabled. */\n disallowTypeAhead: boolean\n}\nexport interface AriaAutocompleteProps extends AutocompleteProps {\n /**\n * An optional filter function used to determine if a option should be included in the autocomplete list.\n * Include this if the items you are providing to your wrapped collection aren't filtered by default.\n */\n filter?: (textValue: string, inputValue: string) => boolean\n}\n\nexport interface AriaAutocompleteOptions extends Omit<AriaAutocompleteProps, 'children'> {\n /** The ref for the wrapped collection element. */\n collectionRef: RefObject<HTMLElement | null>,\n /** The ref for the wrapped input element. */\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nexport interface AutocompleteAria {\n /** Props for the autocomplete input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */\n collectionProps: CollectionOptions,\n /** Ref to attach to the wrapped collection. */\n collectionRef: RefObject<HTMLElement | null>,\n /** A filter function that returns if the provided collection node should be filtered out of the collection. */\n filterFn?: (nodeTextValue: string) => boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for a autocomplete component.\n * A autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.\n * @param props - Props for the autocomplete.\n * @param state - State for the autocomplete, as returned by `useAutocompleteState`.\n */\nexport function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state: AutocompleteState): AutocompleteAria {\n let {\n collectionRef,\n filter,\n inputRef\n } = props;\n\n let collectionId = useId();\n let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n let delayNextActiveDescendant = useRef(false);\n let queuedActiveDescendant = useRef(null);\n let lastCollectionNode = useRef<HTMLElement>(null);\n\n let updateActiveDescendant = useEffectEvent((e) => {\n let {target} = e;\n if (queuedActiveDescendant.current === target.id) {\n return;\n }\n\n clearTimeout(timeout.current);\n e.stopPropagation();\n\n if (target !== collectionRef.current) {\n if (delayNextActiveDescendant.current) {\n queuedActiveDescendant.current = target.id;\n timeout.current = setTimeout(() => {\n state.setFocusedNodeId(target.id);\n queuedActiveDescendant.current = null;\n }, 500);\n } else {\n state.setFocusedNodeId(target.id);\n }\n } else {\n state.setFocusedNodeId(null);\n }\n\n delayNextActiveDescendant.current = false;\n });\n\n let callbackRef = useCallback((collectionNode) => {\n if (collectionNode != null) {\n // When typing forward, we want to delay the setting of active descendant to not interrupt the native screen reader announcement\n // of the letter you just typed. If we recieve another UPDATE_ACTIVEDESCENDANT call then we clear the queued update\n // We track lastCollectionNode to do proper cleanup since callbackRefs just pass null when unmounting. This also handles\n // React 19's extra call of the callback ref in strict mode\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n lastCollectionNode.current = collectionNode;\n collectionNode.addEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n } else {\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n }\n }, [updateActiveDescendant]);\n\n // Make sure to memo so that React doesn't keep registering a new event listeners on every rerender of the wrapped collection\n let mergedCollectionRef = useObjectRef(useMemo(() => mergeRefs(collectionRef, callbackRef), [collectionRef, callbackRef]));\n\n let focusFirstItem = useEffectEvent(() => {\n delayNextActiveDescendant.current = true;\n collectionRef.current?.dispatchEvent(\n new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true,\n detail: {\n focusStrategy: 'first'\n }\n })\n );\n });\n\n let clearVirtualFocus = useEffectEvent(() => {\n state.setFocusedNodeId(null);\n let clearFocusEvent = new CustomEvent(CLEAR_FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n clearTimeout(timeout.current);\n delayNextActiveDescendant.current = false;\n collectionRef.current?.dispatchEvent(clearFocusEvent);\n });\n\n // TODO: update to see if we can tell what kind of event (paste vs backspace vs typing) is happening instead\n let onChange = (e: ChangeEvent<HTMLInputElement>) => {\n // Tell wrapped collection to focus the first element in the list when typing forward and to clear focused key when deleting text\n // for screen reader announcements\n if (state.inputValue !== e.target.value && state.inputValue.length <= e.target.value.length) {\n focusFirstItem();\n } else {\n clearVirtualFocus();\n }\n\n state.setInputValue(e.target.value);\n };\n\n // For textfield specific keydown operations\n let onKeyDown = (e: BaseEvent<ReactKeyboardEvent<any>>) => {\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'a':\n if (isCtrlKeyPressed(e)) {\n return;\n }\n break;\n case 'Escape':\n // Early return for Escape here so it doesn't leak the Escape event from the simulated collection event below and\n // close the dialog prematurely. Ideally that should be up to the discretion of the input element hence the check\n // for isPropagationStopped\n // Also set the inputValue to '' to cover Firefox case where Esc doesn't actually clear searchfields. Normally we already\n // handle this in useSearchField, but we are directly setting the inputValue on the input element in RAC Autocomplete instead of\n // passing it to the SearchField via props. This means that a controlled value set on the Autocomplete isn't synced up with the\n // SearchField until the user makes a change to the field's value via typing\n if (e.isPropagationStopped()) {\n state.setInputValue('');\n return;\n }\n break;\n case ' ':\n // Space shouldn't trigger onAction so early return.\n\n return;\n case 'Home':\n case 'End':\n case 'PageDown':\n case 'PageUp':\n case 'ArrowUp':\n case 'ArrowDown': {\n if ((e.key === 'Home' || e.key === 'End') && state.focusedNodeId == null && e.shiftKey) {\n return;\n }\n\n // Prevent these keys from moving the text cursor in the input\n e.preventDefault();\n // Move virtual focus into the wrapped collection\n let focusCollection = new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n\n collectionRef.current?.dispatchEvent(focusCollection);\n break;\n }\n case 'ArrowLeft':\n case 'ArrowRight':\n // TODO: will need to special case this so it doesn't clear the focused key if we are currently\n // focused on a submenutrigger? May not need to since focus would\n // But what about wrapped grids where ArrowLeft and ArrowRight should navigate left/right\n clearVirtualFocus();\n break;\n }\n\n // Emulate the keyboard events that happen in the input field in the wrapped collection. This is for triggering things like onAction via Enter\n // or moving focus from one item to another\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n }\n };\n\n let onKeyUp = useEffectEvent((e) => {\n // Dispatch simulated key up events for things like triggering links in listbox\n // Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair\n // is detected by usePress instead of the original keyup originating from the input\n if (e.target === inputRef.current) {\n e.stopImmediatePropagation();\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n }\n }\n });\n\n useEffect(() => {\n document.addEventListener('keyup', onKeyUp, true);\n return () => {\n document.removeEventListener('keyup', onKeyUp, true);\n };\n }, [inputRef, onKeyUp]);\n\n let {keyboardProps} = useKeyboard({onKeyDown});\n\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/autocomplete');\n let collectionProps = useLabels({\n id: collectionId,\n 'aria-label': stringFormatter.format('collectionLabel')\n });\n\n let filterFn = useCallback((nodeTextValue: string) => {\n if (filter) {\n return filter(nodeTextValue, state.inputValue);\n }\n\n return true;\n }, [state.inputValue, filter]);\n\n return {\n inputProps: {\n value: state.inputValue,\n onChange,\n ...keyboardProps,\n autoComplete: 'off',\n 'aria-haspopup': 'listbox',\n 'aria-controls': collectionId,\n // TODO: readd proper logic for completionMode = complete (aria-autocomplete: both)\n 'aria-autocomplete': 'list',\n 'aria-activedescendant': state.focusedNodeId ?? undefined,\n // This disable's iOS's autocorrect suggestions, since the autocomplete provides its own suggestions.\n autoCorrect: 'off',\n // This disable's the macOS Safari spell check auto corrections.\n spellCheck: 'false'\n },\n collectionProps: mergeProps(collectionProps, {\n // TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?\n shouldUseVirtualFocus: true,\n disallowTypeAhead: true\n }),\n collectionRef: mergedCollectionRef,\n filterFn: filter != null ? filterFn : undefined\n };\n}\n"],"names":[],"version":3,"file":"useAutocomplete.module.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/autocomplete/src/useAutocomplete.ts"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaLabelingProps, BaseEvent, DOMProps, RefObject} from '@react-types/shared';\nimport {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete';\nimport {ChangeEvent, InputHTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect, useMemo, useRef} from 'react';\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, isCtrlKeyPressed, mergeProps, mergeRefs, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useId, useLabels, useObjectRef} from '@react-aria/utils';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {useKeyboard} from '@react-aria/interactions';\nimport {useLocalizedStringFormatter} from '@react-aria/i18n';\n\nexport interface CollectionOptions extends DOMProps, AriaLabelingProps {\n /** Whether the collection items should use virtual focus instead of being focused directly. */\n shouldUseVirtualFocus: boolean,\n /** Whether typeahead is disabled. */\n disallowTypeAhead: boolean\n}\nexport interface AriaAutocompleteProps extends AutocompleteProps {\n /**\n * An optional filter function used to determine if a option should be included in the autocomplete list.\n * Include this if the items you are providing to your wrapped collection aren't filtered by default.\n */\n filter?: (textValue: string, inputValue: string) => boolean\n}\n\nexport interface AriaAutocompleteOptions extends Omit<AriaAutocompleteProps, 'children'> {\n /** The ref for the wrapped collection element. */\n collectionRef: RefObject<HTMLElement | null>,\n /** The ref for the wrapped input element. */\n inputRef: RefObject<HTMLInputElement | null>\n}\n\nexport interface AutocompleteAria {\n /** Props for the autocomplete input element. */\n inputProps: InputHTMLAttributes<HTMLInputElement>,\n /** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */\n collectionProps: CollectionOptions,\n /** Ref to attach to the wrapped collection. */\n collectionRef: RefObject<HTMLElement | null>,\n /** A filter function that returns if the provided collection node should be filtered out of the collection. */\n filterFn?: (nodeTextValue: string) => boolean\n}\n\n/**\n * Provides the behavior and accessibility implementation for a autocomplete component.\n * A autocomplete combines a text input with a collection, allowing users to filter the collection's contents match a query.\n * @param props - Props for the autocomplete.\n * @param state - State for the autocomplete, as returned by `useAutocompleteState`.\n */\nexport function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state: AutocompleteState): AutocompleteAria {\n let {\n collectionRef,\n filter,\n inputRef\n } = props;\n\n let collectionId = useId();\n let timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n let delayNextActiveDescendant = useRef(false);\n let queuedActiveDescendant = useRef(null);\n let lastCollectionNode = useRef<HTMLElement>(null);\n\n let updateActiveDescendant = useEffectEvent((e) => {\n let {target} = e;\n if (queuedActiveDescendant.current === target.id) {\n return;\n }\n\n clearTimeout(timeout.current);\n e.stopPropagation();\n\n if (target !== collectionRef.current) {\n if (delayNextActiveDescendant.current) {\n queuedActiveDescendant.current = target.id;\n timeout.current = setTimeout(() => {\n state.setFocusedNodeId(target.id);\n queuedActiveDescendant.current = null;\n }, 500);\n } else {\n state.setFocusedNodeId(target.id);\n }\n } else {\n state.setFocusedNodeId(null);\n }\n\n delayNextActiveDescendant.current = false;\n });\n\n let callbackRef = useCallback((collectionNode) => {\n if (collectionNode != null) {\n // When typing forward, we want to delay the setting of active descendant to not interrupt the native screen reader announcement\n // of the letter you just typed. If we recieve another UPDATE_ACTIVEDESCENDANT call then we clear the queued update\n // We track lastCollectionNode to do proper cleanup since callbackRefs just pass null when unmounting. This also handles\n // React 19's extra call of the callback ref in strict mode\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n lastCollectionNode.current = collectionNode;\n collectionNode.addEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n } else {\n lastCollectionNode.current?.removeEventListener(UPDATE_ACTIVEDESCENDANT, updateActiveDescendant);\n }\n }, [updateActiveDescendant]);\n\n // Make sure to memo so that React doesn't keep registering a new event listeners on every rerender of the wrapped collection\n let mergedCollectionRef = useObjectRef(useMemo(() => mergeRefs(collectionRef, callbackRef), [collectionRef, callbackRef]));\n\n let focusFirstItem = useEffectEvent(() => {\n delayNextActiveDescendant.current = true;\n collectionRef.current?.dispatchEvent(\n new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true,\n detail: {\n focusStrategy: 'first'\n }\n })\n );\n });\n\n let clearVirtualFocus = useEffectEvent(() => {\n state.setFocusedNodeId(null);\n let clearFocusEvent = new CustomEvent(CLEAR_FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n clearTimeout(timeout.current);\n delayNextActiveDescendant.current = false;\n collectionRef.current?.dispatchEvent(clearFocusEvent);\n });\n\n // TODO: update to see if we can tell what kind of event (paste vs backspace vs typing) is happening instead\n let onChange = (e: ChangeEvent<HTMLInputElement>) => {\n // Tell wrapped collection to focus the first element in the list when typing forward and to clear focused key when deleting text\n // for screen reader announcements\n if (state.inputValue !== e.target.value && state.inputValue.length <= e.target.value.length) {\n focusFirstItem();\n } else {\n clearVirtualFocus();\n }\n\n state.setInputValue(e.target.value);\n };\n\n // For textfield specific keydown operations\n let onKeyDown = (e: BaseEvent<ReactKeyboardEvent<any>>) => {\n if (e.nativeEvent.isComposing) {\n return;\n }\n\n switch (e.key) {\n case 'a':\n if (isCtrlKeyPressed(e)) {\n return;\n }\n break;\n case 'Escape':\n // Early return for Escape here so it doesn't leak the Escape event from the simulated collection event below and\n // close the dialog prematurely. Ideally that should be up to the discretion of the input element hence the check\n // for isPropagationStopped\n // Also set the inputValue to '' to cover Firefox case where Esc doesn't actually clear searchfields. Normally we already\n // handle this in useSearchField, but we are directly setting the inputValue on the input element in RAC Autocomplete instead of\n // passing it to the SearchField via props. This means that a controlled value set on the Autocomplete isn't synced up with the\n // SearchField until the user makes a change to the field's value via typing\n if (e.isPropagationStopped()) {\n state.setInputValue('');\n return;\n }\n break;\n case ' ':\n // Space shouldn't trigger onAction so early return.\n\n return;\n case 'Home':\n case 'End':\n case 'PageDown':\n case 'PageUp':\n case 'ArrowUp':\n case 'ArrowDown': {\n if ((e.key === 'Home' || e.key === 'End') && state.focusedNodeId == null && e.shiftKey) {\n return;\n }\n\n // Prevent these keys from moving the text cursor in the input\n e.preventDefault();\n // Move virtual focus into the wrapped collection\n let focusCollection = new CustomEvent(FOCUS_EVENT, {\n cancelable: true,\n bubbles: true\n });\n\n collectionRef.current?.dispatchEvent(focusCollection);\n break;\n }\n case 'ArrowLeft':\n case 'ArrowRight':\n // TODO: will need to special case this so it doesn't clear the focused key if we are currently\n // focused on a submenutrigger? May not need to since focus would\n // But what about wrapped grids where ArrowLeft and ArrowRight should navigate left/right\n clearVirtualFocus();\n break;\n }\n\n // Emulate the keyboard events that happen in the input field in the wrapped collection. This is for triggering things like onAction via Enter\n // or moving focus from one item to another\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n }\n };\n\n let onKeyUpCapture = useEffectEvent((e) => {\n // Dispatch simulated key up events for things like triggering links in listbox\n // Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair\n // is detected by usePress instead of the original keyup originating from the input\n if (e.target === inputRef.current) {\n e.stopImmediatePropagation();\n if (state.focusedNodeId == null) {\n collectionRef.current?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n } else {\n let item = document.getElementById(state.focusedNodeId);\n item?.dispatchEvent(\n new KeyboardEvent(e.type, e)\n );\n }\n }\n });\n\n useEffect(() => {\n document.addEventListener('keyup', onKeyUpCapture, true);\n return () => {\n document.removeEventListener('keyup', onKeyUpCapture, true);\n };\n }, [inputRef, onKeyUpCapture]);\n\n let {keyboardProps} = useKeyboard({onKeyDown});\n\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/autocomplete');\n let collectionProps = useLabels({\n id: collectionId,\n 'aria-label': stringFormatter.format('collectionLabel')\n });\n\n let filterFn = useCallback((nodeTextValue: string) => {\n if (filter) {\n return filter(nodeTextValue, state.inputValue);\n }\n\n return true;\n }, [state.inputValue, filter]);\n\n return {\n inputProps: {\n value: state.inputValue,\n onChange,\n ...keyboardProps,\n autoComplete: 'off',\n 'aria-haspopup': 'listbox',\n 'aria-controls': collectionId,\n // TODO: readd proper logic for completionMode = complete (aria-autocomplete: both)\n 'aria-autocomplete': 'list',\n 'aria-activedescendant': state.focusedNodeId ?? undefined,\n // This disable's iOS's autocorrect suggestions, since the autocomplete provides its own suggestions.\n autoCorrect: 'off',\n // This disable's the macOS Safari spell check auto corrections.\n spellCheck: 'false'\n },\n collectionProps: mergeProps(collectionProps, {\n // TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?\n shouldUseVirtualFocus: true,\n disallowTypeAhead: true,\n // Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally\n // they've been handled by the input already\n onKeyDown: (e) => e.stopPropagation()\n }),\n collectionRef: mergedCollectionRef,\n filterFn: filter != null ? filterFn : undefined\n };\n}\n"],"names":[],"version":3,"file":"useAutocomplete.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/autocomplete",
|
|
3
|
-
"version": "3.0.0-nightly-
|
|
3
|
+
"version": "3.0.0-nightly-e4497fdb6-250110",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
"url": "https://github.com/adobe/react-spectrum"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@react-aria/combobox": "3.0.0-nightly-
|
|
26
|
-
"@react-aria/i18n": "3.0.0-nightly-
|
|
27
|
-
"@react-aria/interactions": "3.0.0-nightly-
|
|
28
|
-
"@react-aria/listbox": "3.0.0-nightly-
|
|
29
|
-
"@react-aria/searchfield": "3.0.0-nightly-
|
|
30
|
-
"@react-aria/utils": "3.0.0-nightly-
|
|
31
|
-
"@react-stately/autocomplete": "3.0.0-nightly-
|
|
32
|
-
"@react-stately/combobox": "3.0.0-nightly-
|
|
33
|
-
"@react-types/autocomplete": "3.0.0-nightly-
|
|
34
|
-
"@react-types/button": "3.0.0-nightly-
|
|
35
|
-
"@react-types/shared": "3.0.0-nightly-
|
|
25
|
+
"@react-aria/combobox": "3.0.0-nightly-e4497fdb6-250110",
|
|
26
|
+
"@react-aria/i18n": "3.0.0-nightly-e4497fdb6-250110",
|
|
27
|
+
"@react-aria/interactions": "3.0.0-nightly-e4497fdb6-250110",
|
|
28
|
+
"@react-aria/listbox": "3.0.0-nightly-e4497fdb6-250110",
|
|
29
|
+
"@react-aria/searchfield": "3.0.0-nightly-e4497fdb6-250110",
|
|
30
|
+
"@react-aria/utils": "3.0.0-nightly-e4497fdb6-250110",
|
|
31
|
+
"@react-stately/autocomplete": "3.0.0-nightly-e4497fdb6-250110",
|
|
32
|
+
"@react-stately/combobox": "3.0.0-nightly-e4497fdb6-250110",
|
|
33
|
+
"@react-types/autocomplete": "3.0.0-nightly-e4497fdb6-250110",
|
|
34
|
+
"@react-types/button": "3.0.0-nightly-e4497fdb6-250110",
|
|
35
|
+
"@react-types/shared": "3.0.0-nightly-e4497fdb6-250110",
|
|
36
36
|
"@swc/helpers": "^0.5.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
package/src/useAutocomplete.ts
CHANGED
|
@@ -223,7 +223,7 @@ export function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state:
|
|
|
223
223
|
}
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
-
let
|
|
226
|
+
let onKeyUpCapture = useEffectEvent((e) => {
|
|
227
227
|
// Dispatch simulated key up events for things like triggering links in listbox
|
|
228
228
|
// Make sure to stop the propagation of the input keyup event so that the simulated keyup/down pair
|
|
229
229
|
// is detected by usePress instead of the original keyup originating from the input
|
|
@@ -243,11 +243,11 @@ export function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state:
|
|
|
243
243
|
});
|
|
244
244
|
|
|
245
245
|
useEffect(() => {
|
|
246
|
-
document.addEventListener('keyup',
|
|
246
|
+
document.addEventListener('keyup', onKeyUpCapture, true);
|
|
247
247
|
return () => {
|
|
248
|
-
document.removeEventListener('keyup',
|
|
248
|
+
document.removeEventListener('keyup', onKeyUpCapture, true);
|
|
249
249
|
};
|
|
250
|
-
}, [inputRef,
|
|
250
|
+
}, [inputRef, onKeyUpCapture]);
|
|
251
251
|
|
|
252
252
|
let {keyboardProps} = useKeyboard({onKeyDown});
|
|
253
253
|
|
|
@@ -284,7 +284,10 @@ export function UNSTABLE_useAutocomplete(props: AriaAutocompleteOptions, state:
|
|
|
284
284
|
collectionProps: mergeProps(collectionProps, {
|
|
285
285
|
// TODO: shouldFocusOnHover? shouldFocusWrap? Should it be up to the wrapped collection?
|
|
286
286
|
shouldUseVirtualFocus: true,
|
|
287
|
-
disallowTypeAhead: true
|
|
287
|
+
disallowTypeAhead: true,
|
|
288
|
+
// Prevent the emulated keyboard events that were dispatched on the wrapped collection from propagating outside of the autocomplete since techincally
|
|
289
|
+
// they've been handled by the input already
|
|
290
|
+
onKeyDown: (e) => e.stopPropagation()
|
|
288
291
|
}),
|
|
289
292
|
collectionRef: mergedCollectionRef,
|
|
290
293
|
filterFn: filter != null ? filterFn : undefined
|