@wordpress/components 30.6.1-next.b8c8708f3.0 → 30.6.1

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 (55) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/build/custom-select-control-v2/custom-select.js +2 -2
  3. package/build/custom-select-control-v2/custom-select.js.map +2 -2
  4. package/build/font-size-picker/font-size-picker-select.js +20 -19
  5. package/build/font-size-picker/font-size-picker-select.js.map +3 -3
  6. package/build/font-size-picker/font-size-picker-toggle-group.js +27 -3
  7. package/build/font-size-picker/font-size-picker-toggle-group.js.map +2 -2
  8. package/build/font-size-picker/index.js +23 -11
  9. package/build/font-size-picker/index.js.map +2 -2
  10. package/build/font-size-picker/styles.js +30 -13
  11. package/build/font-size-picker/styles.js.map +3 -3
  12. package/build/font-size-picker/utils.js +11 -0
  13. package/build/font-size-picker/utils.js.map +2 -2
  14. package/build-module/custom-select-control-v2/custom-select.js +1 -1
  15. package/build-module/custom-select-control-v2/custom-select.js.map +1 -1
  16. package/build-module/font-size-picker/font-size-picker-select.js +21 -10
  17. package/build-module/font-size-picker/font-size-picker-select.js.map +2 -2
  18. package/build-module/font-size-picker/font-size-picker-toggle-group.js +27 -3
  19. package/build-module/font-size-picker/font-size-picker-toggle-group.js.map +2 -2
  20. package/build-module/font-size-picker/index.js +23 -11
  21. package/build-module/font-size-picker/index.js.map +2 -2
  22. package/build-module/font-size-picker/styles.js +28 -12
  23. package/build-module/font-size-picker/styles.js.map +2 -2
  24. package/build-module/font-size-picker/utils.js +10 -0
  25. package/build-module/font-size-picker/utils.js.map +2 -2
  26. package/build-style/style-rtl.css +1 -0
  27. package/build-style/style.css +1 -0
  28. package/build-types/font-size-picker/font-size-picker-select.d.ts +3 -0
  29. package/build-types/font-size-picker/font-size-picker-select.d.ts.map +1 -1
  30. package/build-types/font-size-picker/font-size-picker-toggle-group.d.ts.map +1 -1
  31. package/build-types/font-size-picker/index.d.ts.map +1 -1
  32. package/build-types/font-size-picker/styles.d.ts +3 -0
  33. package/build-types/font-size-picker/styles.d.ts.map +1 -1
  34. package/build-types/font-size-picker/test/font-size-picker-select.d.ts +2 -0
  35. package/build-types/font-size-picker/test/font-size-picker-select.d.ts.map +1 -0
  36. package/build-types/font-size-picker/test/font-size-picker-toggle-group.d.ts +2 -0
  37. package/build-types/font-size-picker/test/font-size-picker-toggle-group.d.ts.map +1 -0
  38. package/build-types/font-size-picker/types.d.ts +18 -4
  39. package/build-types/font-size-picker/types.d.ts.map +1 -1
  40. package/build-types/font-size-picker/utils.d.ts +10 -1
  41. package/build-types/font-size-picker/utils.d.ts.map +1 -1
  42. package/package.json +20 -20
  43. package/src/badge/styles.scss +1 -0
  44. package/src/custom-select-control-v2/custom-select.tsx +1 -1
  45. package/src/font-size-picker/README.md +10 -0
  46. package/src/font-size-picker/font-size-picker-select.tsx +44 -11
  47. package/src/font-size-picker/font-size-picker-toggle-group.tsx +58 -4
  48. package/src/font-size-picker/index.tsx +44 -19
  49. package/src/font-size-picker/styles.ts +9 -0
  50. package/src/font-size-picker/test/font-size-picker-select.tsx +221 -0
  51. package/src/font-size-picker/test/font-size-picker-toggle-group.tsx +275 -0
  52. package/src/font-size-picker/test/index.tsx +460 -2
  53. package/src/font-size-picker/types.ts +24 -4
  54. package/src/font-size-picker/utils.ts +23 -1
  55. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,221 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { screen } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
6
+ import { render } from '@ariakit/test/react';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import FontSizePickerSelect from '../font-size-picker-select';
12
+ import type { FontSize } from '../types';
13
+
14
+ describe( 'FontSizePickerSelect', () => {
15
+ const fontSizes: FontSize[] = [
16
+ {
17
+ slug: 'small',
18
+ name: 'Small',
19
+ size: '12px',
20
+ },
21
+ {
22
+ slug: 'medium',
23
+ name: 'Medium',
24
+ size: '16px',
25
+ },
26
+ {
27
+ slug: 'large',
28
+ name: 'Large',
29
+ size: '20px',
30
+ },
31
+ ];
32
+
33
+ describe( 'valueMode prop', () => {
34
+ it( 'should find font size by size value when valueMode is literal', async () => {
35
+ const onChange = jest.fn();
36
+ await render(
37
+ <FontSizePickerSelect
38
+ fontSizes={ fontSizes }
39
+ value="16px"
40
+ valueMode="literal"
41
+ onChange={ onChange }
42
+ onSelectCustom={ jest.fn() }
43
+ disableCustomFontSizes={ false }
44
+ __next40pxDefaultSize={ false }
45
+ size="default"
46
+ />
47
+ );
48
+ // Should select the medium option (16px)
49
+ expect(
50
+ screen.getByRole( 'combobox', { name: 'Font size' } )
51
+ ).toHaveTextContent( 'Medium' );
52
+ } );
53
+
54
+ it( 'should find font size by slug when valueMode is slug', async () => {
55
+ const onChange = jest.fn();
56
+ await render(
57
+ <FontSizePickerSelect
58
+ fontSizes={ fontSizes }
59
+ value="medium"
60
+ valueMode="slug"
61
+ onChange={ onChange }
62
+ onSelectCustom={ jest.fn() }
63
+ disableCustomFontSizes={ false }
64
+ __next40pxDefaultSize={ false }
65
+ size="default"
66
+ />
67
+ );
68
+ // Should select the medium option
69
+ expect(
70
+ screen.getByRole( 'combobox', { name: 'Font size' } )
71
+ ).toHaveTextContent( 'Medium' );
72
+ } );
73
+
74
+ it( 'should handle undefined value', async () => {
75
+ const onChange = jest.fn();
76
+ await render(
77
+ <FontSizePickerSelect
78
+ fontSizes={ fontSizes }
79
+ value={ undefined }
80
+ valueMode="literal"
81
+ onChange={ onChange }
82
+ onSelectCustom={ jest.fn() }
83
+ disableCustomFontSizes={ false }
84
+ __next40pxDefaultSize={ false }
85
+ size="default"
86
+ />
87
+ );
88
+ // Should show default option
89
+ expect(
90
+ screen.getByRole( 'combobox', { name: 'Font size' } )
91
+ ).toHaveTextContent( 'Default' );
92
+ } );
93
+
94
+ it( 'should handle empty string value', async () => {
95
+ const onChange = jest.fn();
96
+ await render(
97
+ <FontSizePickerSelect
98
+ fontSizes={ fontSizes }
99
+ value=""
100
+ valueMode="literal"
101
+ onChange={ onChange }
102
+ onSelectCustom={ jest.fn() }
103
+ disableCustomFontSizes={ false }
104
+ __next40pxDefaultSize={ false }
105
+ size="default"
106
+ />
107
+ );
108
+ // Should show default option
109
+ expect(
110
+ screen.getByRole( 'combobox', { name: 'Font size' } )
111
+ ).toHaveTextContent( 'Default' );
112
+ } );
113
+ } );
114
+
115
+ describe( 'onChange callback', () => {
116
+ it( 'should call onChange with FontSize object as second parameter', async () => {
117
+ const user = userEvent.setup();
118
+ const onChange = jest.fn();
119
+ await render(
120
+ <FontSizePickerSelect
121
+ fontSizes={ fontSizes }
122
+ onChange={ onChange }
123
+ onSelectCustom={ jest.fn() }
124
+ disableCustomFontSizes={ false }
125
+ __next40pxDefaultSize={ false }
126
+ size="default"
127
+ />
128
+ );
129
+ await user.click(
130
+ screen.getByRole( 'combobox', { name: 'Font size' } )
131
+ );
132
+ await user.click(
133
+ screen.getByRole( 'option', { name: 'Small 12px' } )
134
+ );
135
+ expect( onChange ).toHaveBeenCalledWith( '12px', fontSizes[ 0 ] );
136
+ } );
137
+
138
+ it( 'should call onChange with undefined as second parameter for default option', async () => {
139
+ const user = userEvent.setup();
140
+ const onChange = jest.fn();
141
+ await render(
142
+ <FontSizePickerSelect
143
+ fontSizes={ fontSizes }
144
+ value="16px" // Start with a selected value
145
+ onChange={ onChange }
146
+ onSelectCustom={ jest.fn() }
147
+ disableCustomFontSizes={ false }
148
+ __next40pxDefaultSize={ false }
149
+ size="default"
150
+ />
151
+ );
152
+ await user.click(
153
+ screen.getByRole( 'combobox', { name: 'Font size' } )
154
+ );
155
+ await user.click(
156
+ screen.getByRole( 'option', { name: 'Default' } )
157
+ );
158
+ expect( onChange ).toHaveBeenCalledWith( undefined, undefined );
159
+ } );
160
+ } );
161
+
162
+ describe( 'edge cases', () => {
163
+ const fontSizesWithDuplicates: FontSize[] = [
164
+ {
165
+ slug: 'small-1',
166
+ name: 'Small 1',
167
+ size: '12px',
168
+ },
169
+ {
170
+ slug: 'small-2',
171
+ name: 'Small 2',
172
+ size: '12px',
173
+ },
174
+ {
175
+ slug: 'medium',
176
+ name: 'Medium',
177
+ size: '16px',
178
+ },
179
+ ];
180
+
181
+ it( 'should handle multiple font sizes with same value in literal mode', async () => {
182
+ const onChange = jest.fn();
183
+ await render(
184
+ <FontSizePickerSelect
185
+ fontSizes={ fontSizesWithDuplicates }
186
+ value="12px"
187
+ valueMode="literal"
188
+ onChange={ onChange }
189
+ onSelectCustom={ jest.fn() }
190
+ disableCustomFontSizes={ false }
191
+ __next40pxDefaultSize={ false }
192
+ size="default"
193
+ />
194
+ );
195
+ // Should show the first matching font size when there are multiple matches
196
+ expect(
197
+ screen.getByRole( 'combobox', { name: 'Font size' } )
198
+ ).toHaveTextContent( 'Small 1' );
199
+ } );
200
+
201
+ it( 'should handle multiple font sizes with same value in slug mode', async () => {
202
+ const onChange = jest.fn();
203
+ await render(
204
+ <FontSizePickerSelect
205
+ fontSizes={ fontSizesWithDuplicates }
206
+ value="small-1"
207
+ valueMode="slug"
208
+ onChange={ onChange }
209
+ onSelectCustom={ jest.fn() }
210
+ disableCustomFontSizes={ false }
211
+ __next40pxDefaultSize={ false }
212
+ size="default"
213
+ />
214
+ );
215
+ // Should select the specific font size by slug
216
+ expect(
217
+ screen.getByRole( 'combobox', { name: 'Font size' } )
218
+ ).toHaveTextContent( 'Small 1' );
219
+ } );
220
+ } );
221
+ } );
@@ -0,0 +1,275 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { screen } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
6
+ import { render } from '@ariakit/test/react';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import FontSizePickerToggleGroup from '../font-size-picker-toggle-group';
12
+ import type { FontSize } from '../types';
13
+
14
+ describe( 'FontSizePickerToggleGroup', () => {
15
+ const fontSizes: FontSize[] = [
16
+ {
17
+ slug: 'small',
18
+ name: 'Small',
19
+ size: '12px',
20
+ },
21
+ {
22
+ slug: 'medium',
23
+ name: 'Medium',
24
+ size: '16px',
25
+ },
26
+ {
27
+ slug: 'large',
28
+ name: 'Large',
29
+ size: '20px',
30
+ },
31
+ ];
32
+
33
+ describe( 'valueMode prop', () => {
34
+ it( 'should find font size by size value when valueMode is literal', async () => {
35
+ const onChange = jest.fn();
36
+ await render(
37
+ <FontSizePickerToggleGroup
38
+ fontSizes={ fontSizes }
39
+ value="16px"
40
+ valueMode="literal"
41
+ onChange={ onChange }
42
+ __next40pxDefaultSize={ false }
43
+ size="default"
44
+ />
45
+ );
46
+ // Should select the medium option (16px)
47
+ expect(
48
+ screen.getByRole( 'radio', { checked: true } )
49
+ ).toHaveAccessibleName( 'Medium' );
50
+ } );
51
+
52
+ it( 'should find font size by slug when valueMode is slug', async () => {
53
+ const onChange = jest.fn();
54
+ await render(
55
+ <FontSizePickerToggleGroup
56
+ fontSizes={ fontSizes }
57
+ value="medium"
58
+ valueMode="slug"
59
+ onChange={ onChange }
60
+ __next40pxDefaultSize={ false }
61
+ size="default"
62
+ />
63
+ );
64
+ // Should select the medium option
65
+ expect(
66
+ screen.getByRole( 'radio', { checked: true } )
67
+ ).toHaveAccessibleName( 'Medium' );
68
+ } );
69
+
70
+ it( 'should handle undefined value', async () => {
71
+ const onChange = jest.fn();
72
+ await render(
73
+ <FontSizePickerToggleGroup
74
+ fontSizes={ fontSizes }
75
+ value={ undefined }
76
+ valueMode="literal"
77
+ onChange={ onChange }
78
+ __next40pxDefaultSize={ false }
79
+ size="default"
80
+ />
81
+ );
82
+ // Should have no selection
83
+ expect(
84
+ screen.queryByRole( 'radio', { checked: true } )
85
+ ).not.toBeInTheDocument();
86
+ } );
87
+
88
+ it( 'should handle empty string value', async () => {
89
+ const onChange = jest.fn();
90
+ await render(
91
+ <FontSizePickerToggleGroup
92
+ fontSizes={ fontSizes }
93
+ value=""
94
+ valueMode="literal"
95
+ onChange={ onChange }
96
+ __next40pxDefaultSize={ false }
97
+ size="default"
98
+ />
99
+ );
100
+ // Should have no selection
101
+ expect(
102
+ screen.queryByRole( 'radio', { checked: true } )
103
+ ).not.toBeInTheDocument();
104
+ } );
105
+ } );
106
+
107
+ describe( 'onChange callback', () => {
108
+ it( 'should call onChange with FontSize object as second parameter', async () => {
109
+ const user = userEvent.setup();
110
+ const onChange = jest.fn();
111
+ await render(
112
+ <FontSizePickerToggleGroup
113
+ fontSizes={ fontSizes }
114
+ onChange={ onChange }
115
+ __next40pxDefaultSize={ false }
116
+ size="default"
117
+ />
118
+ );
119
+ await user.click( screen.getByRole( 'radio', { name: 'Small' } ) );
120
+ expect( onChange ).toHaveBeenCalledWith( '12px', fontSizes[ 0 ] );
121
+ } );
122
+
123
+ it( 'should call onChange with FontSize object when selecting a different option', async () => {
124
+ const user = userEvent.setup();
125
+ const onChange = jest.fn();
126
+ await render(
127
+ <FontSizePickerToggleGroup
128
+ fontSizes={ fontSizes }
129
+ value="medium"
130
+ onChange={ onChange }
131
+ __next40pxDefaultSize={ false }
132
+ size="default"
133
+ />
134
+ );
135
+ // Click a different option
136
+ await user.click( screen.getByRole( 'radio', { name: 'Small' } ) );
137
+ expect( onChange ).toHaveBeenCalledWith( '12px', fontSizes[ 0 ] );
138
+ } );
139
+ } );
140
+
141
+ describe( 'edge cases', () => {
142
+ const fontSizesWithDuplicates: FontSize[] = [
143
+ {
144
+ slug: 'small-1',
145
+ name: 'Small 1',
146
+ size: '12px',
147
+ },
148
+ {
149
+ slug: 'small-2',
150
+ name: 'Small 2',
151
+ size: '12px',
152
+ },
153
+ {
154
+ slug: 'medium',
155
+ name: 'Medium',
156
+ size: '16px',
157
+ },
158
+ ];
159
+
160
+ it( 'should handle multiple font sizes with same value in literal mode', async () => {
161
+ const onChange = jest.fn();
162
+ await render(
163
+ <FontSizePickerToggleGroup
164
+ fontSizes={ fontSizesWithDuplicates }
165
+ value="12px"
166
+ valueMode="literal"
167
+ onChange={ onChange }
168
+ __next40pxDefaultSize={ false }
169
+ size="default"
170
+ />
171
+ );
172
+ // Should have no selection when there are multiple matches
173
+ expect(
174
+ screen.queryByRole( 'radio', { checked: true } )
175
+ ).not.toBeInTheDocument();
176
+ } );
177
+
178
+ it( 'should handle multiple font sizes with same value in slug mode', async () => {
179
+ const onChange = jest.fn();
180
+ await render(
181
+ <FontSizePickerToggleGroup
182
+ fontSizes={ fontSizesWithDuplicates }
183
+ value="small-1"
184
+ valueMode="slug"
185
+ onChange={ onChange }
186
+ __next40pxDefaultSize={ false }
187
+ size="default"
188
+ />
189
+ );
190
+ // Should select the specific font size by slug
191
+ expect(
192
+ screen.getByRole( 'radio', { checked: true } )
193
+ ).toHaveAccessibleName( 'Small 1' );
194
+ } );
195
+ } );
196
+
197
+ describe( 'heterogeneous font sizes', () => {
198
+ const heterogeneousFontSizes: FontSize[] = [
199
+ {
200
+ slug: 'small',
201
+ name: 'Small',
202
+ size: '12px',
203
+ },
204
+ {
205
+ slug: 'medium',
206
+ name: 'Medium',
207
+ size: '1em',
208
+ },
209
+ {
210
+ slug: 'large',
211
+ name: 'Large',
212
+ size: '2rem',
213
+ },
214
+ {
215
+ slug: 'x-large',
216
+ name: 'Extra Large',
217
+ size: 'clamp(1.75rem, 3vw, 2.25rem)',
218
+ },
219
+ ];
220
+
221
+ it( 'should handle different units in literal mode', async () => {
222
+ const onChange = jest.fn();
223
+ await render(
224
+ <FontSizePickerToggleGroup
225
+ fontSizes={ heterogeneousFontSizes }
226
+ value="1em"
227
+ valueMode="literal"
228
+ onChange={ onChange }
229
+ __next40pxDefaultSize={ false }
230
+ size="default"
231
+ />
232
+ );
233
+ // Should select the medium option (1em)
234
+ expect(
235
+ screen.getByRole( 'radio', { checked: true } )
236
+ ).toHaveAccessibleName( 'Medium' );
237
+ } );
238
+
239
+ it( 'should handle complex font size values in literal mode', async () => {
240
+ const onChange = jest.fn();
241
+ await render(
242
+ <FontSizePickerToggleGroup
243
+ fontSizes={ heterogeneousFontSizes }
244
+ value="clamp(1.75rem, 3vw, 2.25rem)"
245
+ valueMode="literal"
246
+ onChange={ onChange }
247
+ __next40pxDefaultSize={ false }
248
+ size="default"
249
+ />
250
+ );
251
+ // Should select the extra large option
252
+ expect(
253
+ screen.getByRole( 'radio', { checked: true } )
254
+ ).toHaveAccessibleName( 'Extra Large' );
255
+ } );
256
+
257
+ it( 'should handle different units in slug mode', async () => {
258
+ const onChange = jest.fn();
259
+ await render(
260
+ <FontSizePickerToggleGroup
261
+ fontSizes={ heterogeneousFontSizes }
262
+ value="medium"
263
+ valueMode="slug"
264
+ onChange={ onChange }
265
+ __next40pxDefaultSize={ false }
266
+ size="default"
267
+ />
268
+ );
269
+ // Should select the medium option
270
+ expect(
271
+ screen.getByRole( 'radio', { checked: true } )
272
+ ).toHaveAccessibleName( 'Medium' );
273
+ } );
274
+ } );
275
+ } );