@wordpress/components 25.8.12 → 25.8.14

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.
@@ -22,6 +22,8 @@ import {
22
22
  isCollapsed,
23
23
  getTextContent,
24
24
  } from '@wordpress/rich-text';
25
+ import { speak } from '@wordpress/a11y';
26
+ import { isAppleOS } from '@wordpress/keycodes';
25
27
 
26
28
  /**
27
29
  * Internal dependencies
@@ -39,6 +41,35 @@ import type {
39
41
  WPCompleter,
40
42
  } from './types';
41
43
 
44
+ const getNodeText = ( node: React.ReactNode ): string => {
45
+ if ( node === null ) {
46
+ return '';
47
+ }
48
+
49
+ switch ( typeof node ) {
50
+ case 'string':
51
+ case 'number':
52
+ return node.toString();
53
+ break;
54
+ case 'boolean':
55
+ return '';
56
+ break;
57
+ case 'object': {
58
+ if ( node instanceof Array ) {
59
+ return node.map( getNodeText ).join( '' );
60
+ }
61
+ if ( 'props' in node ) {
62
+ return getNodeText( node.props.children );
63
+ }
64
+ break;
65
+ }
66
+ default:
67
+ return '';
68
+ }
69
+
70
+ return '';
71
+ };
72
+
42
73
  const EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];
43
74
 
44
75
  export function useAutocomplete( {
@@ -163,20 +194,35 @@ export function useAutocomplete( {
163
194
  ) {
164
195
  return;
165
196
  }
197
+
166
198
  switch ( event.key ) {
167
- case 'ArrowUp':
168
- setSelectedIndex(
199
+ case 'ArrowUp': {
200
+ const newIndex =
169
201
  ( selectedIndex === 0
170
202
  ? filteredOptions.length
171
- : selectedIndex ) - 1
172
- );
203
+ : selectedIndex ) - 1;
204
+ setSelectedIndex( newIndex );
205
+ // See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.
206
+ if ( isAppleOS() ) {
207
+ speak(
208
+ getNodeText( filteredOptions[ newIndex ].label ),
209
+ 'assertive'
210
+ );
211
+ }
173
212
  break;
213
+ }
174
214
 
175
- case 'ArrowDown':
176
- setSelectedIndex(
177
- ( selectedIndex + 1 ) % filteredOptions.length
178
- );
215
+ case 'ArrowDown': {
216
+ const newIndex = ( selectedIndex + 1 ) % filteredOptions.length;
217
+ setSelectedIndex( newIndex );
218
+ if ( isAppleOS() ) {
219
+ speak(
220
+ getNodeText( filteredOptions[ newIndex ].label ),
221
+ 'assertive'
222
+ );
223
+ }
179
224
  break;
225
+ }
180
226
 
181
227
  case 'Escape':
182
228
  setAutocompleter( null );
@@ -35,9 +35,9 @@ export const Slot = forwardRef( ( { bubblesVirtually, ...props }, ref ) => {
35
35
  return <BaseSlot { ...props } />;
36
36
  } );
37
37
 
38
- export function Provider( { children, ...props } ) {
38
+ export function Provider( { children, passthrough = false, ...props } ) {
39
39
  const parent = useContext( SlotFillContext );
40
- if ( ! parent.isDefault ) {
40
+ if ( ! parent.isDefault && passthrough ) {
41
41
  return children;
42
42
  }
43
43
  return (