@wordpress/components 27.1.0 → 27.3.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/CHANGELOG.md +53 -3
  2. package/README.md +13 -0
  3. package/build/button/index.js +3 -4
  4. package/build/button/index.js.map +1 -1
  5. package/build/button/types.js.map +1 -1
  6. package/build/color-picker/component.js +2 -12
  7. package/build/color-picker/component.js.map +1 -1
  8. package/build/color-picker/picker.js +18 -77
  9. package/build/color-picker/picker.js.map +1 -1
  10. package/build/color-picker/types.js.map +1 -1
  11. package/build/custom-select-control-v2/default-component/index.js +4 -2
  12. package/build/custom-select-control-v2/default-component/index.js.map +1 -1
  13. package/build/custom-select-control-v2/index.js +1 -8
  14. package/build/custom-select-control-v2/index.js.map +1 -1
  15. package/build/custom-select-control-v2/{custom-select-item.js → item.js} +2 -1
  16. package/build/custom-select-control-v2/{custom-select-item.js.map → item.js.map} +1 -1
  17. package/build/custom-select-control-v2/legacy-component/index.js +5 -5
  18. package/build/custom-select-control-v2/legacy-component/index.js.map +1 -1
  19. package/build/date-time/date/styles.js +7 -7
  20. package/build/date-time/date/styles.js.map +1 -1
  21. package/build/form-token-field/index.js +1 -1
  22. package/build/form-token-field/index.js.map +1 -1
  23. package/build/input-control/index.js +1 -1
  24. package/build/input-control/index.js.map +1 -1
  25. package/build/input-control/input-field.js +2 -1
  26. package/build/input-control/input-field.js.map +1 -1
  27. package/build/mobile/color-settings/palette.screen.native.js +1 -0
  28. package/build/mobile/color-settings/palette.screen.native.js.map +1 -1
  29. package/build/navigable-container/container.js.map +1 -1
  30. package/build/navigator/navigator-provider/component.js +162 -120
  31. package/build/navigator/navigator-provider/component.js.map +1 -1
  32. package/build/navigator/navigator-screen/component.js +2 -2
  33. package/build/navigator/navigator-screen/component.js.map +1 -1
  34. package/build/palette-edit/index.js +18 -12
  35. package/build/palette-edit/index.js.map +1 -1
  36. package/build/popover/index.js +7 -34
  37. package/build/popover/index.js.map +1 -1
  38. package/build/range-control/styles/range-control-styles.js +29 -29
  39. package/build/range-control/styles/range-control-styles.js.map +1 -1
  40. package/build/text-control/types.js.map +1 -1
  41. package/build/toggle-group-control/toggle-group-control-option-base/component.js +5 -2
  42. package/build/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  43. package/build/tools-panel/tools-panel-header/component.js +1 -1
  44. package/build/tools-panel/tools-panel-header/component.js.map +1 -1
  45. package/build/utils/config-values.js +1 -1
  46. package/build/utils/config-values.js.map +1 -1
  47. package/build/utils/input/base.js +2 -2
  48. package/build/utils/input/base.js.map +1 -1
  49. package/build-module/button/index.js +3 -4
  50. package/build-module/button/index.js.map +1 -1
  51. package/build-module/button/types.js.map +1 -1
  52. package/build-module/color-picker/component.js +3 -13
  53. package/build-module/color-picker/component.js.map +1 -1
  54. package/build-module/color-picker/picker.js +19 -78
  55. package/build-module/color-picker/picker.js.map +1 -1
  56. package/build-module/color-picker/types.js.map +1 -1
  57. package/build-module/custom-select-control-v2/default-component/index.js +4 -2
  58. package/build-module/custom-select-control-v2/default-component/index.js.map +1 -1
  59. package/build-module/custom-select-control-v2/index.js +1 -2
  60. package/build-module/custom-select-control-v2/index.js.map +1 -1
  61. package/build-module/custom-select-control-v2/{custom-select-item.js → item.js} +2 -1
  62. package/build-module/custom-select-control-v2/{custom-select-item.js.map → item.js.map} +1 -1
  63. package/build-module/custom-select-control-v2/legacy-component/index.js +4 -4
  64. package/build-module/custom-select-control-v2/legacy-component/index.js.map +1 -1
  65. package/build-module/date-time/date/styles.js +7 -7
  66. package/build-module/date-time/date/styles.js.map +1 -1
  67. package/build-module/form-token-field/index.js +1 -1
  68. package/build-module/form-token-field/index.js.map +1 -1
  69. package/build-module/input-control/index.js +1 -1
  70. package/build-module/input-control/index.js.map +1 -1
  71. package/build-module/input-control/input-field.js +2 -1
  72. package/build-module/input-control/input-field.js.map +1 -1
  73. package/build-module/mobile/color-settings/palette.screen.native.js +1 -0
  74. package/build-module/mobile/color-settings/palette.screen.native.js.map +1 -1
  75. package/build-module/navigable-container/container.js.map +1 -1
  76. package/build-module/navigator/navigator-provider/component.js +163 -121
  77. package/build-module/navigator/navigator-provider/component.js.map +1 -1
  78. package/build-module/navigator/navigator-screen/component.js +2 -2
  79. package/build-module/navigator/navigator-screen/component.js.map +1 -1
  80. package/build-module/palette-edit/index.js +17 -11
  81. package/build-module/palette-edit/index.js.map +1 -1
  82. package/build-module/popover/index.js +9 -36
  83. package/build-module/popover/index.js.map +1 -1
  84. package/build-module/range-control/styles/range-control-styles.js +29 -29
  85. package/build-module/range-control/styles/range-control-styles.js.map +1 -1
  86. package/build-module/text-control/types.js.map +1 -1
  87. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js +6 -3
  88. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  89. package/build-module/tools-panel/tools-panel-header/component.js +1 -1
  90. package/build-module/tools-panel/tools-panel-header/component.js.map +1 -1
  91. package/build-module/utils/config-values.js +1 -1
  92. package/build-module/utils/config-values.js.map +1 -1
  93. package/build-module/utils/input/base.js +2 -2
  94. package/build-module/utils/input/base.js.map +1 -1
  95. package/build-style/style-rtl.css +26 -29
  96. package/build-style/style.css +26 -29
  97. package/build-types/box-control/styles/box-control-styles.d.ts +1 -1
  98. package/build-types/button/deprecated.d.ts +4 -10
  99. package/build-types/button/deprecated.d.ts.map +1 -1
  100. package/build-types/button/index.d.ts +3 -3
  101. package/build-types/button/index.d.ts.map +1 -1
  102. package/build-types/button/stories/e2e/index.story.d.ts +1 -1
  103. package/build-types/button/stories/e2e/index.story.d.ts.map +1 -1
  104. package/build-types/button/stories/index.story.d.ts +7 -7
  105. package/build-types/button/stories/index.story.d.ts.map +1 -1
  106. package/build-types/button/types.d.ts +37 -8
  107. package/build-types/button/types.d.ts.map +1 -1
  108. package/build-types/color-picker/component.d.ts.map +1 -1
  109. package/build-types/color-picker/picker.d.ts +1 -1
  110. package/build-types/color-picker/picker.d.ts.map +1 -1
  111. package/build-types/color-picker/styles.d.ts +1 -1
  112. package/build-types/color-picker/types.d.ts +0 -3
  113. package/build-types/color-picker/types.d.ts.map +1 -1
  114. package/build-types/custom-select-control/stories/index.story.d.ts +35 -0
  115. package/build-types/custom-select-control/stories/index.story.d.ts.map +1 -0
  116. package/build-types/custom-select-control-v2/default-component/index.d.ts +5 -2
  117. package/build-types/custom-select-control-v2/default-component/index.d.ts.map +1 -1
  118. package/build-types/custom-select-control-v2/index.d.ts +1 -2
  119. package/build-types/custom-select-control-v2/index.d.ts.map +1 -1
  120. package/build-types/custom-select-control-v2/{custom-select-item.d.ts → item.d.ts} +4 -1
  121. package/build-types/custom-select-control-v2/item.d.ts.map +1 -0
  122. package/build-types/custom-select-control-v2/legacy-component/index.d.ts +2 -2
  123. package/build-types/custom-select-control-v2/legacy-component/index.d.ts.map +1 -1
  124. package/build-types/custom-select-control-v2/stories/default.story.d.ts +2 -2
  125. package/build-types/custom-select-control-v2/stories/default.story.d.ts.map +1 -1
  126. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts +4 -2
  127. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts.map +1 -1
  128. package/build-types/date-time/date/styles.d.ts +1 -1
  129. package/build-types/dropdown/stories/index.story.d.ts +1 -0
  130. package/build-types/dropdown/stories/index.story.d.ts.map +1 -1
  131. package/build-types/font-size-picker/styles.d.ts +1 -1
  132. package/build-types/form-token-field/index.d.ts +1 -1
  133. package/build-types/input-control/index.d.ts +1 -1
  134. package/build-types/input-control/input-field.d.ts.map +1 -1
  135. package/build-types/input-control/stories/index.story.d.ts.map +1 -1
  136. package/build-types/navigation/styles/navigation-styles.d.ts +1 -1
  137. package/build-types/navigator/navigator-back-button/component.d.ts +0 -1
  138. package/build-types/navigator/navigator-back-button/component.d.ts.map +1 -1
  139. package/build-types/navigator/navigator-back-button/hook.d.ts +1 -2
  140. package/build-types/navigator/navigator-back-button/hook.d.ts.map +1 -1
  141. package/build-types/navigator/navigator-button/component.d.ts +0 -1
  142. package/build-types/navigator/navigator-button/component.d.ts.map +1 -1
  143. package/build-types/navigator/navigator-button/hook.d.ts +1 -2
  144. package/build-types/navigator/navigator-button/hook.d.ts.map +1 -1
  145. package/build-types/navigator/navigator-provider/component.d.ts.map +1 -1
  146. package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
  147. package/build-types/navigator/navigator-to-parent-button/component.d.ts +0 -1
  148. package/build-types/navigator/navigator-to-parent-button/component.d.ts.map +1 -1
  149. package/build-types/number-control/styles/number-control-styles.d.ts +1 -1
  150. package/build-types/palette-edit/index.d.ts +6 -3
  151. package/build-types/palette-edit/index.d.ts.map +1 -1
  152. package/build-types/palette-edit/styles.d.ts +2 -2
  153. package/build-types/popover/index.d.ts.map +1 -1
  154. package/build-types/text-control/index.d.ts +1 -1
  155. package/build-types/text-control/types.d.ts +1 -1
  156. package/build-types/text-control/types.d.ts.map +1 -1
  157. package/build-types/toggle-group-control/toggle-group-control-option-base/component.d.ts.map +1 -1
  158. package/build-types/toolbar/toolbar-button/index.d.ts +4 -10
  159. package/build-types/toolbar/toolbar-button/index.d.ts.map +1 -1
  160. package/package.json +21 -21
  161. package/src/button/index.tsx +3 -4
  162. package/src/button/test/index.tsx +6 -6
  163. package/src/button/types.ts +37 -9
  164. package/src/color-picker/component.tsx +3 -25
  165. package/src/color-picker/picker.tsx +12 -96
  166. package/src/color-picker/types.ts +0 -3
  167. package/src/confirm-dialog/README.md +7 -0
  168. package/src/custom-select-control/stories/{index.story.js → index.story.tsx} +8 -3
  169. package/src/custom-select-control/test/index.js +24 -0
  170. package/src/custom-select-control-v2/README.md +27 -27
  171. package/src/custom-select-control-v2/default-component/index.tsx +5 -2
  172. package/src/custom-select-control-v2/index.tsx +1 -2
  173. package/src/custom-select-control-v2/{custom-select-item.tsx → item.tsx} +2 -0
  174. package/src/custom-select-control-v2/legacy-component/index.tsx +4 -6
  175. package/src/custom-select-control-v2/legacy-component/test/index.tsx +13 -10
  176. package/src/custom-select-control-v2/stories/default.story.tsx +16 -17
  177. package/src/custom-select-control-v2/stories/legacy.story.tsx +20 -35
  178. package/src/custom-select-control-v2/test/index.tsx +26 -16
  179. package/src/date-time/date/styles.ts +2 -2
  180. package/src/dimension-control/test/__snapshots__/index.test.js.snap +4 -4
  181. package/src/dropdown/stories/index.story.tsx +19 -0
  182. package/src/dropdown/style.scss +26 -0
  183. package/src/dropdown-menu/style.scss +0 -25
  184. package/src/flex/flex/README.md +2 -2
  185. package/src/form-token-field/README.md +1 -1
  186. package/src/form-token-field/index.tsx +1 -1
  187. package/src/grid/README.md +11 -11
  188. package/src/h-stack/README.md +6 -6
  189. package/src/heading/README.md +1 -1
  190. package/src/heading/test/__snapshots__/index.tsx.snap +3 -3
  191. package/src/input-control/README.md +1 -1
  192. package/src/input-control/index.tsx +1 -1
  193. package/src/input-control/input-field.tsx +2 -1
  194. package/src/input-control/stories/index.story.tsx +1 -0
  195. package/src/item-group/test/__snapshots__/index.js.snap +11 -11
  196. package/src/mobile/bottom-sheet-select-control/README.md +1 -1
  197. package/src/mobile/color-settings/palette.screen.native.js +5 -1
  198. package/src/navigable-container/container.tsx +1 -1
  199. package/src/navigator/navigator-provider/component.tsx +187 -188
  200. package/src/navigator/navigator-screen/component.tsx +2 -4
  201. package/src/palette-edit/index.tsx +21 -21
  202. package/src/palette-edit/test/index.tsx +21 -17
  203. package/src/placeholder/style.scss +5 -1
  204. package/src/popover/index.tsx +59 -99
  205. package/src/popover/style.scss +0 -9
  206. package/src/progress-bar/README.md +1 -1
  207. package/src/radio-control/README.md +3 -3
  208. package/src/range-control/styles/range-control-styles.ts +1 -1
  209. package/src/resizable-box/resize-tooltip/README.md +2 -2
  210. package/src/text/test/__snapshots__/index.tsx.snap +3 -3
  211. package/src/text-control/style.scss +2 -0
  212. package/src/text-control/types.ts +12 -1
  213. package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +14 -10
  214. package/src/toggle-group-control/toggle-group-control-option-base/component.tsx +14 -12
  215. package/src/toolbar/toolbar/style.scss +1 -1
  216. package/src/tools-panel/tools-panel-header/component.tsx +1 -1
  217. package/src/truncate/README.md +5 -5
  218. package/src/utils/config-values.js +1 -1
  219. package/src/utils/input/base.js +1 -1
  220. package/src/v-stack/README.md +6 -6
  221. package/tsconfig.json +1 -0
  222. package/tsconfig.tsbuildinfo +1 -1
  223. package/build-types/custom-select-control-v2/custom-select-item.d.ts.map +0 -1
@@ -7,118 +7,34 @@ import { colord } from 'colord';
7
7
  /**
8
8
  * WordPress dependencies
9
9
  */
10
- import { useMemo, useEffect, useRef } from '@wordpress/element';
10
+ import { useMemo } from '@wordpress/element';
11
11
  /**
12
12
  * Internal dependencies
13
13
  */
14
14
  import type { PickerProps } from './types';
15
15
 
16
- /**
17
- * Track the start and the end of drag pointer events related to controlling
18
- * the picker's saturation / hue / alpha, and fire the corresponding callbacks.
19
- * This is particularly useful to implement synergies like the one with the
20
- * `Popover` component, where a pointer events "trap" is rendered while
21
- * the user is dragging the pointer to avoid potential interference with iframe
22
- * elements.
23
- *
24
- * @param props
25
- * @param props.containerEl
26
- * @param props.onDragStart
27
- * @param props.onDragEnd
28
- */
29
- const useOnPickerDrag = ( {
30
- containerEl,
31
- onDragStart,
32
- onDragEnd,
33
- }: Pick< PickerProps, 'containerEl' | 'onDragStart' | 'onDragEnd' > ) => {
34
- const isDragging = useRef( false );
35
- const leftWhileDragging = useRef( false );
36
- useEffect( () => {
37
- if ( ! containerEl || ( ! onDragStart && ! onDragEnd ) ) {
38
- return;
39
- }
40
- const interactiveElements = [
41
- containerEl.querySelector( '.react-colorful__saturation' ),
42
- containerEl.querySelector( '.react-colorful__hue' ),
43
- containerEl.querySelector( '.react-colorful__alpha' ),
44
- ].filter( ( el ) => !! el ) as Element[];
45
-
46
- if ( interactiveElements.length === 0 ) {
47
- return;
48
- }
49
-
50
- const doc = containerEl.ownerDocument;
51
-
52
- const onPointerUp: EventListener = ( event ) => {
53
- isDragging.current = false;
54
- leftWhileDragging.current = false;
55
- onDragEnd?.( event as MouseEvent );
56
- };
57
-
58
- const onPointerDown: EventListener = ( event ) => {
59
- isDragging.current = true;
60
- onDragStart?.( event as MouseEvent );
61
- };
62
-
63
- const onPointerLeave: EventListener = () => {
64
- leftWhileDragging.current = isDragging.current;
65
- };
66
-
67
- // Try to detect if the user released the pointer while away from the
68
- // current window. If the check is successfull, the dragEnd callback will
69
- // called as soon as the pointer re-enters the window (better late than never)
70
- const onPointerEnter: EventListener = ( event ) => {
71
- const noPointerButtonsArePressed =
72
- ( event as PointerEvent ).buttons === 0;
73
-
74
- if ( leftWhileDragging.current && noPointerButtonsArePressed ) {
75
- onPointerUp( event );
76
- }
77
- };
78
-
79
- // The pointerdown event is added on the interactive elements,
80
- // while the remaining events are added on the document object since
81
- // the pointer wouldn't necessarily be hovering the initial interactive
82
- // element at that point.
83
- interactiveElements.forEach( ( el ) =>
84
- el.addEventListener( 'pointerdown', onPointerDown )
85
- );
86
- doc.addEventListener( 'pointerup', onPointerUp );
87
- doc.addEventListener( 'pointerenter', onPointerEnter );
88
- doc.addEventListener( 'pointerleave', onPointerLeave );
89
-
90
- return () => {
91
- interactiveElements.forEach( ( el ) =>
92
- el.removeEventListener( 'pointerdown', onPointerDown )
93
- );
94
- doc.removeEventListener( 'pointerup', onPointerUp );
95
- doc.removeEventListener( 'pointerenter', onPointerEnter );
96
- doc.removeEventListener( 'pointerleave', onPointerUp );
97
- };
98
- }, [ onDragStart, onDragEnd, containerEl ] );
99
- };
100
-
101
- export const Picker = ( {
102
- color,
103
- enableAlpha,
104
- onChange,
105
- onDragStart,
106
- onDragEnd,
107
- containerEl,
108
- }: PickerProps ) => {
16
+ export const Picker = ( { color, enableAlpha, onChange }: PickerProps ) => {
109
17
  const Component = enableAlpha
110
18
  ? RgbaStringColorPicker
111
19
  : RgbStringColorPicker;
112
20
  const rgbColor = useMemo( () => color.toRgbString(), [ color ] );
113
21
 
114
- useOnPickerDrag( { containerEl, onDragStart, onDragEnd } );
115
-
116
22
  return (
117
23
  <Component
118
24
  color={ rgbColor }
119
25
  onChange={ ( nextColor ) => {
120
26
  onChange( colord( nextColor ) );
121
27
  } }
28
+ // Pointer capture fortifies drag gestures so that they continue to
29
+ // work while dragging outside the component over objects like
30
+ // iframes. If a newer version of react-colorful begins to employ
31
+ // pointer capture this will be redundant and should be removed.
32
+ onPointerDown={ ( { currentTarget, pointerId } ) => {
33
+ currentTarget.setPointerCapture( pointerId );
34
+ } }
35
+ onPointerUp={ ( { currentTarget, pointerId } ) => {
36
+ currentTarget.releasePointerCapture( pointerId );
37
+ } }
122
38
  />
123
39
  );
124
40
  };
@@ -59,9 +59,6 @@ export interface PickerProps {
59
59
  color: Colord;
60
60
  enableAlpha: boolean;
61
61
  onChange: ( nextColor: Colord ) => void;
62
- containerEl: HTMLElement | null;
63
- onDragStart?: ( event: MouseEvent ) => void;
64
- onDragEnd?: ( event: MouseEvent ) => void;
65
62
  }
66
63
 
67
64
  export interface ColorInputProps {
@@ -138,3 +138,10 @@ The optional custom text to display as the confirmation button's label
138
138
  - Default: "Cancel"
139
139
 
140
140
  The optional custom text to display as the cancellation button's label
141
+
142
+ ## Best practices
143
+
144
+ The ConfirmDialog component should:
145
+
146
+ - Be used only for short confirmation messages where a cancel and confirm actions are provided.
147
+ - Use a descriptive text for the _confirm_ button. Default is "OK".
@@ -1,3 +1,8 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import type { StoryFn } from '@storybook/react';
5
+
1
6
  /**
2
7
  * Internal dependencies
3
8
  */
@@ -18,7 +23,7 @@ export default {
18
23
  },
19
24
  };
20
25
 
21
- export const Default = CustomSelectControl.bind( {} );
26
+ export const Default: StoryFn = CustomSelectControl.bind( {} );
22
27
  Default.args = {
23
28
  label: 'Label',
24
29
  options: [
@@ -46,7 +51,7 @@ Default.args = {
46
51
  ],
47
52
  };
48
53
 
49
- export const WithLongLabels = CustomSelectControl.bind( {} );
54
+ export const WithLongLabels: StoryFn = CustomSelectControl.bind( {} );
50
55
  WithLongLabels.args = {
51
56
  ...Default.args,
52
57
  options: [
@@ -65,7 +70,7 @@ WithLongLabels.args = {
65
70
  ],
66
71
  };
67
72
 
68
- export const WithHints = CustomSelectControl.bind( {} );
73
+ export const WithHints: StoryFn = CustomSelectControl.bind( {} );
69
74
  WithHints.args = {
70
75
  ...Default.args,
71
76
  options: [
@@ -238,6 +238,30 @@ describe.each( [
238
238
  ).toHaveTextContent( 'Hint' );
239
239
  } );
240
240
 
241
+ it( 'shows selected hint in list of options when added, regardless of __experimentalShowSelectedHint prop', async () => {
242
+ const user = userEvent.setup();
243
+
244
+ render(
245
+ <Component
246
+ { ...props }
247
+ label="Custom select"
248
+ options={ [
249
+ {
250
+ key: 'one',
251
+ name: 'One',
252
+ __experimentalHint: 'Hint',
253
+ },
254
+ ] }
255
+ />
256
+ );
257
+
258
+ await user.click(
259
+ screen.getByRole( 'button', { name: 'Custom select' } )
260
+ );
261
+
262
+ expect( screen.getByRole( 'option', { name: /hint/i } ) ).toBeVisible();
263
+ } );
264
+
241
265
  describe( 'Keyboard behavior and accessibility', () => {
242
266
  it( 'Captures the keypress event and does not let it propagate', async () => {
243
267
  const user = userEvent.setup();
@@ -1,4 +1,4 @@
1
- # CustomSelect
1
+ # CustomSelectControlV2
2
2
 
3
3
  <div class="callout callout-alert">
4
4
  This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
@@ -12,31 +12,31 @@ Used to render a customizable select control component.
12
12
 
13
13
  #### Uncontrolled Mode
14
14
 
15
- CustomSelect can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `defaultValue` prop can be used to set the initial selected value. If this prop is not set, the first value from the children will be selected by default.
15
+ `CustomSelectControlV2` can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `defaultValue` prop can be used to set the initial selected value. If this prop is not set, the first value from the children will be selected by default.
16
16
 
17
17
  ```jsx
18
- const UncontrolledCustomSelect = () => (
19
- <CustomSelect label="Colors">
20
- <CustomSelectItem value="Blue">
18
+ const UncontrolledCustomSelectControlV2 = () => (
19
+ <CustomSelectControlV2 label="Colors">
20
+ <CustomSelectControlV2.Item value="Blue">
21
21
  { /* The `defaultValue` since it wasn't defined */ }
22
22
  <span style={ { color: 'blue' } }>Blue</span>
23
- </CustomSelectItem>
24
- <CustomSelectItem value="Purple">
23
+ </CustomSelectControlV2.Item>
24
+ <CustomSelectControlV2.Item value="Purple">
25
25
  <span style={ { color: 'purple' } }>Purple</span>
26
- </CustomSelectItem>
27
- <CustomSelectItem value="Pink">
26
+ </CustomSelectControlV2.Item>
27
+ <CustomSelectControlV2.Item value="Pink">
28
28
  <span style={ { color: 'deeppink' } }>Pink</span>
29
- </CustomSelectItem>
30
- </CustomSelect>
29
+ </CustomSelectControlV2.Item>
30
+ </CustomSelectControlV2>
31
31
  );
32
32
  ```
33
33
 
34
34
  #### Controlled Mode
35
35
 
36
- CustomSelect can also be used in a controlled mode, where the parent component specifies the `value` and the `onChange` props to control selection.
36
+ `CustomSelectControlV2` can also be used in a controlled mode, where the parent component specifies the `value` and the `onChange` props to control selection.
37
37
 
38
38
  ```jsx
39
- const ControlledCustomSelect = () => {
39
+ const ControlledCustomSelectControlV2 = () => {
40
40
  const [ value, setValue ] = useState< string | string[] >();
41
41
 
42
42
  const renderControlledValue = ( renderValue: string | string[] ) => (
@@ -46,7 +46,7 @@ const ControlledCustomSelect = () => {
46
46
  );
47
47
 
48
48
  return (
49
- <CustomSelect
49
+ <CustomSelectControlV2
50
50
  { ...props }
51
51
  onChange={ ( nextValue ) => {
52
52
  setValue( nextValue );
@@ -55,11 +55,11 @@ const ControlledCustomSelect = () => {
55
55
  value={ value }
56
56
  >
57
57
  { [ 'blue', 'purple', 'pink' ].map( ( option ) => (
58
- <CustomSelectItem key={ option } value={ option }>
58
+ <CustomSelectControlV2.Item key={ option } value={ option }>
59
59
  { renderControlledValue( option ) }
60
- </CustomSelectItem>
60
+ </CustomSelectControlV2.Item>
61
61
  ) ) }
62
- </CustomSelect>
62
+ </CustomSelectControlV2>
63
63
  );
64
64
  };
65
65
  ```
@@ -70,23 +70,23 @@ Multiple selection can be enabled by using an array for the `value` and
70
70
  `defaultValue` props. The argument of the `onChange` function will also change accordingly.
71
71
 
72
72
  ```jsx
73
- const MultiSelectCustomSelect = () => (
74
- <CustomSelect defaultValue={ [ 'blue', 'pink' ] } label="Colors">
73
+ const MultiSelectCustomSelectControlV2 = () => (
74
+ <CustomSelectControlV2 defaultValue={ [ 'blue', 'pink' ] } label="Colors">
75
75
  { [ 'blue', 'purple', 'pink' ].map( ( item ) => (
76
- <CustomSelectItem key={ item } value={ item }>
76
+ <CustomSelectControlV2.Item key={ item } value={ item }>
77
77
  { item }
78
- </CustomSelectItem>
78
+ </CustomSelectControlV2.Item>
79
79
  ) ) }
80
- </CustomSelect>
80
+ </CustomSelectControlV2>
81
81
  );
82
82
  ```
83
83
 
84
84
  ### Components and Sub-components
85
85
 
86
- CustomSelect is comprised of two individual components:
86
+ `CustomSelectControlV2` is comprised of two individual components:
87
87
 
88
- - `CustomSelect`: a wrapper component and context provider. It is responsible for managing the state of the `CustomSelectItem` children.
89
- - `CustomSelectItem`: renders a single select item. The first `CustomSelectItem` child will be used as the `defaultValue` when `defaultValue` is undefined.
88
+ - `CustomSelectControlV2`: a wrapper component and context provider. It is responsible for managing the state of the `CustomSelectControlV2.Item` children.
89
+ - `CustomSelectControlV2.Item`: renders a single select item. The first `CustomSelectControlV2.Item` child will be used as the `defaultValue` when `defaultValue` is undefined.
90
90
 
91
91
  #### Props
92
92
 
@@ -94,7 +94,7 @@ The component accepts the following props:
94
94
 
95
95
  ##### `children`: `React.ReactNode`
96
96
 
97
- The child elements. This should be composed of CustomSelect.Item components.
97
+ The child elements. This should be composed of `CustomSelectControlV2.Item` components.
98
98
 
99
99
  - Required: yes
100
100
 
@@ -142,7 +142,7 @@ Can be used to externally control the value of the control.
142
142
 
143
143
  - Required: no
144
144
 
145
- ### `CustomSelectItem`
145
+ ### `CustomSelectControlV2.Item`
146
146
 
147
147
  Used to render a select item.
148
148
 
@@ -9,8 +9,9 @@ import * as Ariakit from '@ariakit/react';
9
9
  import _CustomSelect from '../custom-select';
10
10
  import type { CustomSelectProps } from '../types';
11
11
  import type { WordPressComponentProps } from '../../context';
12
+ import Item from '../item';
12
13
 
13
- function CustomSelect(
14
+ function CustomSelectControlV2(
14
15
  props: WordPressComponentProps< CustomSelectProps, 'button', false >
15
16
  ) {
16
17
  const { defaultValue, onChange, value, ...restProps } = props;
@@ -24,4 +25,6 @@ function CustomSelect(
24
25
  return <_CustomSelect { ...restProps } store={ store } />;
25
26
  }
26
27
 
27
- export default CustomSelect;
28
+ CustomSelectControlV2.Item = Item;
29
+
30
+ export default CustomSelectControlV2;
@@ -1,5 +1,4 @@
1
1
  /**
2
2
  * Internal dependencies
3
3
  */
4
- export { default as CustomSelect } from './default-component';
5
- export { default as CustomSelectItem } from './custom-select-item';
4
+ export { default } from './default-component';
@@ -26,4 +26,6 @@ export function CustomSelectItem( {
26
26
  );
27
27
  }
28
28
 
29
+ CustomSelectItem.displayName = 'CustomSelectControlV2.Item';
30
+
29
31
  export default CustomSelectItem;
@@ -11,12 +11,12 @@ import { useMemo } from '@wordpress/element';
11
11
  * Internal dependencies
12
12
  */
13
13
  import _CustomSelect from '../custom-select';
14
+ import CustomSelectItem from '../item';
14
15
  import type { LegacyCustomSelectProps } from '../types';
15
- import { CustomSelectItem } from '..';
16
16
  import * as Styled from '../styles';
17
17
  import { ContextSystemProvider } from '../../context';
18
18
 
19
- function CustomSelect( props: LegacyCustomSelectProps ) {
19
+ function CustomSelectControl( props: LegacyCustomSelectProps ) {
20
20
  const {
21
21
  __experimentalShowSelectedHint,
22
22
  __next40pxDefaultSize = false,
@@ -68,9 +68,7 @@ function CustomSelect( props: LegacyCustomSelectProps ) {
68
68
  <CustomSelectItem
69
69
  key={ key }
70
70
  value={ name }
71
- children={
72
- __experimentalShowSelectedHint ? withHint : name
73
- }
71
+ children={ __experimentalHint ? withHint : name }
74
72
  { ...rest }
75
73
  />
76
74
  );
@@ -130,4 +128,4 @@ function CustomSelect( props: LegacyCustomSelectProps ) {
130
128
  );
131
129
  }
132
130
 
133
- export default CustomSelect;
131
+ export default CustomSelectControl;
@@ -12,7 +12,7 @@ import { useState } from '@wordpress/element';
12
12
  /**
13
13
  * Internal dependencies
14
14
  */
15
- import UncontrolledCustomSelect from '..';
15
+ import UncontrolledCustomSelectControl from '..';
16
16
 
17
17
  const customClass = 'amber-skies';
18
18
 
@@ -48,14 +48,14 @@ const legacyProps = {
48
48
  ],
49
49
  };
50
50
 
51
- const LegacyControlledCustomSelect = ( {
51
+ const ControlledCustomSelectControl = ( {
52
52
  options,
53
53
  onChange,
54
54
  ...restProps
55
- }: React.ComponentProps< typeof UncontrolledCustomSelect > ) => {
55
+ }: React.ComponentProps< typeof UncontrolledCustomSelectControl > ) => {
56
56
  const [ value, setValue ] = useState( options[ 0 ] );
57
57
  return (
58
- <UncontrolledCustomSelect
58
+ <UncontrolledCustomSelectControl
59
59
  { ...restProps }
60
60
  options={ options }
61
61
  onChange={ ( args: any ) => {
@@ -70,8 +70,8 @@ const LegacyControlledCustomSelect = ( {
70
70
  };
71
71
 
72
72
  describe.each( [
73
- [ 'Uncontrolled', UncontrolledCustomSelect ],
74
- [ 'Controlled', LegacyControlledCustomSelect ],
73
+ [ 'Uncontrolled', UncontrolledCustomSelectControl ],
74
+ [ 'Controlled', ControlledCustomSelectControl ],
75
75
  ] )( 'CustomSelectControl (%s)', ( ...modeAndComponent ) => {
76
76
  const [ , Component ] = modeAndComponent;
77
77
 
@@ -248,7 +248,7 @@ describe.each( [
248
248
  );
249
249
  } );
250
250
 
251
- it( 'shows selected hint in list of options when added', async () => {
251
+ it( 'shows selected hint in list of options when added, regardless of __experimentalShowSelectedHint prop', async () => {
252
252
  render(
253
253
  <Component
254
254
  { ...legacyProps }
@@ -260,7 +260,6 @@ describe.each( [
260
260
  __experimentalHint: 'Hint',
261
261
  },
262
262
  ] }
263
- __experimentalShowSelectedHint
264
263
  />
265
264
  );
266
265
 
@@ -388,8 +387,10 @@ describe.each( [
388
387
  await sleep();
389
388
  await press.Tab();
390
389
  expect( currentSelectedItem ).toHaveFocus();
390
+ expect( currentSelectedItem ).toHaveTextContent( 'violets' );
391
391
 
392
- await type( 'aq' );
392
+ // Ideally we would test a multi-character typeahead, but anything more than a single character is flaky
393
+ await type( 'a' );
393
394
 
394
395
  expect(
395
396
  screen.queryByRole( 'listbox', {
@@ -398,8 +399,10 @@ describe.each( [
398
399
  } )
399
400
  ).not.toBeInTheDocument();
400
401
 
402
+ // This Enter is a workaround for flakiness, and shouldn't be necessary in an actual browser
401
403
  await press.Enter();
402
- expect( currentSelectedItem ).toHaveTextContent( 'aquamarine' );
404
+
405
+ expect( currentSelectedItem ).toHaveTextContent( 'amber' );
403
406
  } );
404
407
 
405
408
  it( 'Should have correct aria-selected value for selections', async () => {
@@ -11,15 +11,14 @@ import { useState } from '@wordpress/element';
11
11
  /**
12
12
  * Internal dependencies
13
13
  */
14
- import CustomSelect from '../default-component';
15
- import { CustomSelectItem } from '..';
14
+ import CustomSelectControlV2 from '..';
16
15
 
17
- const meta: Meta< typeof CustomSelect > = {
16
+ const meta: Meta< typeof CustomSelectControlV2 > = {
18
17
  title: 'Components (Experimental)/CustomSelectControl v2/Default',
19
- component: CustomSelect,
18
+ component: CustomSelectControlV2,
20
19
  subcomponents: {
21
20
  // @ts-expect-error - See https://github.com/storybookjs/storybook/issues/23170
22
- CustomSelectItem,
21
+ 'CustomSelectControlV2.Item': CustomSelectControlV2.Item,
23
22
  },
24
23
  argTypes: {
25
24
  children: { control: { type: null } },
@@ -48,10 +47,10 @@ const meta: Meta< typeof CustomSelect > = {
48
47
  };
49
48
  export default meta;
50
49
 
51
- const Template: StoryFn< typeof CustomSelect > = ( props ) => {
50
+ const Template: StoryFn< typeof CustomSelectControlV2 > = ( props ) => {
52
51
  const [ value, setValue ] = useState< string | string[] >();
53
52
  return (
54
- <CustomSelect
53
+ <CustomSelectControlV2
55
54
  { ...props }
56
55
  onChange={ ( nextValue: string | string[] ) => {
57
56
  setValue( nextValue );
@@ -68,15 +67,15 @@ Default.args = {
68
67
  defaultValue: 'Select a color...',
69
68
  children: (
70
69
  <>
71
- <CustomSelectItem value="Blue">
70
+ <CustomSelectControlV2.Item value="Blue">
72
71
  <span style={ { color: 'blue' } }>Blue</span>
73
- </CustomSelectItem>
74
- <CustomSelectItem value="Purple">
72
+ </CustomSelectControlV2.Item>
73
+ <CustomSelectControlV2.Item value="Purple">
75
74
  <span style={ { color: 'purple' } }>Purple</span>
76
- </CustomSelectItem>
77
- <CustomSelectItem value="Pink">
75
+ </CustomSelectControlV2.Item>
76
+ <CustomSelectControlV2.Item value="Pink">
78
77
  <span style={ { color: 'deeppink' } }>Pink</span>
79
- </CustomSelectItem>
78
+ </CustomSelectControlV2.Item>
80
79
  </>
81
80
  ),
82
81
  };
@@ -100,9 +99,9 @@ MultipleSelection.args = {
100
99
  'maroon',
101
100
  'tangerine',
102
101
  ].map( ( item ) => (
103
- <CustomSelectItem key={ item } value={ item }>
102
+ <CustomSelectControlV2.Item key={ item } value={ item }>
104
103
  { item }
105
- </CustomSelectItem>
104
+ </CustomSelectControlV2.Item>
106
105
  ) ) }
107
106
  </>
108
107
  ),
@@ -134,9 +133,9 @@ CustomSelectedValue.args = {
134
133
  <>
135
134
  { [ 'mystery-person', 'identicon', 'wavatar', 'retro' ].map(
136
135
  ( option ) => (
137
- <CustomSelectItem key={ option } value={ option }>
136
+ <CustomSelectControlV2.Item key={ option } value={ option }>
138
137
  { renderItem( option ) }
139
- </CustomSelectItem>
138
+ </CustomSelectControlV2.Item>
140
139
  )
141
140
  ) }
142
141
  </>
@@ -11,11 +11,12 @@ import { useState } from '@wordpress/element';
11
11
  /**
12
12
  * Internal dependencies
13
13
  */
14
- import CustomSelect from '../legacy-component';
14
+ import CustomSelectControl from '../legacy-component';
15
+ import * as V1Story from '../../custom-select-control/stories/index.story';
15
16
 
16
- const meta: Meta< typeof CustomSelect > = {
17
+ const meta: Meta< typeof CustomSelectControl > = {
17
18
  title: 'Components (Experimental)/CustomSelectControl v2/Legacy',
18
- component: CustomSelect,
19
+ component: CustomSelectControl,
19
20
  argTypes: {
20
21
  onChange: { control: { type: null } },
21
22
  value: { control: { type: null } },
@@ -42,46 +43,30 @@ const meta: Meta< typeof CustomSelect > = {
42
43
  };
43
44
  export default meta;
44
45
 
45
- const Template: StoryFn< typeof CustomSelect > = ( props ) => {
46
- const [ fontSize, setFontSize ] = useState( props.options[ 0 ] );
46
+ const Template: StoryFn< typeof CustomSelectControl > = ( props ) => {
47
+ const [ value, setValue ] = useState( props.options[ 0 ] );
47
48
 
48
49
  const onChange: React.ComponentProps<
49
- typeof CustomSelect
50
+ typeof CustomSelectControl
50
51
  >[ 'onChange' ] = ( changeObject ) => {
51
- setFontSize( changeObject.selectedItem );
52
+ setValue( changeObject.selectedItem );
52
53
  props.onChange?.( changeObject );
53
54
  };
54
55
 
55
56
  return (
56
- <CustomSelect { ...props } onChange={ onChange } value={ fontSize } />
57
+ <CustomSelectControl
58
+ { ...props }
59
+ onChange={ onChange }
60
+ value={ value }
61
+ />
57
62
  );
58
63
  };
59
64
 
60
65
  export const Default = Template.bind( {} );
61
- Default.args = {
62
- label: 'Label text',
63
- options: [
64
- {
65
- key: 'small',
66
- name: 'Small',
67
- style: { fontSize: '50%' },
68
- __experimentalHint: '50%',
69
- },
70
- {
71
- key: 'normal',
72
- name: 'Normal',
73
- style: { fontSize: '100%' },
74
- className: 'can-apply-custom-class-to-option',
75
- },
76
- {
77
- key: 'large',
78
- name: 'Large',
79
- style: { fontSize: '200%' },
80
- },
81
- {
82
- key: 'huge',
83
- name: 'Huge',
84
- style: { fontSize: '300%' },
85
- },
86
- ],
87
- };
66
+ Default.args = V1Story.Default.args;
67
+
68
+ export const WithLongLabels = Template.bind( {} );
69
+ WithLongLabels.args = V1Story.WithLongLabels.args;
70
+
71
+ export const WithHints = Template.bind( {} );
72
+ WithHints.args = V1Story.WithHints.args;