@wordpress/components 19.1.5 → 19.1.6

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 (33) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/build/font-size-picker/index.js +10 -9
  3. package/build/font-size-picker/index.js.map +1 -1
  4. package/build/font-size-picker/utils.js +19 -9
  5. package/build/font-size-picker/utils.js.map +1 -1
  6. package/build/palette-edit/index.js +31 -27
  7. package/build/palette-edit/index.js.map +1 -1
  8. package/build/palette-edit/styles.js +10 -10
  9. package/build/palette-edit/styles.js.map +1 -1
  10. package/build/tools-panel/tools-panel-item/hook.js +12 -6
  11. package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
  12. package/build-module/font-size-picker/index.js +10 -9
  13. package/build-module/font-size-picker/index.js.map +1 -1
  14. package/build-module/font-size-picker/utils.js +19 -9
  15. package/build-module/font-size-picker/utils.js.map +1 -1
  16. package/build-module/palette-edit/index.js +30 -27
  17. package/build-module/palette-edit/index.js.map +1 -1
  18. package/build-module/palette-edit/styles.js +10 -10
  19. package/build-module/palette-edit/styles.js.map +1 -1
  20. package/build-module/tools-panel/tools-panel-item/hook.js +12 -6
  21. package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
  22. package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
  23. package/package.json +4 -4
  24. package/src/font-size-picker/index.js +27 -13
  25. package/src/font-size-picker/stories/index.js +62 -0
  26. package/src/font-size-picker/test/index.js +87 -0
  27. package/src/font-size-picker/utils.js +22 -9
  28. package/src/palette-edit/index.js +106 -73
  29. package/src/palette-edit/styles.js +0 -2
  30. package/src/tools-panel/test/index.js +353 -3
  31. package/src/tools-panel/tools-panel/README.md +3 -2
  32. package/src/tools-panel/tools-panel-item/hook.ts +18 -6
  33. package/tsconfig.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/components",
3
- "version": "19.1.5",
3
+ "version": "19.1.6",
4
4
  "description": "UI components for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -36,7 +36,7 @@
36
36
  "@emotion/styled": "^11.3.0",
37
37
  "@emotion/utils": "1.0.0",
38
38
  "@wordpress/a11y": "^3.2.4",
39
- "@wordpress/compose": "^5.0.6",
39
+ "@wordpress/compose": "^5.0.7",
40
40
  "@wordpress/date": "^4.2.3",
41
41
  "@wordpress/deprecated": "^3.2.3",
42
42
  "@wordpress/dom": "^3.2.7",
@@ -47,7 +47,7 @@
47
47
  "@wordpress/is-shallow-equal": "^4.2.1",
48
48
  "@wordpress/keycodes": "^3.2.4",
49
49
  "@wordpress/primitives": "^3.0.4",
50
- "@wordpress/rich-text": "^5.0.6",
50
+ "@wordpress/rich-text": "^5.0.7",
51
51
  "@wordpress/warning": "^2.2.2",
52
52
  "classnames": "^2.3.1",
53
53
  "colord": "^2.7.0",
@@ -74,5 +74,5 @@
74
74
  "publishConfig": {
75
75
  "access": "public"
76
76
  },
77
- "gitHead": "3665e3e1b121046300d8b2fa35074d748f16dbc2"
77
+ "gitHead": "1081a28b2368fcebd9a14554fbd0e25eb33fbcb6"
78
78
  }
@@ -47,23 +47,28 @@ function FontSizePicker(
47
47
  availableUnits: [ 'px', 'em', 'rem' ],
48
48
  } );
49
49
 
50
- // The main font size UI displays a toggle group when the presets are less
51
- // than six and a select control when they are more.
52
- //
53
- // A select control is also used when the value of a preset cannot be
54
- // immediately computed (eg. 'calc', 'var').
55
- const shouldUseSelectControl =
56
- fontSizes.length > 5 ||
57
- fontSizes.some( ( { size } ) => ! isSimpleCssValue( size ) );
58
-
50
+ /**
51
+ * The main font size UI displays a toggle group when the presets are less
52
+ * than six and a select control when they are more.
53
+ */
54
+ const fontSizesContainComplexValues = fontSizes.some(
55
+ ( { size } ) => ! isSimpleCssValue( size )
56
+ );
57
+ const shouldUseSelectControl = fontSizes.length > 5;
59
58
  const options = useMemo(
60
59
  () =>
61
60
  getFontSizeOptions(
62
61
  shouldUseSelectControl,
63
62
  fontSizes,
64
- disableCustomFontSizes
63
+ disableCustomFontSizes,
64
+ fontSizesContainComplexValues
65
65
  ),
66
- [ shouldUseSelectControl, fontSizes, disableCustomFontSizes ]
66
+ [
67
+ shouldUseSelectControl,
68
+ fontSizes,
69
+ disableCustomFontSizes,
70
+ fontSizesContainComplexValues,
71
+ ]
67
72
  );
68
73
  const selectedOption = getSelectedOption( fontSizes, value );
69
74
  const isCustomValue = selectedOption.slug === CUSTOM_FONT_SIZE;
@@ -88,12 +93,21 @@ function FontSizePicker(
88
93
  }
89
94
  // Calculate the `hint` for toggle group control.
90
95
  let hint = selectedOption.name;
91
- if ( typeof selectedOption.size === 'string' ) {
96
+ if (
97
+ ! fontSizesContainComplexValues &&
98
+ typeof selectedOption.size === 'string'
99
+ ) {
92
100
  const [ , unit ] = splitValueAndUnitFromSize( selectedOption.size );
93
101
  hint += `(${ unit })`;
94
102
  }
95
103
  return hint;
96
- }, [ showCustomValueControl, selectedOption?.slug, value, isCustomValue ] );
104
+ }, [
105
+ showCustomValueControl,
106
+ selectedOption?.slug,
107
+ value,
108
+ isCustomValue,
109
+ fontSizesContainComplexValues,
110
+ ] );
97
111
 
98
112
  if ( ! options ) {
99
113
  return null;
@@ -156,3 +156,65 @@ export const differentControlBySize = () => {
156
156
  <FontSizePickerWithState fontSizes={ fontSizes } initialValue={ 8 } />
157
157
  );
158
158
  };
159
+
160
+ export const withComplexCSSValues = () => {
161
+ const options = [
162
+ {
163
+ name: 'Small',
164
+ slug: 'small',
165
+ size: '0.65rem',
166
+ },
167
+ {
168
+ name: 'Medium',
169
+ slug: 'medium',
170
+ size: '1.125rem',
171
+ },
172
+ {
173
+ name: 'Large',
174
+ slug: 'large',
175
+ size: '1.7rem',
176
+ },
177
+ {
178
+ name: 'Extra Large',
179
+ slug: 'extra-large',
180
+ size: '1.95rem',
181
+ },
182
+ {
183
+ name: 'Extra Extra Large',
184
+ slug: 'extra-extra-large',
185
+ size: '2.5rem',
186
+ },
187
+ {
188
+ name: 'Huge',
189
+ slug: 'huge',
190
+ size: '2.8rem',
191
+ },
192
+ ];
193
+ const showMoreFontSizes = boolean( 'Add more font sizes', false );
194
+ const addComplexCssValues = boolean(
195
+ 'Add some complex css values(calc, var, etc..)',
196
+ true
197
+ );
198
+
199
+ const _options = options.map( ( option, index ) => {
200
+ const _option = { ...option };
201
+ // Adding just one complex css value is enough (first element);
202
+ if ( addComplexCssValues && ! index ) {
203
+ _option.size = 'clamp(1.75rem, 3vw, 2.25rem)';
204
+ }
205
+ return _option;
206
+ } );
207
+
208
+ const fontSizes = _options.slice(
209
+ 0,
210
+ showMoreFontSizes ? _options.length : 5
211
+ );
212
+ return (
213
+ <div style={ { maxWidth: '248px' } }>
214
+ <FontSizePickerWithState
215
+ fontSizes={ fontSizes }
216
+ initialValue={ '1.125rem' }
217
+ />
218
+ </div>
219
+ );
220
+ };
@@ -141,4 +141,91 @@ describe( 'FontSizePicker', () => {
141
141
  expect( fontSize ).toBe( '16px' );
142
142
  } );
143
143
  } );
144
+ describe( 'renders different control', () => {
145
+ const options = [
146
+ {
147
+ name: 'Small',
148
+ slug: 'small',
149
+ size: '0.65rem',
150
+ },
151
+ {
152
+ name: 'Medium',
153
+ slug: 'medium',
154
+ size: '1.125rem',
155
+ },
156
+ {
157
+ name: 'Large',
158
+ slug: 'large',
159
+ size: '1.7rem',
160
+ },
161
+ ];
162
+ it( 'should render select control when we have more than five font sizes', () => {
163
+ const extraOptions = [
164
+ {
165
+ name: 'Extra Large',
166
+ slug: 'extra-large',
167
+ size: '1.95rem',
168
+ },
169
+ {
170
+ name: 'Extra Extra Large',
171
+ slug: 'extra-extra-large',
172
+ size: '2.5rem',
173
+ },
174
+ {
175
+ name: 'Huge',
176
+ slug: 'huge',
177
+ size: '2.8rem',
178
+ },
179
+ ];
180
+ const fontSizes = [ ...options, ...extraOptions ];
181
+ render(
182
+ <FontSizePicker
183
+ fontSizes={ fontSizes }
184
+ value={ fontSizes[ 0 ].size }
185
+ />
186
+ );
187
+ // Trigger click to open the select menu and take into account
188
+ // the two extra options (default, custom);
189
+ fireEvent.click(
190
+ screen.getByLabelText( 'Font size', { selector: 'button' } )
191
+ );
192
+ const element = screen.getAllByRole( 'option' );
193
+ expect( element ).toHaveLength( fontSizes.length + 2 );
194
+ } );
195
+ describe( 'segmented control', () => {
196
+ it( 'should use numeric labels for simple css values', () => {
197
+ const fontSizes = [ ...options ];
198
+ render(
199
+ <FontSizePicker
200
+ fontSizes={ fontSizes }
201
+ value={ fontSizes[ 0 ].size }
202
+ />
203
+ );
204
+ const element = screen.getByLabelText( 'Large' );
205
+ expect( element ).toBeInTheDocument();
206
+ expect( element.children ).toHaveLength( 2 );
207
+ expect( element.children[ 0 ].textContent ).toBe( '1.7' );
208
+ } );
209
+ it( 'should use incremental sequence of numbers as labels if we have complex css', () => {
210
+ const fontSizes = [
211
+ ...options,
212
+ {
213
+ name: 'Extra Large',
214
+ slug: 'extra-large',
215
+ size: 'clamp(1.75rem, 3vw, 2.25rem)',
216
+ },
217
+ ];
218
+ render(
219
+ <FontSizePicker
220
+ fontSizes={ fontSizes }
221
+ value={ fontSizes[ 0 ].size }
222
+ />
223
+ );
224
+ const element = screen.getByLabelText( 'Large' );
225
+ expect( element ).toBeInTheDocument();
226
+ expect( element.children ).toHaveLength( 2 );
227
+ expect( element.children[ 0 ].textContent ).toBe( '3' );
228
+ } );
229
+ } );
230
+ } );
144
231
  } );
@@ -14,6 +14,15 @@ const CUSTOM_FONT_SIZE_OPTION = {
14
14
  name: __( 'Custom' ),
15
15
  };
16
16
 
17
+ /**
18
+ * In case we have at most five font sizes, where at least one the them
19
+ * contain a complex css value(clamp, var, etc..) show a incremental sequence
20
+ * of numbers as a label of the font size. We do this because complex css values
21
+ * cannot be caluclated properly and the incremental sequence of numbers as labels
22
+ * can help the user better mentally map the different available font sizes.
23
+ */
24
+ const FONT_SIZES_ALIASES = [ '1', '2', '3', '4', '5' ];
25
+
17
26
  /**
18
27
  * Helper util to split a font size to its numeric value
19
28
  * and its `unit`, if exists.
@@ -46,22 +55,24 @@ export function isSimpleCssValue( value ) {
46
55
  * Return font size options in the proper format depending
47
56
  * on the currently used control (select, toggle group).
48
57
  *
49
- * @param {boolean} useSelectControl Whether to use a select control.
50
- * @param {Object[]} optionsArray Array of available font sizes objects.
51
- * @param {*} disableCustomFontSizes Flag that indicates if custom font sizes are disabled.
58
+ * @param {boolean} useSelectControl Whether to use a select control.
59
+ * @param {Object[]} optionsArray Array of available font sizes objects.
60
+ * @param {*} disableCustomFontSizes Flag that indicates if custom font sizes are disabled.
61
+ * @param {boolean} optionsContainComplexCssValues Whether font sizes contain at least one complex css value(clamp, var, etc..).
52
62
  * @return {Object[]|null} Array of font sizes in proper format for the used control.
53
63
  */
54
64
  export function getFontSizeOptions(
55
65
  useSelectControl,
56
66
  optionsArray,
57
- disableCustomFontSizes
67
+ disableCustomFontSizes,
68
+ optionsContainComplexCssValues
58
69
  ) {
59
70
  if ( disableCustomFontSizes && ! optionsArray.length ) {
60
71
  return null;
61
72
  }
62
73
  return useSelectControl
63
74
  ? getSelectOptions( optionsArray, disableCustomFontSizes )
64
- : getToggleGroupOptions( optionsArray );
75
+ : getToggleGroupOptions( optionsArray, optionsContainComplexCssValues );
65
76
  }
66
77
 
67
78
  function getSelectOptions( optionsArray, disableCustomFontSizes ) {
@@ -79,10 +90,12 @@ function getSelectOptions( optionsArray, disableCustomFontSizes ) {
79
90
  } ) );
80
91
  }
81
92
 
82
- function getToggleGroupOptions( optionsArray ) {
83
- return optionsArray.map( ( { slug, size, name } ) => {
84
- let label = size;
85
- if ( typeof size === 'string' ) {
93
+ function getToggleGroupOptions( optionsArray, optionsContainComplexCssValues ) {
94
+ return optionsArray.map( ( { slug, size, name }, index ) => {
95
+ let label = optionsContainComplexCssValues
96
+ ? FONT_SIZES_ALIASES[ index ]
97
+ : size;
98
+ if ( ! optionsContainComplexCssValues && typeof size === 'string' ) {
86
99
  const [ numericValue ] = splitValueAndUnitFromSize( size );
87
100
  label = numericValue;
88
101
  }
@@ -40,6 +40,8 @@ import { NavigableMenu } from '../navigable-container';
40
40
  import { DEFAULT_GRADIENT } from '../custom-gradient-picker/constants';
41
41
  import CustomGradientPicker from '../custom-gradient-picker';
42
42
 
43
+ const DEFAULT_COLOR = '#000';
44
+
43
45
  function NameInput( { value, onChange, label } ) {
44
46
  return (
45
47
  <NameInputControl
@@ -51,6 +53,14 @@ function NameInput( { value, onChange, label } ) {
51
53
  );
52
54
  }
53
55
 
56
+ function getNameForPosition( position ) {
57
+ return sprintf(
58
+ /* translators: %s: is a temporary id for a custom color */
59
+ __( 'Color %s ' ),
60
+ position + 1
61
+ );
62
+ }
63
+
54
64
  function Option( {
55
65
  canOnlyChangeValues,
56
66
  element,
@@ -143,6 +153,14 @@ function Option( {
143
153
  );
144
154
  }
145
155
 
156
+ function isTemporaryElement( slugPrefix, { slug, color, gradient }, index ) {
157
+ return (
158
+ slug === slugPrefix + kebabCase( getNameForPosition( index ) ) &&
159
+ ( ( !! color && color === DEFAULT_COLOR ) ||
160
+ ( !! gradient && gradient === DEFAULT_GRADIENT ) )
161
+ );
162
+ }
163
+
146
164
  function PaletteEditListView( {
147
165
  elements,
148
166
  onChange,
@@ -159,9 +177,14 @@ function PaletteEditListView( {
159
177
  }, [ elements ] );
160
178
  useEffect( () => {
161
179
  return () => {
162
- if ( elementsReference.current.some( ( { slug } ) => ! slug ) ) {
180
+ if (
181
+ elementsReference.current.some( ( element, index ) =>
182
+ isTemporaryElement( slugPrefix, element, index )
183
+ )
184
+ ) {
163
185
  const newElements = elementsReference.current.filter(
164
- ( { slug } ) => slug
186
+ ( element, index ) =>
187
+ ! isTemporaryElement( slugPrefix, element, index )
165
188
  );
166
189
  onChange( newElements.length ? newElements : undefined );
167
190
  }
@@ -272,19 +295,19 @@ export default function PaletteEdit( {
272
295
  : __( 'Add color' )
273
296
  }
274
297
  onClick={ () => {
275
- const tempOptionName = sprintf(
276
- /* translators: %s: is a temporary id for a custom color */
277
- __( 'Color %s ' ),
278
- elementsLength + 1
298
+ const tempOptionName = getNameForPosition(
299
+ elementsLength
279
300
  );
280
301
  onChange( [
281
302
  ...elements,
282
303
  {
283
304
  ...( isGradient
284
305
  ? { gradient: DEFAULT_GRADIENT }
285
- : { color: '#000' } ),
306
+ : { color: DEFAULT_COLOR } ),
286
307
  name: tempOptionName,
287
- slug: '',
308
+ slug:
309
+ slugPrefix +
310
+ kebabCase( tempOptionName ),
288
311
  },
289
312
  ] );
290
313
  setIsEditing( true );
@@ -293,71 +316,81 @@ export default function PaletteEdit( {
293
316
  />
294
317
  ) }
295
318
 
296
- { hasElements && ( canReset || ! canOnlyChangeValues ) && (
297
- <DropdownMenu
298
- icon={ moreVertical }
299
- label={
300
- isGradient
301
- ? __( 'Gradient options' )
302
- : __( 'Color options' )
303
- }
304
- toggleProps={ {
305
- isSmall: true,
306
- } }
307
- >
308
- { ( { onClose } ) => (
309
- <>
310
- <NavigableMenu role="menu">
311
- <Button
312
- variant="tertiary"
313
- disabled={ isEditing }
314
- onClick={ () => {
315
- setIsEditing( true );
316
- onClose();
317
- } }
318
- className="components-palette-edit__menu-button"
319
- >
320
- { __( 'Edit custom colors' ) }
321
- </Button>
322
- { ! canOnlyChangeValues && (
323
- <Button
324
- variant="tertiary"
325
- onClick={ () => {
326
- setEditingElement( null );
327
- setIsEditing( false );
328
- onChange();
329
- onClose();
330
- } }
331
- className="components-palette-edit__menu-button"
332
- >
333
- { isGradient
334
- ? __(
335
- 'Remove all gradients'
336
- )
337
- : __(
338
- 'Remove all colors'
339
- ) }
340
- </Button>
341
- ) }
342
- { canReset && (
343
- <Button
344
- variant="tertiary"
345
- onClick={ () => {
346
- setEditingElement( null );
347
- onChange();
348
- onClose();
349
- } }
350
- >
351
- { isGradient
352
- ? __( 'Reset gradient' )
353
- : __( 'Reset colors' ) }
354
- </Button>
355
- ) }
356
- </NavigableMenu>
357
- </>
358
- ) }
359
- </DropdownMenu>
360
- ) }
319
+ { hasElements &&
320
+ ( ! isEditing ||
321
+ ! canOnlyChangeValues ||
322
+ canReset ) && (
323
+ <DropdownMenu
324
+ icon={ moreVertical }
325
+ label={
326
+ isGradient
327
+ ? __( 'Gradient options' )
328
+ : __( 'Color options' )
329
+ }
330
+ toggleProps={ {
331
+ isSmall: true,
332
+ } }
333
+ >
334
+ { ( { onClose } ) => (
335
+ <>
336
+ <NavigableMenu role="menu">
337
+ { ! isEditing && (
338
+ <Button
339
+ variant="tertiary"
340
+ onClick={ () => {
341
+ setIsEditing( true );
342
+ onClose();
343
+ } }
344
+ className="components-palette-edit__menu-button"
345
+ >
346
+ { isGradient
347
+ ? __( 'Edit gradients' )
348
+ : __( 'Edit colors' ) }
349
+ </Button>
350
+ ) }
351
+ { ! canOnlyChangeValues && (
352
+ <Button
353
+ variant="tertiary"
354
+ onClick={ () => {
355
+ setEditingElement(
356
+ null
357
+ );
358
+ setIsEditing( false );
359
+ onChange();
360
+ onClose();
361
+ } }
362
+ className="components-palette-edit__menu-button"
363
+ >
364
+ { isGradient
365
+ ? __(
366
+ 'Remove all gradients'
367
+ )
368
+ : __(
369
+ 'Remove all colors'
370
+ ) }
371
+ </Button>
372
+ ) }
373
+ { canReset && (
374
+ <Button
375
+ variant="tertiary"
376
+ onClick={ () => {
377
+ setEditingElement(
378
+ null
379
+ );
380
+ onChange();
381
+ onClose();
382
+ } }
383
+ >
384
+ { isGradient
385
+ ? __( 'Reset gradient' )
386
+ : __( 'Reset colors' ) }
387
+ </Button>
388
+ ) }
389
+ </NavigableMenu>
390
+ </>
391
+ ) }
392
+ </DropdownMenu>
393
+ ) }
361
394
  </PaletteActionsContainer>
362
395
  </PaletteHStackHeader>
363
396
  { hasElements && (
@@ -57,9 +57,7 @@ export const NameContainer = styled.div`
57
57
  export const PaletteHeading = styled( Heading )`
58
58
  text-transform: uppercase;
59
59
  line-height: ${ space( 6 ) };
60
- font-weight: 500;
61
60
  &&& {
62
- font-size: 11px;
63
61
  margin-bottom: 0;
64
62
  }
65
63
  `;