@wordpress/block-editor 14.11.0 → 14.12.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 (57) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/grid/grid-visualizer.js +11 -19
  3. package/build/components/grid/grid-visualizer.js.map +1 -1
  4. package/build/components/grid/utils.js +6 -4
  5. package/build/components/grid/utils.js.map +1 -1
  6. package/build/components/inserter/menu.js +13 -2
  7. package/build/components/inserter/menu.js.map +1 -1
  8. package/build/components/inspector-controls-tabs/position-controls-panel.js +49 -21
  9. package/build/components/inspector-controls-tabs/position-controls-panel.js.map +1 -1
  10. package/build/components/spacing-sizes-control/index.js +44 -2
  11. package/build/components/spacing-sizes-control/index.js.map +1 -1
  12. package/build/components/spacing-sizes-control/linked-button.js +6 -9
  13. package/build/components/spacing-sizes-control/linked-button.js.map +1 -1
  14. package/build/components/spacing-sizes-control/utils.js +0 -108
  15. package/build/components/spacing-sizes-control/utils.js.map +1 -1
  16. package/build/hooks/contrast-checker.js +41 -22
  17. package/build/hooks/contrast-checker.js.map +1 -1
  18. package/build/hooks/custom-class-name.js +2 -1
  19. package/build/hooks/custom-class-name.js.map +1 -1
  20. package/build/store/selectors.js +13 -2
  21. package/build/store/selectors.js.map +1 -1
  22. package/build-module/components/grid/grid-visualizer.js +11 -19
  23. package/build-module/components/grid/grid-visualizer.js.map +1 -1
  24. package/build-module/components/grid/utils.js +6 -4
  25. package/build-module/components/grid/utils.js.map +1 -1
  26. package/build-module/components/inserter/menu.js +13 -2
  27. package/build-module/components/inserter/menu.js.map +1 -1
  28. package/build-module/components/inspector-controls-tabs/position-controls-panel.js +51 -23
  29. package/build-module/components/inspector-controls-tabs/position-controls-panel.js.map +1 -1
  30. package/build-module/components/spacing-sizes-control/index.js +45 -1
  31. package/build-module/components/spacing-sizes-control/index.js.map +1 -1
  32. package/build-module/components/spacing-sizes-control/linked-button.js +7 -10
  33. package/build-module/components/spacing-sizes-control/linked-button.js.map +1 -1
  34. package/build-module/components/spacing-sizes-control/utils.js +0 -104
  35. package/build-module/components/spacing-sizes-control/utils.js.map +1 -1
  36. package/build-module/hooks/contrast-checker.js +42 -23
  37. package/build-module/hooks/contrast-checker.js.map +1 -1
  38. package/build-module/hooks/custom-class-name.js +2 -1
  39. package/build-module/hooks/custom-class-name.js.map +1 -1
  40. package/build-module/store/selectors.js +13 -2
  41. package/build-module/store/selectors.js.map +1 -1
  42. package/build-style/style-rtl.css +1 -0
  43. package/build-style/style.css +1 -0
  44. package/package.json +34 -34
  45. package/src/components/grid/grid-visualizer.js +10 -21
  46. package/src/components/grid/style.scss +1 -0
  47. package/src/components/grid/utils.js +6 -4
  48. package/src/components/inserter/menu.js +11 -9
  49. package/src/components/inspector-controls-tabs/position-controls-panel.js +62 -27
  50. package/src/components/spacing-sizes-control/README.md +93 -0
  51. package/src/components/spacing-sizes-control/index.js +44 -1
  52. package/src/components/spacing-sizes-control/linked-button.js +8 -10
  53. package/src/components/spacing-sizes-control/test/utils.js +0 -151
  54. package/src/components/spacing-sizes-control/utils.js +0 -106
  55. package/src/hooks/contrast-checker.js +64 -30
  56. package/src/hooks/custom-class-name.js +2 -1
  57. package/src/store/selectors.js +15 -7
@@ -184,64 +184,6 @@ export function getSliderValueFromPreset( presetValue, spacingSizes ) {
184
184
  return sliderValue !== -1 ? sliderValue : NaN;
185
185
  }
186
186
 
187
- /**
188
- * Gets an items with the most occurrence within an array
189
- * https://stackoverflow.com/a/20762713
190
- *
191
- * @param {Array<any>} arr Array of items to check.
192
- * @return {any} The item with the most occurrences.
193
- */
194
- function mode( arr ) {
195
- return arr
196
- .sort(
197
- ( a, b ) =>
198
- arr.filter( ( v ) => v === a ).length -
199
- arr.filter( ( v ) => v === b ).length
200
- )
201
- .pop();
202
- }
203
-
204
- /**
205
- * Gets the 'all' input value from values data.
206
- *
207
- * @param {Object} values Box spacing values
208
- *
209
- * @return {string} The most common value from all sides of box.
210
- */
211
- export function getAllRawValue( values = {} ) {
212
- return mode( Object.values( values ) );
213
- }
214
-
215
- /**
216
- * Checks to determine if values are mixed.
217
- *
218
- * @param {Object} values Box values.
219
- * @param {Array} sides Sides that values relate to.
220
- *
221
- * @return {boolean} Whether values are mixed.
222
- */
223
- export function isValuesMixed( values = {}, sides = ALL_SIDES ) {
224
- return (
225
- ( Object.values( values ).length >= 1 &&
226
- Object.values( values ).length < sides.length ) ||
227
- new Set( Object.values( values ) ).size > 1
228
- );
229
- }
230
-
231
- /**
232
- * Checks to determine if values are defined.
233
- *
234
- * @param {Object} values Box values.
235
- *
236
- * @return {boolean} Whether values are defined.
237
- */
238
- export function isValuesDefined( values ) {
239
- if ( values === undefined || values === null ) {
240
- return false;
241
- }
242
- return Object.values( values ).filter( ( value ) => !! value ).length > 0;
243
- }
244
-
245
187
  /**
246
188
  * Determines whether a particular axis has support. If no axis is
247
189
  * specified, this function checks if either axis is supported.
@@ -275,54 +217,6 @@ export function hasAxisSupport( sides, axis ) {
275
217
  return hasHorizontalSupport || hasVerticalSupport;
276
218
  }
277
219
 
278
- /**
279
- * Determines which menu options should be included in the SidePicker.
280
- *
281
- * @param {Array} sides Supported sides.
282
- *
283
- * @return {Object} Menu options with each option containing label & icon.
284
- */
285
- export function getSupportedMenuItems( sides ) {
286
- if ( ! sides || ! sides.length ) {
287
- return {};
288
- }
289
-
290
- const menuItems = {};
291
-
292
- // Determine the primary "side" menu options.
293
- const hasHorizontalSupport = hasAxisSupport( sides, 'horizontal' );
294
- const hasVerticalSupport = hasAxisSupport( sides, 'vertical' );
295
-
296
- if ( hasHorizontalSupport && hasVerticalSupport ) {
297
- menuItems.axial = { label: LABELS.axial, icon: ICONS.axial };
298
- } else if ( hasHorizontalSupport ) {
299
- menuItems.axial = { label: LABELS.horizontal, icon: ICONS.horizontal };
300
- } else if ( hasVerticalSupport ) {
301
- menuItems.axial = { label: LABELS.vertical, icon: ICONS.vertical };
302
- }
303
-
304
- // Track whether we have any individual sides so we can omit the custom
305
- // option if required.
306
- let numberOfIndividualSides = 0;
307
-
308
- ALL_SIDES.forEach( ( side ) => {
309
- if ( sides.includes( side ) ) {
310
- numberOfIndividualSides += 1;
311
- menuItems[ side ] = {
312
- label: LABELS[ side ],
313
- icon: ICONS[ side ],
314
- };
315
- }
316
- } );
317
-
318
- // Add custom item if there are enough sides to warrant a separated view.
319
- if ( numberOfIndividualSides > 1 ) {
320
- menuItems.custom = { label: LABELS.custom, icon: ICONS.custom };
321
- }
322
-
323
- return menuItems;
324
- }
325
-
326
220
  /**
327
221
  * Checks if the supported sides are balanced for each axis.
328
222
  * - Horizontal - both left and right sides are supported.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useState, useEffect } from '@wordpress/element';
4
+ import { useLayoutEffect, useReducer } from '@wordpress/element';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -9,52 +9,86 @@ import { useState, useEffect } from '@wordpress/element';
9
9
  import ContrastChecker from '../components/contrast-checker';
10
10
  import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs';
11
11
 
12
- function getComputedStyle( node ) {
13
- return node.ownerDocument.defaultView.getComputedStyle( node );
12
+ function getComputedValue( node, property ) {
13
+ return node.ownerDocument.defaultView
14
+ .getComputedStyle( node )
15
+ .getPropertyValue( property );
16
+ }
17
+
18
+ function getBlockElementColors( blockEl ) {
19
+ if ( ! blockEl ) {
20
+ return {};
21
+ }
22
+
23
+ const firstLinkElement = blockEl.querySelector( 'a' );
24
+ const linkColor = !! firstLinkElement?.innerText
25
+ ? getComputedValue( firstLinkElement, 'color' )
26
+ : undefined;
27
+
28
+ const textColor = getComputedValue( blockEl, 'color' );
29
+
30
+ let backgroundColorNode = blockEl;
31
+ let backgroundColor = getComputedValue(
32
+ backgroundColorNode,
33
+ 'background-color'
34
+ );
35
+ while (
36
+ backgroundColor === 'rgba(0, 0, 0, 0)' &&
37
+ backgroundColorNode.parentNode &&
38
+ backgroundColorNode.parentNode.nodeType ===
39
+ backgroundColorNode.parentNode.ELEMENT_NODE
40
+ ) {
41
+ backgroundColorNode = backgroundColorNode.parentNode;
42
+ backgroundColor = getComputedValue(
43
+ backgroundColorNode,
44
+ 'background-color'
45
+ );
46
+ }
47
+
48
+ return {
49
+ textColor,
50
+ backgroundColor,
51
+ linkColor,
52
+ };
53
+ }
54
+
55
+ function reducer( prevColors, newColors ) {
56
+ const hasChanged = Object.keys( newColors ).some(
57
+ ( key ) => prevColors[ key ] !== newColors[ key ]
58
+ );
59
+
60
+ // Do not re-render if the colors have not changed.
61
+ return hasChanged ? newColors : prevColors;
14
62
  }
15
63
 
16
64
  export default function BlockColorContrastChecker( { clientId } ) {
17
- const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState();
18
- const [ detectedColor, setDetectedColor ] = useState();
19
- const [ detectedLinkColor, setDetectedLinkColor ] = useState();
20
65
  const blockEl = useBlockElement( clientId );
66
+ const [ colors, setColors ] = useReducer( reducer, {} );
21
67
 
22
68
  // There are so many things that can change the color of a block
23
69
  // So we perform this check on every render.
24
- useEffect( () => {
70
+ useLayoutEffect( () => {
25
71
  if ( ! blockEl ) {
26
72
  return;
27
73
  }
28
- setDetectedColor( getComputedStyle( blockEl ).color );
29
-
30
- const firstLinkElement = blockEl.querySelector( 'a' );
31
- if ( firstLinkElement && !! firstLinkElement.innerText ) {
32
- setDetectedLinkColor( getComputedStyle( firstLinkElement ).color );
33
- }
34
74
 
35
- let backgroundColorNode = blockEl;
36
- let backgroundColor =
37
- getComputedStyle( backgroundColorNode ).backgroundColor;
38
- while (
39
- backgroundColor === 'rgba(0, 0, 0, 0)' &&
40
- backgroundColorNode.parentNode &&
41
- backgroundColorNode.parentNode.nodeType ===
42
- backgroundColorNode.parentNode.ELEMENT_NODE
43
- ) {
44
- backgroundColorNode = backgroundColorNode.parentNode;
45
- backgroundColor =
46
- getComputedStyle( backgroundColorNode ).backgroundColor;
75
+ function updateColors() {
76
+ setColors( getBlockElementColors( blockEl ) );
47
77
  }
48
78
 
49
- setDetectedBackgroundColor( backgroundColor );
50
- }, [ blockEl ] );
79
+ // Combine `useLayoutEffect` and two rAF calls to ensure that values are read
80
+ // after the current paint but before the next paint.
81
+ window.requestAnimationFrame( () =>
82
+ window.requestAnimationFrame( updateColors )
83
+ );
84
+ } );
51
85
 
52
86
  return (
53
87
  <ContrastChecker
54
- backgroundColor={ detectedBackgroundColor }
55
- textColor={ detectedColor }
88
+ backgroundColor={ colors.backgroundColor }
89
+ textColor={ colors.textColor }
90
+ linkColor={ colors.linkColor }
56
91
  enableAlphaChecker
57
- linkColor={ detectedLinkColor }
58
92
  />
59
93
  );
60
94
  }
@@ -123,7 +123,8 @@ export function addTransforms( result, source, index, results ) {
123
123
  // if source N does not exists we do nothing.
124
124
  if ( source[ index ] ) {
125
125
  const originClassName = source[ index ]?.attributes.className;
126
- if ( originClassName ) {
126
+ // Avoid overriding classes if the transformed block already includes them.
127
+ if ( originClassName && result.attributes.className === undefined ) {
127
128
  return {
128
129
  ...result,
129
130
  attributes: {
@@ -1626,15 +1626,23 @@ const isBlockVisibleInTheInserter = (
1626
1626
  Array.isArray( blockType.parent ) ? blockType.parent : []
1627
1627
  ).concat( Array.isArray( blockType.ancestor ) ? blockType.ancestor : [] );
1628
1628
  if ( parents.length > 0 ) {
1629
- const rootBlockName = getBlockName( state, rootClientId );
1630
1629
  // This is an exception to the rule that says that all blocks are visible in the inserter.
1631
1630
  // Blocks that require a given parent or ancestor are only visible if we're within that parent.
1632
- return (
1633
- parents.includes( 'core/post-content' ) ||
1634
- parents.includes( rootBlockName ) ||
1635
- getBlockParentsByBlockName( state, rootClientId, parents ).length >
1636
- 0
1637
- );
1631
+ if ( parents.includes( 'core/post-content' ) ) {
1632
+ return true;
1633
+ }
1634
+
1635
+ let current = rootClientId;
1636
+ let hasParent = false;
1637
+ do {
1638
+ if ( parents.includes( getBlockName( state, current ) ) ) {
1639
+ hasParent = true;
1640
+ break;
1641
+ }
1642
+ current = state.blocks.parents.get( current );
1643
+ } while ( current );
1644
+
1645
+ return hasParent;
1638
1646
  }
1639
1647
 
1640
1648
  return true;