@wordpress/components 25.15.1-next.79a6196f.0 → 25.16.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 (259) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/build/border-box-control/border-box-control/component.js.map +1 -1
  3. package/build/border-box-control/border-box-control/hook.js +3 -1
  4. package/build/border-box-control/border-box-control/hook.js.map +1 -1
  5. package/build/border-box-control/types.js.map +1 -1
  6. package/build/border-control/border-control/component.js +5 -1
  7. package/build/border-control/border-control/component.js.map +1 -1
  8. package/build/border-control/border-control/hook.js +18 -15
  9. package/build/border-control/border-control/hook.js.map +1 -1
  10. package/build/border-control/border-control-dropdown/component.js +2 -1
  11. package/build/border-control/border-control-dropdown/component.js.map +1 -1
  12. package/build/border-control/border-control-style-picker/component.js +21 -49
  13. package/build/border-control/border-control-style-picker/component.js.map +1 -1
  14. package/build/border-control/styles.js +15 -27
  15. package/build/border-control/styles.js.map +1 -1
  16. package/build/border-control/types.js.map +1 -1
  17. package/build/box-control/all-input-control.js +35 -29
  18. package/build/box-control/all-input-control.js.map +1 -1
  19. package/build/box-control/axial-input-controls.js +40 -54
  20. package/build/box-control/axial-input-controls.js.map +1 -1
  21. package/build/box-control/index.js +21 -24
  22. package/build/box-control/index.js.map +1 -1
  23. package/build/box-control/input-controls.js +45 -37
  24. package/build/box-control/input-controls.js.map +1 -1
  25. package/build/box-control/styles/box-control-styles.js +50 -112
  26. package/build/box-control/styles/box-control-styles.js.map +1 -1
  27. package/build/box-control/types.js.map +1 -1
  28. package/build/box-control/utils.js +123 -8
  29. package/build/box-control/utils.js.map +1 -1
  30. package/build/button/index.js +14 -16
  31. package/build/button/index.js.map +1 -1
  32. package/build/button/types.js.map +1 -1
  33. package/build/color-picker/hsl-input.js +55 -33
  34. package/build/color-picker/hsl-input.js.map +1 -1
  35. package/build/custom-select-control-v2/index.js +3 -2
  36. package/build/custom-select-control-v2/index.js.map +1 -1
  37. package/build/slot-fill/bubbles-virtually/use-slot-fills.js +1 -1
  38. package/build/slot-fill/bubbles-virtually/use-slot-fills.js.map +1 -1
  39. package/build/theme/styles.js +11 -6
  40. package/build/theme/styles.js.map +1 -1
  41. package/build/toggle-group-control/toggle-group-control/utils.js +7 -1
  42. package/build/toggle-group-control/toggle-group-control/utils.js.map +1 -1
  43. package/build/tooltip/index.js +15 -12
  44. package/build/tooltip/index.js.map +1 -1
  45. package/build/tooltip/types.js.map +1 -1
  46. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  47. package/build-module/border-box-control/border-box-control/hook.js +3 -1
  48. package/build-module/border-box-control/border-box-control/hook.js.map +1 -1
  49. package/build-module/border-box-control/types.js.map +1 -1
  50. package/build-module/border-control/border-control/component.js +5 -1
  51. package/build-module/border-control/border-control/component.js.map +1 -1
  52. package/build-module/border-control/border-control/hook.js +18 -15
  53. package/build-module/border-control/border-control/hook.js.map +1 -1
  54. package/build-module/border-control/border-control-dropdown/component.js +2 -1
  55. package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
  56. package/build-module/border-control/border-control-style-picker/component.js +21 -48
  57. package/build-module/border-control/border-control-style-picker/component.js.map +1 -1
  58. package/build-module/border-control/styles.js +14 -24
  59. package/build-module/border-control/styles.js.map +1 -1
  60. package/build-module/border-control/types.js.map +1 -1
  61. package/build-module/box-control/all-input-control.js +38 -28
  62. package/build-module/box-control/all-input-control.js.map +1 -1
  63. package/build-module/box-control/axial-input-controls.js +42 -57
  64. package/build-module/box-control/axial-input-controls.js.map +1 -1
  65. package/build-module/box-control/index.js +22 -25
  66. package/build-module/box-control/index.js.map +1 -1
  67. package/build-module/box-control/input-controls.js +47 -40
  68. package/build-module/box-control/input-controls.js.map +1 -1
  69. package/build-module/box-control/styles/box-control-styles.js +45 -105
  70. package/build-module/box-control/styles/box-control-styles.js.map +1 -1
  71. package/build-module/box-control/types.js.map +1 -1
  72. package/build-module/box-control/utils.js +121 -7
  73. package/build-module/box-control/utils.js.map +1 -1
  74. package/build-module/button/index.js +14 -16
  75. package/build-module/button/index.js.map +1 -1
  76. package/build-module/button/types.js.map +1 -1
  77. package/build-module/color-picker/hsl-input.js +55 -33
  78. package/build-module/color-picker/hsl-input.js.map +1 -1
  79. package/build-module/custom-select-control-v2/index.js +3 -2
  80. package/build-module/custom-select-control-v2/index.js.map +1 -1
  81. package/build-module/slot-fill/bubbles-virtually/use-slot-fills.js +1 -1
  82. package/build-module/slot-fill/bubbles-virtually/use-slot-fills.js.map +1 -1
  83. package/build-module/theme/styles.js +11 -2
  84. package/build-module/theme/styles.js.map +1 -1
  85. package/build-module/toggle-group-control/toggle-group-control/utils.js +7 -1
  86. package/build-module/toggle-group-control/toggle-group-control/utils.js.map +1 -1
  87. package/build-module/tooltip/index.js +16 -13
  88. package/build-module/tooltip/index.js.map +1 -1
  89. package/build-module/tooltip/types.js.map +1 -1
  90. package/build-style/style-rtl.css +6 -4
  91. package/build-style/style.css +6 -4
  92. package/build-types/border-box-control/border-box-control/component.d.ts +1 -0
  93. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  94. package/build-types/border-box-control/border-box-control/hook.d.ts +4 -4
  95. package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
  96. package/build-types/border-box-control/border-box-control-linked-button/hook.d.ts +5 -5
  97. package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts +4 -4
  98. package/build-types/border-box-control/border-box-control-visualizer/hook.d.ts +4 -4
  99. package/build-types/border-box-control/stories/index.story.d.ts +2 -1
  100. package/build-types/border-box-control/stories/index.story.d.ts.map +1 -1
  101. package/build-types/border-box-control/types.d.ts +6 -0
  102. package/build-types/border-box-control/types.d.ts.map +1 -1
  103. package/build-types/border-control/border-control/component.d.ts +1 -0
  104. package/build-types/border-control/border-control/component.d.ts.map +1 -1
  105. package/build-types/border-control/border-control/hook.d.ts +6 -4
  106. package/build-types/border-control/border-control/hook.d.ts.map +1 -1
  107. package/build-types/border-control/border-control-dropdown/component.d.ts +1 -0
  108. package/build-types/border-control/border-control-dropdown/component.d.ts.map +1 -1
  109. package/build-types/border-control/border-control-dropdown/hook.d.ts +5 -4
  110. package/build-types/border-control/border-control-dropdown/hook.d.ts.map +1 -1
  111. package/build-types/border-control/border-control-style-picker/component.d.ts +3 -4
  112. package/build-types/border-control/border-control-style-picker/component.d.ts.map +1 -1
  113. package/build-types/border-control/stories/index.story.d.ts +12 -6
  114. package/build-types/border-control/stories/index.story.d.ts.map +1 -1
  115. package/build-types/border-control/styles.d.ts +0 -2
  116. package/build-types/border-control/styles.d.ts.map +1 -1
  117. package/build-types/border-control/types.d.ts +12 -1
  118. package/build-types/border-control/types.d.ts.map +1 -1
  119. package/build-types/box-control/all-input-control.d.ts +1 -1
  120. package/build-types/box-control/all-input-control.d.ts.map +1 -1
  121. package/build-types/box-control/axial-input-controls.d.ts +1 -1
  122. package/build-types/box-control/axial-input-controls.d.ts.map +1 -1
  123. package/build-types/box-control/index.d.ts +1 -1
  124. package/build-types/box-control/index.d.ts.map +1 -1
  125. package/build-types/box-control/input-controls.d.ts +1 -1
  126. package/build-types/box-control/input-controls.d.ts.map +1 -1
  127. package/build-types/box-control/stories/index.story.d.ts +42 -36
  128. package/build-types/box-control/stories/index.story.d.ts.map +1 -1
  129. package/build-types/box-control/styles/box-control-styles.d.ts +49 -23
  130. package/build-types/box-control/styles/box-control-styles.d.ts.map +1 -1
  131. package/build-types/box-control/types.d.ts +12 -12
  132. package/build-types/box-control/types.d.ts.map +1 -1
  133. package/build-types/box-control/utils.d.ts +2 -1
  134. package/build-types/box-control/utils.d.ts.map +1 -1
  135. package/build-types/button/deprecated.d.ts +3 -3
  136. package/build-types/button/index.d.ts.map +1 -1
  137. package/build-types/button/types.d.ts +7 -3
  138. package/build-types/button/types.d.ts.map +1 -1
  139. package/build-types/card/card/hook.d.ts +4 -4
  140. package/build-types/card/card-body/hook.d.ts +4 -4
  141. package/build-types/card/card-divider/hook.d.ts +4 -4
  142. package/build-types/card/card-footer/hook.d.ts +4 -4
  143. package/build-types/card/card-header/hook.d.ts +4 -4
  144. package/build-types/card/card-media/hook.d.ts +4 -4
  145. package/build-types/color-palette/styles.d.ts +2 -2
  146. package/build-types/color-picker/component.d.ts +1 -1
  147. package/build-types/color-picker/hsl-input.d.ts.map +1 -1
  148. package/build-types/color-picker/stories/index.story.d.ts +1 -1
  149. package/build-types/color-picker/styles.d.ts +3 -3
  150. package/build-types/custom-select-control-v2/index.d.ts.map +1 -1
  151. package/build-types/date-time/date/styles.d.ts +3 -3
  152. package/build-types/date-time/date-time/styles.d.ts +1 -1
  153. package/build-types/date-time/time/styles.d.ts +4 -4
  154. package/build-types/elevation/hook.d.ts +4 -4
  155. package/build-types/flex/flex/hook.d.ts +4 -4
  156. package/build-types/flex/flex-block/hook.d.ts +4 -4
  157. package/build-types/flex/flex-item/hook.d.ts +4 -4
  158. package/build-types/focal-point-picker/styles/focal-point-picker-style.d.ts +1 -1
  159. package/build-types/font-size-picker/styles.d.ts +1 -1
  160. package/build-types/grid/hook.d.ts +4 -4
  161. package/build-types/h-stack/hook.d.ts +4 -4
  162. package/build-types/heading/component.d.ts +1 -1
  163. package/build-types/heading/hook.d.ts +4 -4
  164. package/build-types/item-group/item/hook.d.ts +4 -4
  165. package/build-types/item-group/item-group/hook.d.ts +4 -4
  166. package/build-types/menu-item/index.d.ts +1 -1
  167. package/build-types/menu-item/stories/index.story.d.ts +4 -4
  168. package/build-types/navigation/styles/navigation-styles.d.ts +2 -2
  169. package/build-types/navigator/navigator-back-button/hook.d.ts +4 -4
  170. package/build-types/navigator/navigator-button/hook.d.ts +4 -4
  171. package/build-types/number-control/index.d.ts +1 -1
  172. package/build-types/number-control/stories/index.story.d.ts +1 -1
  173. package/build-types/palette-edit/styles.d.ts +3 -3
  174. package/build-types/range-control/index.d.ts +1 -1
  175. package/build-types/range-control/styles/range-control-styles.d.ts +1 -1
  176. package/build-types/resizable-box/index.d.ts +1 -1
  177. package/build-types/resizable-box/resize-tooltip/index.d.ts +1 -1
  178. package/build-types/resizable-box/stories/index.story.d.ts +2 -2
  179. package/build-types/scrollable/hook.d.ts +4 -4
  180. package/build-types/spacer/hook.d.ts +4 -4
  181. package/build-types/surface/hook.d.ts +4 -4
  182. package/build-types/text/hook.d.ts +4 -4
  183. package/build-types/theme/styles.d.ts.map +1 -1
  184. package/build-types/toggle-control/stories/index.story.d.ts +2 -2
  185. package/build-types/toggle-group-control/toggle-group-control/utils.d.ts.map +1 -1
  186. package/build-types/toggle-group-control/toggle-group-control-option-icon/component.d.ts +1 -1
  187. package/build-types/toolbar/toolbar-button/index.d.ts +3 -3
  188. package/build-types/tools-panel/tools-panel/hook.d.ts +4 -4
  189. package/build-types/tools-panel/tools-panel-header/hook.d.ts +4 -4
  190. package/build-types/tools-panel/tools-panel-item/hook.d.ts +4 -4
  191. package/build-types/tooltip/index.d.ts +1 -1
  192. package/build-types/tooltip/index.d.ts.map +1 -1
  193. package/build-types/tooltip/stories/index.story.d.ts +1 -1
  194. package/build-types/tooltip/stories/index.story.d.ts.map +1 -1
  195. package/build-types/tooltip/types.d.ts +1 -1
  196. package/build-types/tooltip/types.d.ts.map +1 -1
  197. package/build-types/truncate/hook.d.ts +4 -4
  198. package/build-types/unit-control/index.d.ts +1 -1
  199. package/build-types/unit-control/styles/unit-control-styles.d.ts +1 -1
  200. package/build-types/v-stack/hook.d.ts +4 -4
  201. package/build-types/v-stack/stories/index.story.d.ts +1 -1
  202. package/package.json +19 -19
  203. package/src/border-box-control/border-box-control/component.tsx +0 -1
  204. package/src/border-box-control/border-box-control/hook.ts +5 -1
  205. package/src/border-box-control/types.ts +6 -0
  206. package/src/border-control/border-control/component.tsx +4 -0
  207. package/src/border-control/border-control/hook.ts +22 -16
  208. package/src/border-control/border-control-dropdown/component.tsx +2 -1
  209. package/src/border-control/border-control-style-picker/component.tsx +31 -66
  210. package/src/border-control/styles.ts +0 -15
  211. package/src/border-control/types.ts +15 -1
  212. package/src/box-control/all-input-control.tsx +57 -34
  213. package/src/box-control/axial-input-controls.tsx +79 -69
  214. package/src/box-control/index.tsx +47 -54
  215. package/src/box-control/input-controls.tsx +114 -83
  216. package/src/box-control/styles/box-control-styles.ts +21 -61
  217. package/src/box-control/test/index.tsx +126 -18
  218. package/src/box-control/types.ts +10 -21
  219. package/src/box-control/utils.ts +43 -8
  220. package/src/button/README.md +1 -1
  221. package/src/button/index.tsx +21 -33
  222. package/src/button/test/index.tsx +122 -0
  223. package/src/button/types.ts +7 -3
  224. package/src/circular-option-picker/test/index.tsx +10 -16
  225. package/src/color-picker/hsl-input.tsx +56 -30
  226. package/src/color-picker/test/index.tsx +190 -16
  227. package/src/custom-select-control-v2/index.tsx +5 -2
  228. package/src/palette-edit/test/index.tsx +326 -10
  229. package/src/slot-fill/bubbles-virtually/use-slot-fills.ts +1 -1
  230. package/src/tabs/test/index.tsx +3 -1
  231. package/src/theme/styles.ts +3 -1
  232. package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +6 -6
  233. package/src/toggle-group-control/test/index.tsx +73 -36
  234. package/src/toggle-group-control/toggle-group-control/utils.ts +8 -3
  235. package/src/tooltip/index.tsx +29 -29
  236. package/src/tooltip/test/index.tsx +32 -13
  237. package/src/tooltip/types.ts +1 -1
  238. package/tsconfig.tsbuildinfo +1 -1
  239. package/build/border-control/border-control-style-picker/hook.js +0 -41
  240. package/build/border-control/border-control-style-picker/hook.js.map +0 -1
  241. package/build/box-control/styles/box-control-visualizer-styles.js +0 -93
  242. package/build/box-control/styles/box-control-visualizer-styles.js.map +0 -1
  243. package/build/box-control/unit-control.js +0 -76
  244. package/build/box-control/unit-control.js.map +0 -1
  245. package/build-module/border-control/border-control-style-picker/hook.js +0 -32
  246. package/build-module/border-control/border-control-style-picker/hook.js.map +0 -1
  247. package/build-module/box-control/styles/box-control-visualizer-styles.js +0 -86
  248. package/build-module/box-control/styles/box-control-visualizer-styles.js.map +0 -1
  249. package/build-module/box-control/unit-control.js +0 -68
  250. package/build-module/box-control/unit-control.js.map +0 -1
  251. package/build-types/border-control/border-control-style-picker/hook.d.ts +0 -267
  252. package/build-types/border-control/border-control-style-picker/hook.d.ts.map +0 -1
  253. package/build-types/box-control/styles/box-control-visualizer-styles.d.ts +0 -46
  254. package/build-types/box-control/styles/box-control-visualizer-styles.d.ts.map +0 -1
  255. package/build-types/box-control/unit-control.d.ts +0 -4
  256. package/build-types/box-control/unit-control.d.ts.map +0 -1
  257. package/src/border-control/border-control-style-picker/hook.ts +0 -35
  258. package/src/box-control/styles/box-control-visualizer-styles.ts +0 -75
  259. package/src/box-control/unit-control.tsx +0 -74
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { render, fireEvent, screen } from '@testing-library/react';
4
+ import { render, screen, waitFor } from '@testing-library/react';
5
+ import { click, type, press } from '@ariakit/test';
5
6
 
6
7
  /**
7
8
  * Internal dependencies
@@ -9,6 +10,17 @@ import { render, fireEvent, screen } from '@testing-library/react';
9
10
  import PaletteEdit, { getNameForPosition } from '..';
10
11
  import type { PaletteElement } from '../types';
11
12
 
13
+ const noop = () => {};
14
+
15
+ async function clearInput( input: HTMLInputElement ) {
16
+ await click( input );
17
+
18
+ // Press backspace as many times as the input's current value
19
+ for ( const _ of Array( input.value.length ) ) {
20
+ await press.Backspace();
21
+ }
22
+ }
23
+
12
24
  describe( 'getNameForPosition', () => {
13
25
  test( 'should return 1 by default', () => {
14
26
  const slugPrefix = 'test-';
@@ -82,18 +94,322 @@ describe( 'getNameForPosition', () => {
82
94
 
83
95
  describe( 'PaletteEdit', () => {
84
96
  const defaultProps = {
85
- colors: [ { color: '#ffffff', name: 'Base', slug: 'base' } ],
86
- onChange: jest.fn(),
87
97
  paletteLabel: 'Test label',
88
- emptyMessage: 'Test empty message',
89
- canOnlyChangeValues: true,
90
- canReset: true,
91
98
  slugPrefix: '',
99
+ onChange: noop,
92
100
  };
93
101
 
94
- it( 'opens color selector for color palettes', () => {
95
- render( <PaletteEdit { ...defaultProps } /> );
96
- fireEvent.click( screen.getByLabelText( 'Color: Base' ) );
97
- expect( screen.getByLabelText( 'Hex color' ) ).toBeInTheDocument();
102
+ const colors = [
103
+ { color: '#1a4548', name: 'Primary', slug: 'primary' },
104
+ { color: '#0000ff', name: 'Secondary', slug: 'secondary' },
105
+ ];
106
+ const gradients = [
107
+ {
108
+ gradient:
109
+ 'linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)',
110
+ name: 'Pale ocean',
111
+ slug: 'pale-ocean',
112
+ },
113
+ {
114
+ gradient:
115
+ 'linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)',
116
+ name: 'Midnight',
117
+ slug: 'midnight',
118
+ },
119
+ ];
120
+
121
+ it( 'shows heading label', () => {
122
+ render( <PaletteEdit { ...defaultProps } colors={ colors } /> );
123
+
124
+ const paletteLabel = screen.getByRole( 'heading', {
125
+ level: 2,
126
+ name: 'Test label',
127
+ } );
128
+
129
+ expect( paletteLabel ).toBeVisible();
130
+ } );
131
+
132
+ it( 'shows heading label with custom heading level', () => {
133
+ render(
134
+ <PaletteEdit
135
+ { ...defaultProps }
136
+ colors={ colors }
137
+ paletteLabelHeadingLevel={ 5 }
138
+ />
139
+ );
140
+
141
+ expect(
142
+ screen.getByRole( 'heading', {
143
+ level: 5,
144
+ name: 'Test label',
145
+ } )
146
+ ).toBeVisible();
147
+ } );
148
+
149
+ it( 'shows empty message', () => {
150
+ render(
151
+ <PaletteEdit
152
+ { ...defaultProps }
153
+ emptyMessage={ 'Test empty message' }
154
+ />
155
+ );
156
+
157
+ expect( screen.getByText( 'Test empty message' ) ).toBeVisible();
158
+ } );
159
+
160
+ it( 'shows an option to remove all colors', async () => {
161
+ render( <PaletteEdit { ...defaultProps } colors={ colors } /> );
162
+
163
+ await click(
164
+ screen.getByRole( 'button', {
165
+ name: 'Color options',
166
+ } )
167
+ );
168
+
169
+ expect(
170
+ screen.getByRole( 'button', {
171
+ name: 'Remove all colors',
172
+ } )
173
+ ).toBeVisible();
174
+ } );
175
+
176
+ it( 'shows a reset option when the `canReset` prop is enabled', async () => {
177
+ render(
178
+ <PaletteEdit { ...defaultProps } colors={ colors } canReset />
179
+ );
180
+
181
+ await click(
182
+ screen.getByRole( 'button', {
183
+ name: 'Color options',
184
+ } )
185
+ );
186
+ expect(
187
+ screen.getByRole( 'button', {
188
+ name: 'Reset colors',
189
+ } )
190
+ ).toBeVisible();
191
+ } );
192
+
193
+ it( 'does not show a reset colors option when `canReset` is disabled', async () => {
194
+ render( <PaletteEdit { ...defaultProps } colors={ colors } /> );
195
+
196
+ await click(
197
+ screen.getByRole( 'button', {
198
+ name: 'Color options',
199
+ } )
200
+ );
201
+ expect(
202
+ screen.queryByRole( 'button', {
203
+ name: 'Reset colors',
204
+ } )
205
+ ).not.toBeInTheDocument();
206
+ } );
207
+
208
+ it( 'calls the `onChange` with the new color appended', async () => {
209
+ const onChange = jest.fn();
210
+
211
+ render(
212
+ <PaletteEdit
213
+ { ...defaultProps }
214
+ colors={ colors }
215
+ onChange={ onChange }
216
+ />
217
+ );
218
+
219
+ await click(
220
+ screen.getByRole( 'button', {
221
+ name: 'Add color',
222
+ } )
223
+ );
224
+
225
+ await waitFor( () => {
226
+ expect( onChange ).toHaveBeenCalledWith( [
227
+ ...colors,
228
+ {
229
+ color: '#000',
230
+ name: 'Color 1',
231
+ slug: 'color-1',
232
+ },
233
+ ] );
234
+ } );
235
+ } );
236
+
237
+ it( 'calls the `onChange` with the new gradient appended', async () => {
238
+ const onChange = jest.fn();
239
+
240
+ render(
241
+ <PaletteEdit
242
+ { ...defaultProps }
243
+ gradients={ gradients }
244
+ onChange={ onChange }
245
+ />
246
+ );
247
+
248
+ await click(
249
+ screen.getByRole( 'button', {
250
+ name: 'Add gradient',
251
+ } )
252
+ );
253
+
254
+ await waitFor( () => {
255
+ expect( onChange ).toHaveBeenCalledWith( [
256
+ ...gradients,
257
+ {
258
+ gradient:
259
+ 'linear-gradient(135deg, rgba(6, 147, 227, 1) 0%, rgb(155, 81, 224) 100%)',
260
+ name: 'Color 1',
261
+ slug: 'color-1',
262
+ },
263
+ ] );
264
+ } );
265
+ } );
266
+
267
+ it( 'can not add new colors when `canOnlyChangeValues` is enabled', () => {
268
+ render( <PaletteEdit { ...defaultProps } canOnlyChangeValues /> );
269
+
270
+ expect(
271
+ screen.queryByRole( 'button', {
272
+ name: 'Add color',
273
+ } )
274
+ ).not.toBeInTheDocument();
275
+ } );
276
+
277
+ it( 'can remove a color', async () => {
278
+ const onChange = jest.fn();
279
+
280
+ render(
281
+ <PaletteEdit
282
+ { ...defaultProps }
283
+ colors={ colors }
284
+ onChange={ onChange }
285
+ />
286
+ );
287
+
288
+ await click(
289
+ screen.getByRole( 'button', {
290
+ name: 'Color options',
291
+ } )
292
+ );
293
+ await click(
294
+ screen.getByRole( 'button', {
295
+ name: 'Show details',
296
+ } )
297
+ );
298
+ await click( screen.getByText( 'Primary' ) );
299
+ await click(
300
+ screen.getByRole( 'button', {
301
+ name: 'Remove color',
302
+ } )
303
+ );
304
+
305
+ await waitFor( () => {
306
+ expect( onChange ).toHaveBeenCalledWith( [ colors[ 1 ] ] );
307
+ } );
308
+ } );
309
+
310
+ it( 'can update palette name', async () => {
311
+ const onChange = jest.fn();
312
+
313
+ render(
314
+ <PaletteEdit
315
+ { ...defaultProps }
316
+ colors={ colors }
317
+ onChange={ onChange }
318
+ />
319
+ );
320
+
321
+ await click(
322
+ screen.getByRole( 'button', {
323
+ name: 'Color options',
324
+ } )
325
+ );
326
+ await click(
327
+ screen.getByRole( 'button', {
328
+ name: 'Show details',
329
+ } )
330
+ );
331
+ await click( screen.getByText( 'Primary' ) );
332
+ const nameInput = screen.getByRole( 'textbox', {
333
+ name: 'Color name',
334
+ } );
335
+
336
+ await clearInput( nameInput as HTMLInputElement );
337
+
338
+ await type( 'Primary Updated' );
339
+
340
+ await waitFor( () => {
341
+ expect( onChange ).toHaveBeenCalledWith( [
342
+ {
343
+ ...colors[ 0 ],
344
+ name: 'Primary Updated',
345
+ slug: 'primary-updated',
346
+ },
347
+ colors[ 1 ],
348
+ ] );
349
+ } );
350
+ } );
351
+
352
+ it( 'can update color palette value', async () => {
353
+ const onChange = jest.fn();
354
+
355
+ render(
356
+ <PaletteEdit
357
+ { ...defaultProps }
358
+ colors={ colors }
359
+ onChange={ onChange }
360
+ />
361
+ );
362
+
363
+ await click( screen.getByLabelText( 'Color: Primary' ) );
364
+ const hexInput = screen.getByRole( 'textbox', {
365
+ name: 'Hex color',
366
+ } );
367
+
368
+ await clearInput( hexInput as HTMLInputElement );
369
+
370
+ await type( '000000' );
371
+
372
+ await waitFor( () => {
373
+ expect( onChange ).toHaveBeenCalledWith( [
374
+ {
375
+ ...colors[ 0 ],
376
+ color: '#000000',
377
+ },
378
+ colors[ 1 ],
379
+ ] );
380
+ } );
381
+ } );
382
+
383
+ it( 'can update gradient palette value', async () => {
384
+ const onChange = jest.fn();
385
+
386
+ render(
387
+ <PaletteEdit
388
+ { ...defaultProps }
389
+ gradients={ gradients }
390
+ onChange={ onChange }
391
+ />
392
+ );
393
+
394
+ await click( screen.getByLabelText( 'Gradient: Pale ocean' ) );
395
+
396
+ // Select radial gradient option
397
+ await click(
398
+ screen.getByRole( 'combobox', {
399
+ name: 'Type',
400
+ } )
401
+ );
402
+ await click( screen.getByRole( 'option', { name: 'Radial' } ) );
403
+
404
+ await waitFor( () => {
405
+ expect( onChange ).toHaveBeenCalledWith( [
406
+ {
407
+ ...gradients[ 0 ],
408
+ gradient:
409
+ 'radial-gradient(rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)',
410
+ },
411
+ gradients[ 1 ],
412
+ ] );
413
+ } );
98
414
  } );
99
415
  } );
@@ -19,6 +19,6 @@ export default function useSlotFills( name: SlotKey ) {
19
19
  const fills = useSnapshot( registry.fills, { sync: true } );
20
20
  // The important bit here is that this call ensures that the hook
21
21
  // only causes a re-render if the "fills" of a given slot name
22
- // change change, not any fills.
22
+ // change, not any fills.
23
23
  return fills.get( name );
24
24
  }
@@ -1260,7 +1260,9 @@ describe( 'Tabs', () => {
1260
1260
 
1261
1261
  // Tab key should focus the currently selected tab, which is Beta.
1262
1262
  await press.Tab();
1263
- expect( await getSelectedTab() ).toHaveFocus();
1263
+ await waitFor( async () =>
1264
+ expect( await getSelectedTab() ).toHaveFocus()
1265
+ );
1264
1266
 
1265
1267
  rerender(
1266
1268
  <ControlledTabs
@@ -30,4 +30,6 @@ export const colorVariables = ( { colors }: ThemeOutputValues ) => {
30
30
  ];
31
31
  };
32
32
 
33
- export const Wrapper = styled.div``;
33
+ export const Wrapper = styled.div`
34
+ color: var( --wp-components-color-foreground, currentColor );
35
+ `;
@@ -240,7 +240,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
240
240
  class="components-toggle-group-control emotion-8 emotion-9"
241
241
  data-wp-c16t="true"
242
242
  data-wp-component="ToggleGroupControl"
243
- id="toggle-group-control-as-radio-group-8"
243
+ id="toggle-group-control-as-radio-group-10"
244
244
  role="radiogroup"
245
245
  >
246
246
  <div
@@ -254,7 +254,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
254
254
  data-value="uppercase"
255
255
  data-wp-c16t="true"
256
256
  data-wp-component="ToggleGroupControlOptionBase"
257
- id="toggle-group-control-as-radio-group-8-20"
257
+ id="toggle-group-control-as-radio-group-10-24"
258
258
  role="radio"
259
259
  type="button"
260
260
  value="uppercase"
@@ -292,7 +292,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
292
292
  data-value="lowercase"
293
293
  data-wp-c16t="true"
294
294
  data-wp-component="ToggleGroupControlOptionBase"
295
- id="toggle-group-control-as-radio-group-8-21"
295
+ id="toggle-group-control-as-radio-group-10-25"
296
296
  role="radio"
297
297
  type="button"
298
298
  value="lowercase"
@@ -488,7 +488,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options
488
488
  class="components-toggle-group-control emotion-8 emotion-9"
489
489
  data-wp-c16t="true"
490
490
  data-wp-component="ToggleGroupControl"
491
- id="toggle-group-control-as-radio-group-7"
491
+ id="toggle-group-control-as-radio-group-9"
492
492
  role="radiogroup"
493
493
  >
494
494
  <div
@@ -501,7 +501,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options
501
501
  data-value="rigas"
502
502
  data-wp-c16t="true"
503
503
  data-wp-component="ToggleGroupControlOptionBase"
504
- id="toggle-group-control-as-radio-group-7-18"
504
+ id="toggle-group-control-as-radio-group-9-22"
505
505
  role="radio"
506
506
  type="button"
507
507
  value="rigas"
@@ -523,7 +523,7 @@ exports[`ToggleGroupControl controlled should render correctly with text options
523
523
  data-value="jack"
524
524
  data-wp-c16t="true"
525
525
  data-wp-component="ToggleGroupControlOptionBase"
526
- id="toggle-group-control-as-radio-group-7-19"
526
+ id="toggle-group-control-as-radio-group-9-23"
527
527
  role="radio"
528
528
  type="button"
529
529
  value="jack"
@@ -117,6 +117,22 @@ describe.each( [
117
117
  expect( container ).toMatchSnapshot();
118
118
  } );
119
119
  } );
120
+ it( 'should render with the correct option initially selected when `value` is defined', () => {
121
+ render(
122
+ <Component value="jack" label="Test Toggle Group Control">
123
+ { options }
124
+ </Component>
125
+ );
126
+ expect( screen.getByRole( 'radio', { name: 'R' } ) ).not.toBeChecked();
127
+ expect( screen.getByRole( 'radio', { name: 'J' } ) ).toBeChecked();
128
+ } );
129
+ it( 'should render without a selected option when `value` is `undefined`', () => {
130
+ render(
131
+ <Component label="Test Toggle Group Control">{ options }</Component>
132
+ );
133
+ expect( screen.getByRole( 'radio', { name: 'R' } ) ).not.toBeChecked();
134
+ expect( screen.getByRole( 'radio', { name: 'J' } ) ).not.toBeChecked();
135
+ } );
120
136
  it( 'should call onChange with proper value', async () => {
121
137
  const mockOnChange = jest.fn();
122
138
 
@@ -193,7 +209,7 @@ describe.each( [
193
209
  } );
194
210
 
195
211
  if ( mode === 'controlled' ) {
196
- it( 'should reset values correctly', async () => {
212
+ it( 'should reset values correctly when default value is undefined', async () => {
197
213
  render(
198
214
  <Component label="Test Toggle Group Control">
199
215
  { options }
@@ -208,56 +224,77 @@ describe.each( [
208
224
  expect( jackOption ).not.toBeChecked();
209
225
  expect( rigasOption ).toBeChecked();
210
226
 
211
- await press.ArrowRight();
212
-
213
- expect( rigasOption ).not.toBeChecked();
214
- expect( jackOption ).toBeChecked();
215
-
216
227
  await click( screen.getByRole( 'button', { name: 'Reset' } ) );
217
228
 
218
229
  expect( rigasOption ).not.toBeChecked();
219
230
  expect( jackOption ).not.toBeChecked();
220
231
  } );
221
232
 
222
- it( 'should update correctly when triggered by external updates', async () => {
233
+ it( 'should reset values correctly when default value is defined', async () => {
223
234
  render(
224
- <Component
225
- value="rigas"
226
- label="Test Toggle Group Control"
227
- extraButtonOptions={ [
228
- { name: 'Rigas', value: 'rigas' },
229
- { name: 'Jack', value: 'jack' },
230
- ] }
231
- >
235
+ <Component label="Test Toggle Group Control" value="rigas">
232
236
  { options }
233
237
  </Component>
234
238
  );
235
239
 
236
- expect( screen.getByRole( 'radio', { name: 'R' } ) ).toBeChecked();
237
- expect(
238
- screen.getByRole( 'radio', { name: 'J' } )
239
- ).not.toBeChecked();
240
-
241
- await click( screen.getByRole( 'button', { name: 'Jack' } ) );
242
- expect( screen.getByRole( 'radio', { name: 'J' } ) ).toBeChecked();
243
- expect(
244
- screen.getByRole( 'radio', { name: 'R' } )
245
- ).not.toBeChecked();
240
+ const rigasOption = screen.getByRole( 'radio', {
241
+ name: 'R',
242
+ } );
243
+ const jackOption = screen.getByRole( 'radio', {
244
+ name: 'J',
245
+ } );
246
246
 
247
- await click( screen.getByRole( 'button', { name: 'Rigas' } ) );
248
- expect( screen.getByRole( 'radio', { name: 'R' } ) ).toBeChecked();
249
- expect(
250
- screen.getByRole( 'radio', { name: 'J' } )
251
- ).not.toBeChecked();
247
+ expect( rigasOption ).toBeChecked();
248
+ expect( jackOption ).not.toBeChecked();
252
249
 
253
250
  await click( screen.getByRole( 'button', { name: 'Reset' } ) );
254
- expect(
255
- screen.getByRole( 'radio', { name: 'R' } )
256
- ).not.toBeChecked();
257
- expect(
258
- screen.getByRole( 'radio', { name: 'J' } )
259
- ).not.toBeChecked();
251
+
252
+ expect( rigasOption ).not.toBeChecked();
253
+ expect( jackOption ).not.toBeChecked();
260
254
  } );
255
+
256
+ describe.each( [
257
+ [ 'undefined', undefined ],
258
+ [ 'defined', 'rigas' ],
259
+ ] )(
260
+ 'should update correctly when triggered by external updates',
261
+ ( defaultValueType, defaultValue ) => {
262
+ it( `when default value is ${ defaultValueType }`, async () => {
263
+ render(
264
+ <Component
265
+ value={ defaultValue }
266
+ label="Test Toggle Group Control"
267
+ extraButtonOptions={ [
268
+ { name: 'Rigas', value: 'rigas' },
269
+ { name: 'Jack', value: 'jack' },
270
+ ] }
271
+ >
272
+ { options }
273
+ </Component>
274
+ );
275
+
276
+ await click(
277
+ screen.getByRole( 'button', { name: 'Jack' } )
278
+ );
279
+ expect(
280
+ screen.getByRole( 'radio', { name: 'J' } )
281
+ ).toBeChecked();
282
+ expect(
283
+ screen.getByRole( 'radio', { name: 'R' } )
284
+ ).not.toBeChecked();
285
+
286
+ await click(
287
+ screen.getByRole( 'button', { name: 'Rigas' } )
288
+ );
289
+ expect(
290
+ screen.getByRole( 'radio', { name: 'R' } )
291
+ ).toBeChecked();
292
+ expect(
293
+ screen.getByRole( 'radio', { name: 'J' } )
294
+ ).not.toBeChecked();
295
+ } );
296
+ }
297
+ );
261
298
  }
262
299
 
263
300
  describe( 'isDeselectable', () => {
@@ -21,16 +21,21 @@ type ValueProp = ToggleGroupControlProps[ 'value' ];
21
21
  export function useComputeControlledOrUncontrolledValue(
22
22
  valueProp: ValueProp
23
23
  ): { value: ValueProp; defaultValue: ValueProp } {
24
+ const isInitialRender = useRef( true );
24
25
  const prevValueProp = usePrevious( valueProp );
25
26
  const prevIsControlled = useRef( false );
26
27
 
28
+ useEffect( () => {
29
+ if ( isInitialRender.current ) {
30
+ isInitialRender.current = false;
31
+ }
32
+ }, [] );
33
+
27
34
  // Assume the component is being used in controlled mode on the first re-render
28
35
  // that has a different `valueProp` from the previous render.
29
36
  const isControlled =
30
37
  prevIsControlled.current ||
31
- ( prevValueProp !== undefined &&
32
- valueProp !== undefined &&
33
- prevValueProp !== valueProp );
38
+ ( ! isInitialRender.current && prevValueProp !== valueProp );
34
39
  useEffect( () => {
35
40
  prevIsControlled.current = isControlled;
36
41
  }, [ isControlled ] );