@wordpress/components 32.5.0 → 32.6.0
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/AGENTS.md +2 -2
- package/CHANGELOG.md +40 -0
- package/README.md +18 -4
- package/build/alignment-matrix-control/cell.cjs +3 -3
- package/build/alignment-matrix-control/cell.cjs.map +2 -2
- package/build/alignment-matrix-control/index.cjs +3 -3
- package/build/alignment-matrix-control/index.cjs.map +2 -2
- package/build/autocomplete/autocompleter-ui.cjs +75 -79
- package/build/autocomplete/autocompleter-ui.cjs.map +2 -2
- package/build/autocomplete/get-autocomplete-match.cjs +91 -0
- package/build/autocomplete/get-autocomplete-match.cjs.map +7 -0
- package/build/autocomplete/index.cjs +104 -107
- package/build/autocomplete/index.cjs.map +3 -3
- package/build/box-control/index.cjs +0 -8
- package/build/box-control/index.cjs.map +2 -2
- package/build/box-control/utils.cjs +1 -10
- package/build/box-control/utils.cjs.map +2 -2
- package/build/calendar/utils/use-localization-props.cjs +3 -2
- package/build/calendar/utils/use-localization-props.cjs.map +2 -2
- package/build/custom-gradient-picker/index.cjs.map +2 -2
- package/build/custom-select-control/index.cjs.map +3 -3
- package/build/custom-select-control-v2/custom-select.cjs +2 -2
- package/build/custom-select-control-v2/custom-select.cjs.map +2 -2
- package/build/custom-select-control-v2/index.cjs.map +3 -3
- package/build/date-time/{date → date-picker}/index.cjs +6 -6
- package/build/date-time/{date → date-picker}/index.cjs.map +2 -2
- package/build/date-time/{date → date-picker}/styles.cjs +17 -17
- package/build/date-time/{date → date-picker}/styles.cjs.map +2 -2
- package/build/date-time/{date → date-picker}/use-lilius/index.cjs +1 -1
- package/build/date-time/{date → date-picker}/use-lilius/index.cjs.map +1 -1
- package/build/date-time/date-time/index.cjs +6 -6
- package/build/date-time/date-time/index.cjs.map +2 -2
- package/build/date-time/index.cjs +4 -4
- package/build/date-time/index.cjs.map +2 -2
- package/build/date-time/{time → time-picker}/index.cjs +6 -6
- package/build/date-time/time-picker/index.cjs.map +7 -0
- package/build/date-time/{time → time-picker}/styles.cjs +21 -21
- package/build/date-time/{time → time-picker}/styles.cjs.map +2 -2
- package/build/date-time/{time → time-picker}/time-input/index.cjs +1 -1
- package/build/date-time/{time → time-picker}/time-input/index.cjs.map +1 -1
- package/build/date-time/{time → time-picker}/timezone.cjs +1 -1
- package/build/date-time/{time → time-picker}/timezone.cjs.map +1 -1
- package/build/modal/index.cjs.map +2 -2
- package/build/palette-edit/index.cjs.map +2 -2
- package/build/radio-control/index.cjs +2 -0
- package/build/radio-control/index.cjs.map +2 -2
- package/build/sandbox/index.cjs +127 -3
- package/build/sandbox/index.cjs.map +2 -2
- package/build/textarea-control/styles/textarea-control-styles.cjs +3 -3
- package/build/textarea-control/styles/textarea-control-styles.cjs.map +2 -2
- package/build/validated-form-controls/control-with-error.cjs +12 -8
- package/build/validated-form-controls/control-with-error.cjs.map +2 -2
- package/build-module/alignment-matrix-control/cell.mjs +3 -3
- package/build-module/alignment-matrix-control/cell.mjs.map +2 -2
- package/build-module/alignment-matrix-control/index.mjs +3 -3
- package/build-module/alignment-matrix-control/index.mjs.map +2 -2
- package/build-module/autocomplete/autocompleter-ui.mjs +74 -78
- package/build-module/autocomplete/autocompleter-ui.mjs.map +2 -2
- package/build-module/autocomplete/get-autocomplete-match.mjs +56 -0
- package/build-module/autocomplete/get-autocomplete-match.mjs.map +7 -0
- package/build-module/autocomplete/index.mjs +103 -107
- package/build-module/autocomplete/index.mjs.map +3 -3
- package/build-module/box-control/index.mjs +1 -9
- package/build-module/box-control/index.mjs.map +2 -2
- package/build-module/box-control/utils.mjs +1 -9
- package/build-module/box-control/utils.mjs.map +2 -2
- package/build-module/calendar/utils/use-localization-props.mjs +3 -2
- package/build-module/calendar/utils/use-localization-props.mjs.map +2 -2
- package/build-module/custom-gradient-picker/index.mjs.map +2 -2
- package/build-module/custom-select-control/index.mjs +2 -2
- package/build-module/custom-select-control/index.mjs.map +2 -2
- package/build-module/custom-select-control-v2/custom-select.mjs +2 -2
- package/build-module/custom-select-control-v2/custom-select.mjs.map +2 -2
- package/build-module/custom-select-control-v2/index.mjs +2 -2
- package/build-module/custom-select-control-v2/index.mjs.map +2 -2
- package/build-module/date-time/{date → date-picker}/index.mjs +3 -3
- package/build-module/date-time/{date → date-picker}/index.mjs.map +2 -2
- package/build-module/date-time/{date → date-picker}/styles.mjs +17 -17
- package/build-module/date-time/{date → date-picker}/styles.mjs.map +2 -2
- package/build-module/date-time/{date → date-picker}/use-lilius/index.mjs +1 -1
- package/build-module/date-time/{date → date-picker}/use-lilius/index.mjs.map +1 -1
- package/build-module/date-time/date-time/index.mjs +2 -2
- package/build-module/date-time/date-time/index.mjs.map +1 -1
- package/build-module/date-time/index.mjs +2 -2
- package/build-module/date-time/index.mjs.map +1 -1
- package/build-module/date-time/{time → time-picker}/index.mjs +3 -3
- package/build-module/date-time/time-picker/index.mjs.map +7 -0
- package/build-module/date-time/{time → time-picker}/styles.mjs +21 -21
- package/build-module/date-time/{time → time-picker}/styles.mjs.map +2 -2
- package/build-module/date-time/{time → time-picker}/time-input/index.mjs +1 -1
- package/build-module/date-time/{time → time-picker}/time-input/index.mjs.map +1 -1
- package/build-module/date-time/{time → time-picker}/timezone.mjs +1 -1
- package/build-module/date-time/{time → time-picker}/timezone.mjs.map +1 -1
- package/build-module/modal/index.mjs.map +2 -2
- package/build-module/palette-edit/index.mjs.map +2 -2
- package/build-module/radio-control/index.mjs +2 -0
- package/build-module/radio-control/index.mjs.map +2 -2
- package/build-module/sandbox/index.mjs +128 -4
- package/build-module/sandbox/index.mjs.map +2 -2
- package/build-module/textarea-control/styles/textarea-control-styles.mjs +3 -3
- package/build-module/textarea-control/styles/textarea-control-styles.mjs.map +2 -2
- package/build-module/validated-form-controls/control-with-error.mjs +12 -8
- package/build-module/validated-form-controls/control-with-error.mjs.map +2 -2
- package/build-style/style-rtl.css +83 -26
- package/build-style/style.css +83 -26
- package/build-types/autocomplete/autocompleter-ui.d.ts +2 -2
- package/build-types/autocomplete/autocompleter-ui.d.ts.map +1 -1
- package/build-types/autocomplete/get-autocomplete-match.d.ts +11 -0
- package/build-types/autocomplete/get-autocomplete-match.d.ts.map +1 -0
- package/build-types/autocomplete/index.d.ts +8 -0
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/autocomplete/test/get-autocomplete-match.d.ts +2 -0
- package/build-types/autocomplete/test/get-autocomplete-match.d.ts.map +1 -0
- package/build-types/autocomplete/types.d.ts +23 -9
- package/build-types/autocomplete/types.d.ts.map +1 -1
- package/build-types/box-control/index.d.ts.map +1 -1
- package/build-types/box-control/utils.d.ts +7 -16
- package/build-types/box-control/utils.d.ts.map +1 -1
- package/build-types/button/stories/index.story.d.ts +0 -1
- package/build-types/button/stories/index.story.d.ts.map +1 -1
- package/build-types/calendar/utils/use-localization-props.d.ts +3 -3
- package/build-types/calendar/utils/use-localization-props.d.ts.map +1 -1
- package/build-types/checkbox-control/types.d.ts +4 -0
- package/build-types/checkbox-control/types.d.ts.map +1 -1
- package/build-types/custom-gradient-picker/constants.d.ts +2 -2
- package/build-types/custom-gradient-picker/index.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/custom-select.d.ts +3 -3
- package/build-types/custom-select-control-v2/custom-select.d.ts.map +1 -1
- package/build-types/custom-select-control-v2/types.d.ts +1 -1
- package/build-types/custom-select-control-v2/types.d.ts.map +1 -1
- package/build-types/date-time/date-picker/index.d.ts.map +1 -0
- package/build-types/date-time/date-picker/styles.d.ts.map +1 -0
- package/build-types/date-time/date-picker/test/index.d.ts.map +1 -0
- package/build-types/date-time/date-picker/test/use-lilius.d.ts.map +1 -0
- package/build-types/date-time/date-picker/use-lilius/index.d.ts.map +1 -0
- package/build-types/date-time/date-time/index.d.ts +2 -2
- package/build-types/date-time/date-time/index.d.ts.map +1 -1
- package/build-types/date-time/index.d.ts +2 -2
- package/build-types/date-time/index.d.ts.map +1 -1
- package/build-types/date-time/stories/date.story.d.ts +1 -1
- package/build-types/date-time/stories/date.story.d.ts.map +1 -1
- package/build-types/date-time/stories/time.story.d.ts +1 -1
- package/build-types/date-time/stories/time.story.d.ts.map +1 -1
- package/build-types/date-time/{time → time-picker}/index.d.ts +1 -1
- package/build-types/date-time/time-picker/index.d.ts.map +1 -0
- package/build-types/date-time/time-picker/styles.d.ts.map +1 -0
- package/build-types/date-time/time-picker/test/index.d.ts.map +1 -0
- package/build-types/date-time/time-picker/time-input/index.d.ts.map +1 -0
- package/build-types/date-time/time-picker/time-input/test/index.d.ts.map +1 -0
- package/build-types/date-time/time-picker/timezone.d.ts.map +1 -0
- package/build-types/date-time/types.d.ts +1 -1
- package/build-types/date-time/types.d.ts.map +1 -1
- package/build-types/font-size-picker/constants.d.ts +2 -2
- package/build-types/font-size-picker/constants.d.ts.map +1 -1
- package/build-types/modal/index.d.ts.map +1 -1
- package/build-types/palette-edit/index.d.ts +1 -1
- package/build-types/palette-edit/index.d.ts.map +1 -1
- package/build-types/radio-control/index.d.ts.map +1 -1
- package/build-types/radio-control/types.d.ts +6 -0
- package/build-types/radio-control/types.d.ts.map +1 -1
- package/build-types/sandbox/index.d.ts +1 -1
- package/build-types/sandbox/index.d.ts.map +1 -1
- package/build-types/sandbox/types.d.ts +11 -0
- package/build-types/sandbox/types.d.ts.map +1 -1
- package/build-types/textarea-control/stories/index.story.d.ts.map +1 -1
- package/build-types/textarea-control/styles/textarea-control-styles.d.ts.map +1 -1
- package/build-types/validated-form-controls/components/checkbox-control.d.ts +2 -1
- package/build-types/validated-form-controls/components/checkbox-control.d.ts.map +1 -1
- package/build-types/validated-form-controls/components/radio-control.d.ts +2 -1
- package/build-types/validated-form-controls/components/radio-control.d.ts.map +1 -1
- package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/alignment-matrix-control/README.md +1 -1
- package/src/alignment-matrix-control/style.module.scss +1 -1
- package/src/angle-picker-control/style.module.scss +1 -0
- package/src/autocomplete/README.md +2 -2
- package/src/autocomplete/autocompleter-ui.native.js +166 -173
- package/src/autocomplete/autocompleter-ui.tsx +114 -116
- package/src/autocomplete/get-autocomplete-match.ts +115 -0
- package/src/autocomplete/index.tsx +129 -208
- package/src/autocomplete/test/get-autocomplete-match.ts +338 -0
- package/src/autocomplete/test/index.tsx +112 -4
- package/src/autocomplete/types.ts +17 -10
- package/src/box-control/index.tsx +1 -19
- package/src/box-control/utils.ts +1 -19
- package/src/button/README.md +1 -1
- package/src/button/stories/index.story.tsx +0 -1
- package/src/button/style.scss +1 -7
- package/src/calendar/style.scss +3 -3
- package/src/calendar/utils/use-localization-props.ts +3 -4
- package/src/checkbox-control/style.scss +17 -5
- package/src/checkbox-control/types.ts +4 -0
- package/src/circular-option-picker/style.scss +1 -1
- package/src/color-palette/style.scss +1 -1
- package/src/css.d.ts +1 -0
- package/src/custom-gradient-picker/index.tsx +1 -0
- package/src/custom-select-control/index.tsx +3 -3
- package/src/custom-select-control-v2/custom-select.tsx +4 -4
- package/src/custom-select-control-v2/index.tsx +2 -2
- package/src/custom-select-control-v2/types.ts +1 -1
- package/src/date-time/README.md +3 -3
- package/src/date-time/date-picker/README.md +65 -0
- package/src/date-time/date-time/index.tsx +2 -2
- package/src/date-time/index.ts +2 -2
- package/src/date-time/stories/date.story.tsx +1 -1
- package/src/date-time/stories/time.story.tsx +1 -1
- package/src/date-time/time-picker/README.md +119 -0
- package/src/date-time/{time → time-picker}/index.tsx +1 -1
- package/src/date-time/types.ts +1 -1
- package/src/divider/README.md +5 -6
- package/src/dropdown-menu/style.scss +1 -1
- package/src/flex/stories/index.story.tsx +1 -1
- package/src/form-file-upload/README.md +3 -3
- package/src/form-toggle/style.scss +35 -2
- package/src/form-token-field/style.scss +12 -3
- package/src/gradient-picker/README.md +2 -2
- package/src/h-stack/README.md +10 -15
- package/src/h-stack/stories/index.story.tsx +2 -2
- package/src/heading/stories/index.story.tsx +1 -1
- package/src/higher-order/with-focus-outside/index.native.js +21 -20
- package/src/icon/README.md +1 -1
- package/src/menu/README.md +2 -2
- package/src/mobile/utils/get-px-from-css-unit.native.js +1 -1
- package/src/modal/index.tsx +1 -0
- package/src/palette-edit/index.tsx +1 -0
- package/src/radio-control/index.tsx +2 -0
- package/src/radio-control/style.scss +21 -2
- package/src/radio-control/test/index.tsx +10 -0
- package/src/radio-control/types.ts +6 -0
- package/src/sandbox/index.native.js +2 -2
- package/src/sandbox/index.tsx +191 -11
- package/src/sandbox/test/index.tsx +65 -24
- package/src/sandbox/types.ts +11 -0
- package/src/snackbar/style.scss +2 -2
- package/src/tab-panel/style.scss +1 -1
- package/src/tabs/README.md +6 -6
- package/src/text/stories/index.story.tsx +1 -1
- package/src/textarea-control/stories/index.story.tsx +3 -0
- package/src/textarea-control/styles/textarea-control-styles.ts +6 -0
- package/src/toggle-control/style.scss +1 -1
- package/src/toggle-control/test/index.tsx +8 -2
- package/src/toolbar/toolbar-button/toolbar-button-container.native.js +3 -1
- package/src/tree-select/README.md +1 -1
- package/src/v-stack/README.md +10 -15
- package/src/v-stack/stories/index.story.tsx +2 -2
- package/src/validated-form-controls/control-with-error.tsx +17 -12
- package/src/validated-form-controls/test/control-with-error.tsx +28 -1
- package/src/view/README.md +2 -5
- package/build/date-time/time/index.cjs.map +0 -7
- package/build-module/date-time/time/index.mjs.map +0 -7
- package/build-types/date-time/date/index.d.ts.map +0 -1
- package/build-types/date-time/date/styles.d.ts.map +0 -1
- package/build-types/date-time/date/test/index.d.ts.map +0 -1
- package/build-types/date-time/date/test/use-lilius.d.ts.map +0 -1
- package/build-types/date-time/date/use-lilius/index.d.ts.map +0 -1
- package/build-types/date-time/time/index.d.ts.map +0 -1
- package/build-types/date-time/time/styles.d.ts.map +0 -1
- package/build-types/date-time/time/test/index.d.ts.map +0 -1
- package/build-types/date-time/time/time-input/index.d.ts.map +0 -1
- package/build-types/date-time/time/time-input/test/index.d.ts.map +0 -1
- package/build-types/date-time/time/timezone.d.ts.map +0 -1
- package/src/button/stories/style.css +0 -8
- /package/build-types/date-time/{date → date-picker}/index.d.ts +0 -0
- /package/build-types/date-time/{date → date-picker}/styles.d.ts +0 -0
- /package/build-types/date-time/{date → date-picker}/test/index.d.ts +0 -0
- /package/build-types/date-time/{date → date-picker}/test/use-lilius.d.ts +0 -0
- /package/build-types/date-time/{date → date-picker}/use-lilius/index.d.ts +0 -0
- /package/build-types/date-time/{time → time-picker}/styles.d.ts +0 -0
- /package/build-types/date-time/{time → time-picker}/test/index.d.ts +0 -0
- /package/build-types/date-time/{time → time-picker}/time-input/index.d.ts +0 -0
- /package/build-types/date-time/{time → time-picker}/time-input/test/index.d.ts +0 -0
- /package/build-types/date-time/{time → time-picker}/timezone.d.ts +0 -0
- /package/src/date-time/{date → date-picker}/index.tsx +0 -0
- /package/src/date-time/{date → date-picker}/styles.ts +0 -0
- /package/src/date-time/{date → date-picker}/test/index.tsx +0 -0
- /package/src/date-time/{date → date-picker}/test/use-lilius.ts +0 -0
- /package/src/date-time/{date → date-picker}/use-lilius/index.ts +0 -0
- /package/src/date-time/{time → time-picker}/styles.ts +0 -0
- /package/src/date-time/{time → time-picker}/test/index.tsx +0 -0
- /package/src/date-time/{time → time-picker}/time-input/index.tsx +0 -0
- /package/src/date-time/{time → time-picker}/time-input/test/index.tsx +0 -0
- /package/src/date-time/{time → time-picker}/timezone.tsx +0 -0
|
@@ -25,7 +25,7 @@ import getDefaultUseItems from './get-default-use-items';
|
|
|
25
25
|
import Button from '../button';
|
|
26
26
|
import Popover from '../popover';
|
|
27
27
|
import { VisuallyHidden } from '../visually-hidden';
|
|
28
|
-
import type { AutocompleterUIProps, KeyedOption
|
|
28
|
+
import type { AutocompleterUIProps, KeyedOption } from './types';
|
|
29
29
|
|
|
30
30
|
type ListBoxProps = {
|
|
31
31
|
items: KeyedOption[];
|
|
@@ -79,112 +79,125 @@ function ListBox( {
|
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export function
|
|
82
|
+
export function AutocompleterUI( {
|
|
83
|
+
autocompleter,
|
|
84
|
+
filterValue,
|
|
85
|
+
instanceId,
|
|
86
|
+
listBoxId,
|
|
87
|
+
className,
|
|
88
|
+
selectedIndex,
|
|
89
|
+
onChangeOptions,
|
|
90
|
+
onSelect,
|
|
91
|
+
reset,
|
|
92
|
+
contentRef,
|
|
93
|
+
}: AutocompleterUIProps ) {
|
|
94
|
+
// The useItems hook is derived from the autocompleter prop. This is safe
|
|
95
|
+
// because the parent renders this component with key={autocompleter.name},
|
|
96
|
+
// ensuring a fresh mount (and stable hook identity) when the completer changes.
|
|
83
97
|
const useItems =
|
|
84
98
|
autocompleter.useItems ?? getDefaultUseItems( autocompleter );
|
|
99
|
+
// eslint-disable-next-line react-compiler/react-compiler
|
|
100
|
+
const [ items ] = useItems( filterValue );
|
|
101
|
+
const popoverAnchor = useAnchor( {
|
|
102
|
+
editableContentElement: contentRef.current,
|
|
103
|
+
} );
|
|
104
|
+
|
|
105
|
+
const [ needsA11yCompat, setNeedsA11yCompat ] = useState( false );
|
|
106
|
+
const popoverRef = useRef< HTMLElement >( null );
|
|
107
|
+
const popoverRefs = useMergeRefs( [
|
|
108
|
+
popoverRef,
|
|
109
|
+
useRefEffect(
|
|
110
|
+
( node ) => {
|
|
111
|
+
if ( ! contentRef.current ) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
85
114
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// the content, we need to duplicate the options list in the
|
|
115
|
-
// content document so that it's available to the screen
|
|
116
|
-
// readers, which check the DOM ID based aria-* attributes.
|
|
117
|
-
setNeedsA11yCompat(
|
|
118
|
-
node.ownerDocument !== contentRef.current.ownerDocument
|
|
119
|
-
);
|
|
120
|
-
},
|
|
121
|
-
[ contentRef ]
|
|
122
|
-
),
|
|
123
|
-
] );
|
|
124
|
-
|
|
125
|
-
useOnClickOutside( popoverRef, reset );
|
|
126
|
-
|
|
127
|
-
const debouncedSpeak = useDebounce( speak, 500 );
|
|
128
|
-
|
|
129
|
-
function announce( options: Array< KeyedOption > ) {
|
|
130
|
-
if ( ! debouncedSpeak ) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
if ( !! options.length ) {
|
|
134
|
-
if ( filterValue ) {
|
|
135
|
-
debouncedSpeak(
|
|
136
|
-
sprintf(
|
|
137
|
-
/* translators: %d: number of results. */
|
|
138
|
-
_n(
|
|
139
|
-
'%d result found, use up and down arrow keys to navigate.',
|
|
140
|
-
'%d results found, use up and down arrow keys to navigate.',
|
|
141
|
-
options.length
|
|
142
|
-
),
|
|
115
|
+
// If the popover is rendered in a different document than
|
|
116
|
+
// the content, we need to duplicate the options list in the
|
|
117
|
+
// content document so that it's available to the screen
|
|
118
|
+
// readers, which check the DOM ID based aria-* attributes.
|
|
119
|
+
setNeedsA11yCompat(
|
|
120
|
+
node.ownerDocument !== contentRef.current.ownerDocument
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
[ contentRef ]
|
|
124
|
+
),
|
|
125
|
+
] );
|
|
126
|
+
|
|
127
|
+
useOnClickOutside( popoverRef, reset );
|
|
128
|
+
|
|
129
|
+
const debouncedSpeak = useDebounce( speak, 500 );
|
|
130
|
+
|
|
131
|
+
function announce( options: Array< KeyedOption > ) {
|
|
132
|
+
if ( ! debouncedSpeak ) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if ( !! options.length ) {
|
|
136
|
+
if ( filterValue ) {
|
|
137
|
+
debouncedSpeak(
|
|
138
|
+
sprintf(
|
|
139
|
+
/* translators: %d: number of results. */
|
|
140
|
+
_n(
|
|
141
|
+
'%d result found, use up and down arrow keys to navigate.',
|
|
142
|
+
'%d results found, use up and down arrow keys to navigate.',
|
|
143
143
|
options.length
|
|
144
144
|
),
|
|
145
|
-
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
145
|
+
options.length
|
|
146
|
+
),
|
|
147
|
+
'assertive'
|
|
148
|
+
);
|
|
149
|
+
} else {
|
|
150
|
+
debouncedSpeak(
|
|
151
|
+
sprintf(
|
|
152
|
+
/* translators: %d: number of results. */
|
|
153
|
+
_n(
|
|
154
|
+
'Initial %d result loaded. Type to filter all available results. Use up and down arrow keys to navigate.',
|
|
155
|
+
'Initial %d results loaded. Type to filter all available results. Use up and down arrow keys to navigate.',
|
|
156
156
|
options.length
|
|
157
157
|
),
|
|
158
|
-
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
debouncedSpeak( __( 'No results.' ), 'assertive' );
|
|
158
|
+
options.length
|
|
159
|
+
),
|
|
160
|
+
'assertive'
|
|
161
|
+
);
|
|
163
162
|
}
|
|
163
|
+
} else {
|
|
164
|
+
debouncedSpeak( __( 'No results.' ), 'assertive' );
|
|
164
165
|
}
|
|
166
|
+
}
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
useLayoutEffect( () => {
|
|
169
|
+
onChangeOptions( items );
|
|
170
|
+
announce( items );
|
|
171
|
+
// We want to avoid introducing unexpected side effects.
|
|
172
|
+
// See https://github.com/WordPress/gutenberg/pull/41820
|
|
173
|
+
}, [ items ] );
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
if ( items.length === 0 ) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
179
|
+
return (
|
|
180
|
+
<>
|
|
181
|
+
<Popover
|
|
182
|
+
offset={ 8 }
|
|
183
|
+
focusOnMount={ false }
|
|
184
|
+
placement="top-start"
|
|
185
|
+
className="components-autocomplete__popover"
|
|
186
|
+
anchor={ popoverAnchor }
|
|
187
|
+
ref={ popoverRefs }
|
|
188
|
+
>
|
|
189
|
+
<ListBox
|
|
190
|
+
items={ items }
|
|
191
|
+
onSelect={ onSelect }
|
|
192
|
+
selectedIndex={ selectedIndex }
|
|
193
|
+
instanceId={ instanceId }
|
|
194
|
+
listBoxId={ listBoxId }
|
|
195
|
+
className={ className }
|
|
196
|
+
/>
|
|
197
|
+
</Popover>
|
|
198
|
+
{ contentRef.current &&
|
|
199
|
+
needsA11yCompat &&
|
|
200
|
+
createPortal(
|
|
188
201
|
<ListBox
|
|
189
202
|
items={ items }
|
|
190
203
|
onSelect={ onSelect }
|
|
@@ -192,27 +205,12 @@ export function getAutoCompleterUI( autocompleter: WPCompleter ) {
|
|
|
192
205
|
instanceId={ instanceId }
|
|
193
206
|
listBoxId={ listBoxId }
|
|
194
207
|
className={ className }
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
items={ items }
|
|
202
|
-
onSelect={ onSelect }
|
|
203
|
-
selectedIndex={ selectedIndex }
|
|
204
|
-
instanceId={ instanceId }
|
|
205
|
-
listBoxId={ listBoxId }
|
|
206
|
-
className={ className }
|
|
207
|
-
Component={ VisuallyHidden }
|
|
208
|
-
/>,
|
|
209
|
-
contentRef.current.ownerDocument.body
|
|
210
|
-
) }
|
|
211
|
-
</>
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return AutocompleterUI;
|
|
208
|
+
Component={ VisuallyHidden }
|
|
209
|
+
/>,
|
|
210
|
+
contentRef.current.ownerDocument.body
|
|
211
|
+
) }
|
|
212
|
+
</>
|
|
213
|
+
);
|
|
216
214
|
}
|
|
217
215
|
|
|
218
216
|
function useOnClickOutside(
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import removeAccents from 'remove-accents';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import type { WPCompleter } from './types';
|
|
10
|
+
|
|
11
|
+
type AutocompleteMatch = {
|
|
12
|
+
completer: WPCompleter;
|
|
13
|
+
filterValue: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function getAutocompleteMatch(
|
|
17
|
+
textContent: string,
|
|
18
|
+
completers: WPCompleter[],
|
|
19
|
+
filteredOptionsLength: number,
|
|
20
|
+
isBackspacing: boolean,
|
|
21
|
+
getTextAfterSelection: () => string
|
|
22
|
+
): AutocompleteMatch | null {
|
|
23
|
+
if ( ! textContent ) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Find the completer whose trigger prefix ends closest to the cursor
|
|
28
|
+
// (rightmost end position). Comparing end positions instead of start
|
|
29
|
+
// positions correctly resolves overlapping prefixes like "@" and "@@".
|
|
30
|
+
let completer: WPCompleter | null = null;
|
|
31
|
+
let triggerIndex = -1;
|
|
32
|
+
let matchedEndIndex = -1;
|
|
33
|
+
let matchedPrefixLength = 0;
|
|
34
|
+
|
|
35
|
+
for ( const currentCompleter of completers ) {
|
|
36
|
+
const currentIndex = textContent.lastIndexOf(
|
|
37
|
+
currentCompleter.triggerPrefix
|
|
38
|
+
);
|
|
39
|
+
if ( currentIndex < 0 ) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const currentEndIndex =
|
|
43
|
+
currentIndex + currentCompleter.triggerPrefix.length;
|
|
44
|
+
if (
|
|
45
|
+
currentEndIndex > matchedEndIndex ||
|
|
46
|
+
( currentEndIndex === matchedEndIndex &&
|
|
47
|
+
currentCompleter.triggerPrefix.length > matchedPrefixLength )
|
|
48
|
+
) {
|
|
49
|
+
completer = currentCompleter;
|
|
50
|
+
triggerIndex = currentIndex;
|
|
51
|
+
matchedEndIndex = currentEndIndex;
|
|
52
|
+
matchedPrefixLength = currentCompleter.triggerPrefix.length;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if ( ! completer ) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { allowContext, triggerPrefix } = completer;
|
|
61
|
+
const textWithoutTrigger = textContent.slice(
|
|
62
|
+
triggerIndex + triggerPrefix.length
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Prevent matching with an extremely long string, which causes
|
|
66
|
+
// the editor to slow-down significantly. This could happen, for
|
|
67
|
+
// example, if `matchingWhileBackspacing` is true and one of the
|
|
68
|
+
// "words" ends up being too long. Returning null here intentionally
|
|
69
|
+
// resets the autocompleter state in the caller.
|
|
70
|
+
if ( textWithoutTrigger.length > 50 ) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const mismatch = filteredOptionsLength === 0;
|
|
75
|
+
const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
|
|
76
|
+
|
|
77
|
+
// Allow matching when typing a trigger + the match string or when
|
|
78
|
+
// clicking in an existing trigger word on the page.
|
|
79
|
+
// E.g. "Some text @a" — "@a" is detected as a trigger word.
|
|
80
|
+
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
81
|
+
|
|
82
|
+
// Allow matching when backspacing near a trigger word (up to 3
|
|
83
|
+
// words from the trigger character). This lets us recover from a
|
|
84
|
+
// mismatch when backspacing while still imposing sane limits.
|
|
85
|
+
// E.g. "Some text @marcelo sekkkk" — backspacing "kkkk" re-shows
|
|
86
|
+
// the popup once the text matches again.
|
|
87
|
+
const matchingWhileBackspacing =
|
|
88
|
+
isBackspacing && wordsFromTrigger.length <= 3;
|
|
89
|
+
|
|
90
|
+
if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (
|
|
95
|
+
allowContext &&
|
|
96
|
+
! allowContext(
|
|
97
|
+
textContent.slice( 0, triggerIndex ),
|
|
98
|
+
getTextAfterSelection()
|
|
99
|
+
)
|
|
100
|
+
) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (
|
|
105
|
+
/^\s/.test( textWithoutTrigger ) ||
|
|
106
|
+
/\s\s+$/.test( textWithoutTrigger )
|
|
107
|
+
) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
completer,
|
|
113
|
+
filterValue: removeAccents( textWithoutTrigger ),
|
|
114
|
+
};
|
|
115
|
+
}
|