@wordpress/components 26.0.2 → 27.0.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.
Files changed (223) hide show
  1. package/.stylelintrc.js +2 -2
  2. package/CHANGELOG.md +23 -0
  3. package/CONTRIBUTING.md +72 -0
  4. package/build/autocomplete/index.js +3 -8
  5. package/build/autocomplete/index.js.map +1 -1
  6. package/build/color-picker/component.js +10 -1
  7. package/build/color-picker/component.js.map +1 -1
  8. package/build/color-picker/styles.js +8 -9
  9. package/build/color-picker/styles.js.map +1 -1
  10. package/build/combobox-control/index.js +4 -9
  11. package/build/combobox-control/index.js.map +1 -1
  12. package/build/custom-select-control/index.js +2 -15
  13. package/build/custom-select-control/index.js.map +1 -1
  14. package/build/custom-select-control-v2/custom-select-item.js +32 -0
  15. package/build/custom-select-control-v2/custom-select-item.js.map +1 -0
  16. package/build/custom-select-control-v2/custom-select.js +91 -0
  17. package/build/custom-select-control-v2/custom-select.js.map +1 -0
  18. package/build/custom-select-control-v2/default-component/index.js +41 -0
  19. package/build/custom-select-control-v2/default-component/index.js.map +1 -0
  20. package/build/custom-select-control-v2/index.js +13 -82
  21. package/build/custom-select-control-v2/index.js.map +1 -1
  22. package/build/custom-select-control-v2/legacy-adapter.js +29 -0
  23. package/build/custom-select-control-v2/legacy-adapter.js.map +1 -0
  24. package/build/custom-select-control-v2/legacy-component/index.js +123 -0
  25. package/build/custom-select-control-v2/legacy-component/index.js.map +1 -0
  26. package/build/custom-select-control-v2/styles.js +73 -50
  27. package/build/custom-select-control-v2/styles.js.map +1 -1
  28. package/build/custom-select-control-v2/types.js.map +1 -1
  29. package/build/font-size-picker/font-size-picker-select.js +0 -1
  30. package/build/font-size-picker/font-size-picker-select.js.map +1 -1
  31. package/build/form-token-field/index.js +3 -8
  32. package/build/form-token-field/index.js.map +1 -1
  33. package/build/form-token-field/suggestions-list.js +5 -12
  34. package/build/form-token-field/suggestions-list.js.map +1 -1
  35. package/build/mobile/keyboard-aware-flat-list/use-scroll-to-section.native.js +1 -1
  36. package/build/mobile/keyboard-aware-flat-list/use-scroll-to-section.native.js.map +1 -1
  37. package/build/modal/index.js +2 -10
  38. package/build/modal/index.js.map +1 -1
  39. package/build/progress-bar/styles.js +5 -5
  40. package/build/progress-bar/styles.js.map +1 -1
  41. package/build/utils/with-ignore-ime-events.js +34 -0
  42. package/build/utils/with-ignore-ime-events.js.map +1 -0
  43. package/build-module/autocomplete/index.js +3 -8
  44. package/build-module/autocomplete/index.js.map +1 -1
  45. package/build-module/color-picker/component.js +11 -2
  46. package/build-module/color-picker/component.js.map +1 -1
  47. package/build-module/color-picker/styles.js +8 -9
  48. package/build-module/color-picker/styles.js.map +1 -1
  49. package/build-module/combobox-control/index.js +4 -9
  50. package/build-module/combobox-control/index.js.map +1 -1
  51. package/build-module/custom-select-control/index.js +2 -15
  52. package/build-module/custom-select-control/index.js.map +1 -1
  53. package/build-module/custom-select-control-v2/custom-select-item.js +26 -0
  54. package/build-module/custom-select-control-v2/custom-select-item.js.map +1 -0
  55. package/build-module/custom-select-control-v2/custom-select.js +82 -0
  56. package/build-module/custom-select-control-v2/custom-select.js.map +1 -0
  57. package/build-module/custom-select-control-v2/default-component/index.js +30 -0
  58. package/build-module/custom-select-control-v2/default-component/index.js.map +1 -0
  59. package/build-module/custom-select-control-v2/index.js +2 -74
  60. package/build-module/custom-select-control-v2/index.js.map +1 -1
  61. package/build-module/custom-select-control-v2/legacy-adapter.js +21 -0
  62. package/build-module/custom-select-control-v2/legacy-adapter.js.map +1 -0
  63. package/build-module/custom-select-control-v2/legacy-component/index.js +111 -0
  64. package/build-module/custom-select-control-v2/legacy-component/index.js.map +1 -0
  65. package/build-module/custom-select-control-v2/styles.js +73 -42
  66. package/build-module/custom-select-control-v2/styles.js.map +1 -1
  67. package/build-module/custom-select-control-v2/types.js.map +1 -1
  68. package/build-module/font-size-picker/font-size-picker-select.js +0 -1
  69. package/build-module/font-size-picker/font-size-picker-select.js.map +1 -1
  70. package/build-module/form-token-field/index.js +3 -8
  71. package/build-module/form-token-field/index.js.map +1 -1
  72. package/build-module/form-token-field/suggestions-list.js +5 -12
  73. package/build-module/form-token-field/suggestions-list.js.map +1 -1
  74. package/build-module/mobile/keyboard-aware-flat-list/use-scroll-to-section.native.js +1 -1
  75. package/build-module/mobile/keyboard-aware-flat-list/use-scroll-to-section.native.js.map +1 -1
  76. package/build-module/modal/index.js +3 -10
  77. package/build-module/modal/index.js.map +1 -1
  78. package/build-module/progress-bar/styles.js +5 -5
  79. package/build-module/progress-bar/styles.js.map +1 -1
  80. package/build-module/utils/with-ignore-ime-events.js +28 -0
  81. package/build-module/utils/with-ignore-ime-events.js.map +1 -0
  82. package/build-style/style-rtl.css +8 -1
  83. package/build-style/style.css +8 -1
  84. package/build-types/alignment-matrix-control/stories/index.story.d.ts +1 -1
  85. package/build-types/angle-picker-control/stories/index.story.d.ts +1 -1
  86. package/build-types/animate/stories/index.story.d.ts +7 -7
  87. package/build-types/autocomplete/index.d.ts.map +1 -1
  88. package/build-types/base-control/stories/index.story.d.ts +1 -1
  89. package/build-types/border-box-control/stories/index.story.d.ts +1 -1
  90. package/build-types/border-control/stories/index.story.d.ts +6 -6
  91. package/build-types/box-control/stories/index.story.d.ts +6 -6
  92. package/build-types/button/stories/e2e/index.story.d.ts +1 -1
  93. package/build-types/button/stories/index.story.d.ts +7 -7
  94. package/build-types/card/stories/index.story.d.ts +2 -2
  95. package/build-types/circular-option-picker/stories/index.story.d.ts +5 -5
  96. package/build-types/color-palette/stories/index.story.d.ts +3 -3
  97. package/build-types/color-picker/component.d.ts.map +1 -1
  98. package/build-types/color-picker/stories/index.story.d.ts +1 -1
  99. package/build-types/color-picker/styles.d.ts.map +1 -1
  100. package/build-types/combobox-control/index.d.ts.map +1 -1
  101. package/build-types/combobox-control/stories/index.story.d.ts +2 -2
  102. package/build-types/confirm-dialog/stories/index.story.d.ts +2 -2
  103. package/build-types/custom-gradient-picker/stories/index.story.d.ts +1 -1
  104. package/build-types/custom-select-control/index.d.ts.map +1 -1
  105. package/build-types/custom-select-control-v2/custom-select-item.d.ts +9 -0
  106. package/build-types/custom-select-control-v2/custom-select-item.d.ts.map +1 -0
  107. package/build-types/custom-select-control-v2/custom-select.d.ts +6 -0
  108. package/build-types/custom-select-control-v2/custom-select.d.ts.map +1 -0
  109. package/build-types/custom-select-control-v2/default-component/index.d.ts +5 -0
  110. package/build-types/custom-select-control-v2/default-component/index.d.ts.map +1 -0
  111. package/build-types/custom-select-control-v2/index.d.ts +5 -6
  112. package/build-types/custom-select-control-v2/index.d.ts.map +1 -1
  113. package/build-types/custom-select-control-v2/legacy-adapter.d.ts +6 -0
  114. package/build-types/custom-select-control-v2/legacy-adapter.d.ts.map +1 -0
  115. package/build-types/custom-select-control-v2/legacy-component/index.d.ts +5 -0
  116. package/build-types/custom-select-control-v2/legacy-component/index.d.ts.map +1 -0
  117. package/build-types/custom-select-control-v2/stories/default.story.d.ts +29 -0
  118. package/build-types/custom-select-control-v2/stories/default.story.d.ts.map +1 -0
  119. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts +12 -0
  120. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts.map +1 -0
  121. package/build-types/custom-select-control-v2/styles.d.ts +31 -6
  122. package/build-types/custom-select-control-v2/styles.d.ts.map +1 -1
  123. package/build-types/custom-select-control-v2/types.d.ts +137 -14
  124. package/build-types/custom-select-control-v2/types.d.ts.map +1 -1
  125. package/build-types/dimension-control/stories/index.story.d.ts +2 -2
  126. package/build-types/drop-zone/stories/index.story.d.ts +1 -1
  127. package/build-types/dropdown/stories/index.story.d.ts +3 -3
  128. package/build-types/dropdown-menu/stories/index.story.d.ts +2 -2
  129. package/build-types/dropdown-menu-v2/stories/index.story.d.ts.map +1 -1
  130. package/build-types/duotone-picker/stories/duotone-picker.story.d.ts +1 -1
  131. package/build-types/duotone-picker/stories/duotone-swatch.story.d.ts +3 -3
  132. package/build-types/focal-point-picker/stories/index.story.d.ts +4 -4
  133. package/build-types/font-size-picker/font-size-picker-select.d.ts.map +1 -1
  134. package/build-types/form-file-upload/stories/index.story.d.ts +5 -5
  135. package/build-types/form-token-field/index.d.ts.map +1 -1
  136. package/build-types/form-token-field/suggestions-list.d.ts.map +1 -1
  137. package/build-types/gradient-picker/stories/index.story.d.ts +3 -3
  138. package/build-types/guide/stories/index.story.d.ts +1 -1
  139. package/build-types/icon/stories/index.story.d.ts +4 -4
  140. package/build-types/input-control/stories/index.story.d.ts +6 -6
  141. package/build-types/keyboard-shortcuts/stories/index.story.d.ts +1 -1
  142. package/build-types/menu-group/stories/index.story.d.ts +1 -1
  143. package/build-types/menu-item/stories/index.story.d.ts +4 -4
  144. package/build-types/modal/index.d.ts.map +1 -1
  145. package/build-types/navigation/stories/index.story.d.ts +6 -6
  146. package/build-types/notice/stories/index.story.d.ts +4 -4
  147. package/build-types/number-control/stories/index.story.d.ts +1 -1
  148. package/build-types/palette-edit/stories/index.story.d.ts +2 -2
  149. package/build-types/progress-bar/stories/index.story.d.ts.map +1 -1
  150. package/build-types/query-controls/stories/index.story.d.ts +1 -1
  151. package/build-types/resizable-box/stories/index.story.d.ts +2 -2
  152. package/build-types/responsive-wrapper/stories/index.story.d.ts +1 -1
  153. package/build-types/sandbox/stories/index.story.d.ts +1 -1
  154. package/build-types/search-control/stories/index.story.d.ts +2 -2
  155. package/build-types/select-control/stories/index.story.d.ts +2 -2
  156. package/build-types/shortcut/stories/index.story.d.ts +1 -1
  157. package/build-types/tab-panel/stories/index.story.d.ts +4 -4
  158. package/build-types/tabs/stories/index.story.d.ts +9 -9
  159. package/build-types/tabs/stories/index.story.d.ts.map +1 -1
  160. package/build-types/text/stories/index.story.d.ts +3 -3
  161. package/build-types/theme/stories/index.story.d.ts +1 -1
  162. package/build-types/theme/stories/index.story.d.ts.map +1 -1
  163. package/build-types/toggle-control/stories/index.story.d.ts +2 -2
  164. package/build-types/toolbar/stories/index.story.d.ts +3 -3
  165. package/build-types/tooltip/stories/index.story.d.ts +1 -1
  166. package/build-types/tree-grid/stories/index.story.d.ts +1 -1
  167. package/build-types/tree-select/stories/index.story.d.ts +1 -1
  168. package/build-types/utils/with-ignore-ime-events.d.ts +15 -0
  169. package/build-types/utils/with-ignore-ime-events.d.ts.map +1 -0
  170. package/build-types/v-stack/stories/index.story.d.ts +1 -1
  171. package/package.json +19 -20
  172. package/src/alignment-matrix-control/test/index.tsx +3 -1
  173. package/src/autocomplete/index.tsx +3 -10
  174. package/src/circular-option-picker/test/index.tsx +4 -1
  175. package/src/color-picker/component.tsx +22 -11
  176. package/src/color-picker/styles.ts +1 -15
  177. package/src/combobox-control/index.tsx +33 -41
  178. package/src/composite/legacy/test/index.tsx +18 -2
  179. package/src/custom-select-control/README.md +0 -10
  180. package/src/custom-select-control/index.js +3 -22
  181. package/src/custom-select-control/stories/index.story.js +0 -1
  182. package/src/custom-select-control/test/index.js +17 -17
  183. package/src/custom-select-control-v2/README.md +97 -7
  184. package/src/custom-select-control-v2/custom-select-item.tsx +29 -0
  185. package/src/custom-select-control-v2/custom-select.tsx +122 -0
  186. package/src/custom-select-control-v2/default-component/index.tsx +24 -0
  187. package/src/custom-select-control-v2/index.tsx +2 -102
  188. package/src/custom-select-control-v2/legacy-adapter.tsx +25 -0
  189. package/src/custom-select-control-v2/legacy-component/index.tsx +133 -0
  190. package/src/custom-select-control-v2/stories/{index.story.tsx → default.story.tsx} +27 -33
  191. package/src/custom-select-control-v2/stories/legacy.story.tsx +88 -0
  192. package/src/custom-select-control-v2/styles.ts +82 -38
  193. package/src/custom-select-control-v2/test/index.tsx +808 -148
  194. package/src/custom-select-control-v2/types.ts +148 -20
  195. package/src/dropdown-menu-v2/stories/index.story.tsx +1 -0
  196. package/src/dropdown-menu-v2/test/index.tsx +4 -1
  197. package/src/font-size-picker/font-size-picker-select.tsx +0 -1
  198. package/src/form-token-field/index.tsx +3 -10
  199. package/src/form-token-field/suggestions-list.tsx +5 -17
  200. package/src/mobile/keyboard-aware-flat-list/use-scroll-to-section.native.js +1 -1
  201. package/src/modal/index.tsx +2 -12
  202. package/src/modal/style.scss +1 -0
  203. package/src/progress-bar/stories/index.story.tsx +1 -0
  204. package/src/progress-bar/styles.ts +2 -2
  205. package/src/tab-panel/test/index.tsx +8 -1
  206. package/src/tabs/stories/index.story.tsx +1 -0
  207. package/src/tabs/test/index.tsx +36 -6
  208. package/src/theme/stories/index.story.tsx +1 -0
  209. package/src/toggle-group-control/test/index.tsx +4 -0
  210. package/src/toolbar/toolbar-group/style.scss +1 -0
  211. package/src/tooltip/test/index.tsx +5 -0
  212. package/src/utils/with-ignore-ime-events.ts +32 -0
  213. package/tsconfig.json +0 -1
  214. package/tsconfig.tsbuildinfo +1 -1
  215. package/build/custom-select-control/styles.js +0 -27
  216. package/build/custom-select-control/styles.js.map +0 -1
  217. package/build-module/custom-select-control/styles.js +0 -18
  218. package/build-module/custom-select-control/styles.js.map +0 -1
  219. package/build-types/custom-select-control/styles.d.ts +0 -11
  220. package/build-types/custom-select-control/styles.d.ts.map +0 -1
  221. package/build-types/custom-select-control-v2/stories/index.story.d.ts +0 -20
  222. package/build-types/custom-select-control-v2/stories/index.story.d.ts.map +0 -1
  223. package/src/custom-select-control/styles.ts +0 -28
@@ -3,30 +3,23 @@
3
3
  */
4
4
  // eslint-disable-next-line no-restricted-imports
5
5
  import type * as Ariakit from '@ariakit/react';
6
+ import type { FocusEventHandler, MouseEventHandler } from 'react';
6
7
 
7
- export type CustomSelectContext =
8
- | {
9
- /**
10
- * The store object returned by Ariakit's `useSelectStore` hook.
11
- */
12
- store: Ariakit.SelectStore;
13
- }
14
- | undefined;
15
-
16
- export type CustomSelectProps = {
8
+ export type CustomSelectStore = {
17
9
  /**
18
- * The child elements. This should be composed of CustomSelectItem components.
10
+ * The store object returned by Ariakit's `useSelectStore` hook.
19
11
  */
20
- children: React.ReactNode;
12
+ store: Ariakit.SelectStore;
13
+ };
14
+
15
+ export type CustomSelectContext = CustomSelectStore | undefined;
16
+
17
+ export type CustomSelectButtonProps = {
21
18
  /**
22
- * An optional default value for the control. If left `undefined`, the first
23
- * non-disabled item will be used.
19
+ * An optional default value for the control when used in uncontrolled mode.
20
+ * If left `undefined`, the first non-disabled item will be used.
24
21
  */
25
22
  defaultValue?: string | string[];
26
- /**
27
- * Label for the control.
28
- */
29
- label: string;
30
23
  /**
31
24
  * A function that receives the new value of the input.
32
25
  */
@@ -42,13 +35,148 @@ export type CustomSelectProps = {
42
35
  *
43
36
  * @default 'default'
44
37
  */
45
- size?: 'default' | 'small';
38
+ size?: 'compact' | 'default' | 'small';
46
39
  /**
47
- * Can be used to externally control the value of the control.
40
+ * The value of the control when used in uncontrolled mode.
48
41
  */
49
42
  value?: string | string[];
50
43
  };
51
44
 
45
+ export type _CustomSelectProps = {
46
+ /**
47
+ * The child elements. This should be composed of `CustomSelectItem` components.
48
+ */
49
+ children: React.ReactNode;
50
+ /**
51
+ * Used to visually hide the label. It will always be visible to screen readers.
52
+ *
53
+ * @default false
54
+ */
55
+ hideLabelFromVision?: boolean;
56
+ /**
57
+ * Accessible label for the control.
58
+ */
59
+ label: string;
60
+ };
61
+
62
+ export type CustomSelectProps = _CustomSelectProps &
63
+ Omit< CustomSelectButtonProps, 'size' > & {
64
+ /**
65
+ * The size of the control.
66
+ *
67
+ * @default 'default'
68
+ */
69
+ size?: Exclude< CustomSelectButtonProps[ 'size' ], 'small' >;
70
+ };
71
+
72
+ /**
73
+ * The legacy object structure for the options array.
74
+ */
75
+ type LegacyOption = {
76
+ key: string;
77
+ name: string;
78
+ style?: React.CSSProperties;
79
+ className?: string;
80
+ __experimentalHint?: string;
81
+ };
82
+
83
+ /**
84
+ * The legacy object returned from the onChange event.
85
+ */
86
+ type LegacyOnChangeObject = {
87
+ highlightedIndex?: number;
88
+ inputValue?: string;
89
+ isOpen?: boolean;
90
+ type?: string;
91
+ selectedItem: LegacyOption;
92
+ };
93
+
94
+ export type LegacyCustomSelectProps = {
95
+ children?: never;
96
+ /**
97
+ * Optional classname for the component.
98
+ */
99
+ className?: string;
100
+ /**
101
+ * Used to visually hide the label. It will always be visible to screen readers.
102
+ *
103
+ */
104
+ hideLabelFromVision?: boolean;
105
+ /**
106
+ * Pass in a description that will be shown to screen readers associated with the
107
+ * select trigger button. If no value is passed, the text "Currently selected:
108
+ * selectedItem.name" will be used fully translated.
109
+ */
110
+ describedBy?: string;
111
+ /**
112
+ * Label for the control.
113
+ */
114
+ label: string;
115
+ /**
116
+ * Function called with the control's internal state changes. The `selectedItem`
117
+ * property contains the next selected item.
118
+ */
119
+ onChange?: ( newValue: LegacyOnChangeObject ) => void;
120
+ /**
121
+ * A handler for `onBlur` events.
122
+ *
123
+ * @ignore
124
+ */
125
+ onBlur?: FocusEventHandler< HTMLButtonElement >;
126
+ /**
127
+ * A handler for `onFocus` events.
128
+ *
129
+ * @ignore
130
+ */
131
+ onFocus?: FocusEventHandler< HTMLButtonElement >;
132
+ /**
133
+ * A handler for `onMouseOver` events.
134
+ *
135
+ * @ignore
136
+ */
137
+ onMouseOut?: MouseEventHandler< HTMLButtonElement >;
138
+ /**
139
+ * A handler for `onMouseOut` events.
140
+ *
141
+ * @ignore
142
+ */
143
+ onMouseOver?: MouseEventHandler< HTMLButtonElement >;
144
+ /**
145
+ * The options that can be chosen from.
146
+ */
147
+ options: Array< LegacyOption >;
148
+ /**
149
+ * The size of the control.
150
+ *
151
+ * @default 'default'
152
+ */
153
+ size?: 'default' | 'small' | '__unstable-large';
154
+ /**
155
+ * Can be used to externally control the value of the control.
156
+ */
157
+ value?: LegacyOption;
158
+ /**
159
+ * Legacy way to add additional text to the right of each option.
160
+ *
161
+ * @default false
162
+ */
163
+ __experimentalShowSelectedHint?: boolean;
164
+ /**
165
+ * Opt-in prop for an unconstrained width style which became the default in
166
+ * WordPress 6.5. The prop is no longer needed and can be safely removed.
167
+ *
168
+ * @deprecated
169
+ * @ignore
170
+ */
171
+ __nextUnconstrainedWidth?: boolean;
172
+ /**
173
+ * Start opting into the larger default height that will become the default size in a future version.
174
+ *
175
+ * @default false
176
+ */
177
+ __next40pxDefaultSize?: boolean;
178
+ };
179
+
52
180
  export type CustomSelectItemProps = {
53
181
  /**
54
182
  * The value of the select item. This will be used as the children if
@@ -56,6 +56,7 @@ const meta: Meta< typeof DropdownMenu > = {
56
56
  children: { control: { type: null } },
57
57
  trigger: { control: { type: null } },
58
58
  },
59
+ tags: [ 'status-private' ],
59
60
  parameters: {
60
61
  actions: { argTypesRegex: '^on.*' },
61
62
  badges: [ 'private' ],
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { render, screen, waitFor } from '@testing-library/react';
5
- import { press, click, hover, type } from '@ariakit/test';
5
+ import { press, click, hover, sleep, type } from '@ariakit/test';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -123,6 +123,7 @@ describe( 'DropdownMenu', () => {
123
123
  } );
124
124
 
125
125
  // Move focus on the toggle
126
+ await sleep();
126
127
  await press.Tab();
127
128
 
128
129
  expect( toggleButton ).toHaveFocus();
@@ -153,6 +154,7 @@ describe( 'DropdownMenu', () => {
153
154
  } );
154
155
 
155
156
  // Move focus on the toggle
157
+ await sleep();
156
158
  await press.Tab();
157
159
 
158
160
  expect( toggleButton ).toHaveFocus();
@@ -908,6 +910,7 @@ describe( 'DropdownMenu', () => {
908
910
 
909
911
  // The outer button can be focused by pressing tab. Doing so will cause
910
912
  // the DropdownMenu to close.
913
+ await sleep();
911
914
  await press.Tab();
912
915
  expect( outerButton ).toBeInTheDocument();
913
916
  expect( screen.queryByRole( 'menu' ) ).not.toBeInTheDocument();
@@ -69,7 +69,6 @@ const FontSizePickerSelect = ( props: FontSizePickerSelectProps ) => {
69
69
  return (
70
70
  <CustomSelectControl
71
71
  __next40pxDefaultSize={ __next40pxDefaultSize }
72
- __nextUnconstrainedWidth
73
72
  className="components-font-size-picker__select"
74
73
  label={ __( 'Font size' ) }
75
74
  hideLabelFromVision
@@ -28,6 +28,7 @@ import {
28
28
  } from '../base-control/styles/base-control-styles';
29
29
  import { Spacer } from '../spacer';
30
30
  import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props';
31
+ import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events';
31
32
 
32
33
  const identity = ( value: string ) => value;
33
34
 
@@ -194,15 +195,7 @@ export function FormTokenField( props: FormTokenFieldProps ) {
194
195
  function onKeyDown( event: KeyboardEvent ) {
195
196
  let preventDefault = false;
196
197
 
197
- if (
198
- event.defaultPrevented ||
199
- // Ignore keydowns from IMEs
200
- event.nativeEvent.isComposing ||
201
- // Workaround for Mac Safari where the final Enter/Backspace of an IME composition
202
- // is `isComposing=false`, even though it's technically still part of the composition.
203
- // These can only be detected by keyCode.
204
- event.keyCode === 229
205
- ) {
198
+ if ( event.defaultPrevented ) {
206
199
  return;
207
200
  }
208
201
  switch ( event.key ) {
@@ -689,7 +682,7 @@ export function FormTokenField( props: FormTokenFieldProps ) {
689
682
 
690
683
  if ( ! disabled ) {
691
684
  tokenFieldProps = Object.assign( {}, tokenFieldProps, {
692
- onKeyDown,
685
+ onKeyDown: withIgnoreIMEEvents( onKeyDown ),
693
686
  onKeyPress,
694
687
  onFocus: onFocusHandler,
695
688
  } );
@@ -1,14 +1,12 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import scrollView from 'dom-scroll-into-view';
5
4
  import classnames from 'classnames';
6
5
  import type { MouseEventHandler, ReactNode } from 'react';
7
6
 
8
7
  /**
9
8
  * WordPress dependencies
10
9
  */
11
- import { useState } from '@wordpress/element';
12
10
  import { useRefEffect } from '@wordpress/compose';
13
11
 
14
12
  /**
@@ -32,8 +30,6 @@ export function SuggestionsList< T extends string | { value: string } >( {
32
30
  instanceId,
33
31
  __experimentalRenderItem,
34
32
  }: SuggestionsListProps< T > ) {
35
- const [ scrollingIntoView, setScrollingIntoView ] = useState( false );
36
-
37
33
  const listRef = useRefEffect< HTMLUListElement >(
38
34
  ( listNode ) => {
39
35
  // only have to worry about scrolling selected suggestion into view
@@ -44,16 +40,10 @@ export function SuggestionsList< T extends string | { value: string } >( {
44
40
  scrollIntoView &&
45
41
  listNode.children[ selectedIndex ]
46
42
  ) {
47
- setScrollingIntoView( true );
48
- scrollView(
49
- listNode.children[ selectedIndex ] as HTMLLIElement,
50
- listNode,
51
- {
52
- onlyScrollIfNeeded: true,
53
- }
54
- );
55
- rafId = requestAnimationFrame( () => {
56
- setScrollingIntoView( false );
43
+ listNode.children[ selectedIndex ].scrollIntoView( {
44
+ behavior: 'instant',
45
+ block: 'nearest',
46
+ inline: 'nearest',
57
47
  } );
58
48
  }
59
49
 
@@ -68,9 +58,7 @@ export function SuggestionsList< T extends string | { value: string } >( {
68
58
 
69
59
  const handleHover = ( suggestion: T ) => {
70
60
  return () => {
71
- if ( ! scrollingIntoView ) {
72
- onHover?.( suggestion );
73
- }
61
+ onHover?.( suggestion );
74
62
  };
75
63
  };
76
64
 
@@ -45,7 +45,7 @@ export default function useScrollToSection(
45
45
  if (
46
46
  ! scrollViewRef.current ||
47
47
  ! scrollEnabled ||
48
- ! scrollViewMeasurements
48
+ ! scrollViewMeasurements.current
49
49
  ) {
50
50
  return;
51
51
  }
@@ -41,6 +41,7 @@ import * as ariaHelper from './aria-helper';
41
41
  import Button from '../button';
42
42
  import StyleProvider from '../style-provider';
43
43
  import type { ModalProps } from './types';
44
+ import { withIgnoreIMEEvents } from '../utils/with-ignore-ime-events';
44
45
 
45
46
  // Used to track and dismiss the prior modal when another opens unless nested.
46
47
  const ModalContext = createContext<
@@ -196,17 +197,6 @@ function UnforwardedModal(
196
197
  }, [ isContentScrollable, childrenContainerRef ] );
197
198
 
198
199
  function handleEscapeKeyDown( event: KeyboardEvent< HTMLDivElement > ) {
199
- if (
200
- // Ignore keydowns from IMEs
201
- event.nativeEvent.isComposing ||
202
- // Workaround for Mac Safari where the final Enter/Backspace of an IME composition
203
- // is `isComposing=false`, even though it's technically still part of the composition.
204
- // These can only be detected by keyCode.
205
- event.keyCode === 229
206
- ) {
207
- return;
208
- }
209
-
210
200
  if (
211
201
  shouldCloseOnEsc &&
212
202
  ( event.code === 'Escape' || event.key === 'Escape' ) &&
@@ -265,7 +255,7 @@ function UnforwardedModal(
265
255
  'components-modal__screen-overlay',
266
256
  overlayClassName
267
257
  ) }
268
- onKeyDown={ handleEscapeKeyDown }
258
+ onKeyDown={ withIgnoreIMEEvents( handleEscapeKeyDown ) }
269
259
  { ...( shouldCloseOnClickOutside ? overlayPressHandlers : {} ) }
270
260
  >
271
261
  <StyleProvider document={ document }>
@@ -15,6 +15,7 @@
15
15
 
16
16
  // The modal window element.
17
17
  .components-modal__frame {
18
+ @include reset;
18
19
  // Use the entire viewport on smaller screens.
19
20
  margin: $grid-unit-50 0 0 0;
20
21
  width: 100%;
@@ -14,6 +14,7 @@ const meta: Meta< typeof ProgressBar > = {
14
14
  argTypes: {
15
15
  value: { control: { type: 'number', min: 0, max: 100, step: 1 } },
16
16
  },
17
+ tags: [ 'status-private' ],
17
18
  parameters: {
18
19
  badges: [ 'private' ],
19
20
  controls: {
@@ -30,7 +30,7 @@ export const Track = styled.div`
30
30
  /* Text color at 10% opacity */
31
31
  background-color: color-mix(
32
32
  in srgb,
33
- var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ),
33
+ ${ COLORS.theme.foreground },
34
34
  transparent 90%
35
35
  );
36
36
  border-radius: ${ CONFIG.radiusBlockUi };
@@ -52,7 +52,7 @@ export const Indicator = styled.div< {
52
52
  /* Text color at 90% opacity */
53
53
  background-color: color-mix(
54
54
  in srgb,
55
- var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ),
55
+ ${ COLORS.theme.foreground },
56
56
  transparent 10%
57
57
  );
58
58
 
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { render, screen, waitFor } from '@testing-library/react';
5
- import { press, hover, click } from '@ariakit/test';
5
+ import { press, hover, click, sleep } from '@ariakit/test';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -155,6 +155,7 @@ describe.each( [
155
155
  // Tab to focus the tablist. Make sure alpha is focused, and that the
156
156
  // corresponding tooltip is shown.
157
157
  expect( screen.queryByText( 'Alpha' ) ).not.toBeInTheDocument();
158
+ await sleep();
158
159
  await press.Tab();
159
160
  expect( mockOnSelect ).toHaveBeenCalledTimes( 1 );
160
161
  expect( screen.getByText( 'Alpha' ) ).toBeInTheDocument();
@@ -626,6 +627,7 @@ describe.each( [
626
627
  // Tab to focus the tablist. Make sure alpha is focused.
627
628
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
628
629
  expect( await getSelectedTab() ).not.toHaveFocus();
630
+ await sleep();
629
631
  await press.Tab();
630
632
  expect( await getSelectedTab() ).toHaveFocus();
631
633
 
@@ -663,6 +665,7 @@ describe.each( [
663
665
  // Tab to focus the tablist. Make sure Alpha is focused.
664
666
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
665
667
  expect( await getSelectedTab() ).not.toHaveFocus();
668
+ await sleep();
666
669
  await press.Tab();
667
670
  expect( await getSelectedTab() ).toHaveFocus();
668
671
 
@@ -700,6 +703,7 @@ describe.each( [
700
703
  // Tab to focus the tablist. Make sure alpha is focused.
701
704
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
702
705
  expect( await getSelectedTab() ).not.toHaveFocus();
706
+ await sleep();
703
707
  await press.Tab();
704
708
  expect( await getSelectedTab() ).toHaveFocus();
705
709
 
@@ -795,6 +799,7 @@ describe.each( [
795
799
  // Tab to focus the tablist. Make sure Alpha is focused.
796
800
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
797
801
  expect( await getSelectedTab() ).not.toHaveFocus();
802
+ await sleep();
798
803
  await press.Tab();
799
804
  expect( await getSelectedTab() ).toHaveFocus();
800
805
  expect( mockOnSelect ).toHaveBeenCalledTimes( 1 );
@@ -836,6 +841,7 @@ describe.each( [
836
841
 
837
842
  // Tab should initially focus the first tab in the tablist, which
838
843
  // is Alpha.
844
+ await sleep();
839
845
  await press.Tab();
840
846
  expect(
841
847
  await screen.findByRole( 'tab', { name: 'Alpha' } )
@@ -843,6 +849,7 @@ describe.each( [
843
849
 
844
850
  // Because all other tabs should have `tabindex=-1`, pressing Tab
845
851
  // should NOT move the focus to the next tab, which is Beta.
852
+ await sleep();
846
853
  await press.Tab();
847
854
  expect(
848
855
  await screen.findByRole( 'tab', { name: 'Beta' } )
@@ -28,6 +28,7 @@ const meta: Meta< typeof Tabs > = {
28
28
  // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
29
29
  'Tabs.TabPanel': Tabs.TabPanel,
30
30
  },
31
+ tags: [ 'status-private' ],
31
32
  parameters: {
32
33
  actions: { argTypesRegex: '^on.*' },
33
34
  badges: [ 'private' ],
@@ -2,7 +2,7 @@
2
2
  * External dependencies
3
3
  */
4
4
  import { render, screen, waitFor } from '@testing-library/react';
5
- import { press, click } from '@ariakit/test';
5
+ import { press, click, sleep } from '@ariakit/test';
6
6
 
7
7
  /**
8
8
  * WordPress dependencies
@@ -194,12 +194,14 @@ describe( 'Tabs', () => {
194
194
 
195
195
  // Tab should initially focus the first tab in the tablist, which
196
196
  // is Alpha.
197
+ await sleep();
197
198
  await press.Tab();
198
199
  expect(
199
200
  await screen.findByRole( 'tab', { name: 'Alpha' } )
200
201
  ).toHaveFocus();
201
202
 
202
203
  // By default the tabpanel should receive focus
204
+ await sleep();
203
205
  await press.Tab();
204
206
  expect( selectedTabPanel ).toHaveFocus();
205
207
  } );
@@ -229,12 +231,14 @@ describe( 'Tabs', () => {
229
231
 
230
232
  // Tab should initially focus the first tab in the tablist, which
231
233
  // is Alpha.
234
+ await sleep();
232
235
  await press.Tab();
233
236
  expect(
234
237
  await screen.findByRole( 'tab', { name: 'Alpha' } )
235
238
  ).toHaveFocus();
236
239
  // Because the alpha tabpanel is set to `focusable: false`, pressing
237
240
  // the Tab key should focus the button, not the tabpanel
241
+ await sleep();
238
242
  await press.Tab();
239
243
  expect( alphaButton ).toHaveFocus();
240
244
  } );
@@ -305,6 +309,7 @@ describe( 'Tabs', () => {
305
309
  // Tab to focus the tablist. Make sure alpha is focused.
306
310
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
307
311
  expect( await getSelectedTab() ).not.toHaveFocus();
312
+ await sleep();
308
313
  await press.Tab();
309
314
  expect( await getSelectedTab() ).toHaveFocus();
310
315
 
@@ -338,6 +343,7 @@ describe( 'Tabs', () => {
338
343
  // Tab to focus the tablist. Make sure Alpha is focused.
339
344
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
340
345
  expect( await getSelectedTab() ).not.toHaveFocus();
346
+ await sleep();
341
347
  await press.Tab();
342
348
  expect( await getSelectedTab() ).toHaveFocus();
343
349
 
@@ -373,6 +379,7 @@ describe( 'Tabs', () => {
373
379
  // Tab to focus the tablist. Make sure alpha is focused.
374
380
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
375
381
  expect( await getSelectedTab() ).not.toHaveFocus();
382
+ await sleep();
376
383
  await press.Tab();
377
384
  expect( await getSelectedTab() ).toHaveFocus();
378
385
 
@@ -472,6 +479,7 @@ describe( 'Tabs', () => {
472
479
  // Tab to focus the tablist. Make sure Alpha is focused.
473
480
  expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' );
474
481
  expect( await getSelectedTab() ).not.toHaveFocus();
482
+ await sleep();
475
483
  await press.Tab();
476
484
  expect( await getSelectedTab() ).toHaveFocus();
477
485
  // Confirm onSelect has not been re-called
@@ -514,6 +522,7 @@ describe( 'Tabs', () => {
514
522
 
515
523
  // Tab should initially focus the first tab in the tablist, which
516
524
  // is Alpha.
525
+ await sleep();
517
526
  await press.Tab();
518
527
  expect(
519
528
  await screen.findByRole( 'tab', { name: 'Alpha' } )
@@ -522,6 +531,7 @@ describe( 'Tabs', () => {
522
531
  // Because all other tabs should have `tabindex=-1`, pressing Tab
523
532
  // should NOT move the focus to the next tab, which is Beta.
524
533
  // Instead, focus should go to the currently selected tabpanel (alpha).
534
+ await sleep();
525
535
  await press.Tab();
526
536
  expect(
527
537
  await screen.findByRole( 'tabpanel', {
@@ -832,6 +842,7 @@ describe( 'Tabs', () => {
832
842
  expect( mockOnSelect ).toHaveBeenLastCalledWith( 'alpha' );
833
843
 
834
844
  // Move focus to the tablist, make sure alpha is focused.
845
+ await sleep();
835
846
  await press.Tab();
836
847
  expect(
837
848
  screen.getByRole( 'tab', { name: 'Alpha' } )
@@ -1185,10 +1196,18 @@ describe( 'Tabs', () => {
1185
1196
  />
1186
1197
  );
1187
1198
 
1199
+ // Due to the timing of the component re-rendering, we
1200
+ // need to force a delay to ensure the test doesn't run
1201
+ // the upcoming assertions too early.
1202
+ // see https://github.com/WordPress/gutenberg/pull/58629#issuecomment-1924875249
1203
+ await sleep();
1204
+
1188
1205
  // Tab key should focus the currently selected tab, which is Beta.
1189
1206
  await press.Tab();
1190
- expect( await getSelectedTab() ).toHaveTextContent(
1191
- 'Beta'
1207
+ await waitFor( async () =>
1208
+ expect( await getSelectedTab() ).toHaveTextContent(
1209
+ 'Beta'
1210
+ )
1192
1211
  );
1193
1212
  expect( await getSelectedTab() ).toHaveFocus();
1194
1213
 
@@ -1201,9 +1220,11 @@ describe( 'Tabs', () => {
1201
1220
  );
1202
1221
 
1203
1222
  // When the selected tab is changed, it should not automatically receive focus.
1223
+
1204
1224
  expect( await getSelectedTab() ).toHaveTextContent(
1205
1225
  'Gamma'
1206
1226
  );
1227
+
1207
1228
  expect(
1208
1229
  screen.getByRole( 'tab', { name: 'Beta' } )
1209
1230
  ).toHaveFocus();
@@ -1228,7 +1249,9 @@ describe( 'Tabs', () => {
1228
1249
  );
1229
1250
 
1230
1251
  // Tab key should focus the currently selected tab, which is Beta.
1252
+ await sleep();
1231
1253
  await press.Tab();
1254
+ await sleep();
1232
1255
  await press.Tab();
1233
1256
  expect( await getSelectedTab() ).toHaveTextContent(
1234
1257
  'Beta'
@@ -1247,9 +1270,11 @@ describe( 'Tabs', () => {
1247
1270
  );
1248
1271
 
1249
1272
  // When the selected tab is changed, it should not automatically receive focus.
1273
+
1250
1274
  expect( await getSelectedTab() ).toHaveTextContent(
1251
1275
  'Gamma'
1252
1276
  );
1277
+
1253
1278
  expect(
1254
1279
  screen.getByRole( 'tab', { name: 'Beta' } )
1255
1280
  ).toHaveFocus();
@@ -1261,6 +1286,7 @@ describe( 'Tabs', () => {
1261
1286
  ).toHaveFocus();
1262
1287
 
1263
1288
  // Press tab, move focus back to the tablist
1289
+ await sleep();
1264
1290
  await press.Tab();
1265
1291
 
1266
1292
  const betaTab = screen.getByRole( 'tab', {
@@ -1282,6 +1308,7 @@ describe( 'Tabs', () => {
1282
1308
  it( 'should automatically select a newly focused tab', async () => {
1283
1309
  render( <ControlledTabs tabs={ TABS } selectedTabId="beta" /> );
1284
1310
 
1311
+ await sleep();
1285
1312
  await press.Tab();
1286
1313
 
1287
1314
  // Tab key should focus the currently selected tab, which is Beta.
@@ -1307,10 +1334,13 @@ describe( 'Tabs', () => {
1307
1334
  expect( await getSelectedTab() ).toHaveTextContent( 'Beta' );
1308
1335
 
1309
1336
  // Tab key should focus the currently selected tab, which is Beta.
1337
+ await sleep();
1310
1338
  await press.Tab();
1311
- expect(
1312
- await screen.findByRole( 'tab', { name: 'Beta' } )
1313
- ).toHaveFocus();
1339
+ await waitFor( async () =>
1340
+ expect(
1341
+ await screen.findByRole( 'tab', { name: 'Beta' } )
1342
+ ).toHaveFocus()
1343
+ );
1314
1344
 
1315
1345
  // Arrow key should move focus but not automatically change the selected tab.
1316
1346
  await press.ArrowRight();
@@ -18,6 +18,7 @@ const meta: Meta< typeof Theme > = {
18
18
  accent: { control: { type: 'color' } },
19
19
  background: { control: { type: 'color' } },
20
20
  },
21
+ tags: [ 'status-private' ],
21
22
  parameters: {
22
23
  badges: [ 'private' ],
23
24
  controls: { expanded: true },