@wordpress/edit-site 4.3.2 → 4.3.3

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.
@@ -24,6 +24,7 @@ import {
24
24
  } from '@wordpress/blocks';
25
25
  import { useEffect, useState, useContext } from '@wordpress/element';
26
26
  import { getCSSRules } from '@wordpress/style-engine';
27
+ import { __unstablePresetDuotoneFilter as PresetDuotoneFilter } from '@wordpress/block-editor';
27
28
 
28
29
  /**
29
30
  * Internal dependencies
@@ -59,16 +60,27 @@ function compileStyleValue( uncompiledValue ) {
59
60
  function getPresetsDeclarations( blockPresets = {} ) {
60
61
  return reduce(
61
62
  PRESET_METADATA,
62
- ( declarations, { path, valueKey, cssVarInfix } ) => {
63
+ ( declarations, { path, valueKey, valueFunc, cssVarInfix } ) => {
63
64
  const presetByOrigin = get( blockPresets, path, [] );
64
65
  [ 'default', 'theme', 'custom' ].forEach( ( origin ) => {
65
66
  if ( presetByOrigin[ origin ] ) {
66
67
  presetByOrigin[ origin ].forEach( ( value ) => {
67
- declarations.push(
68
- `--wp--preset--${ cssVarInfix }--${ kebabCase(
69
- value.slug
70
- ) }: ${ value[ valueKey ] }`
71
- );
68
+ if ( valueKey ) {
69
+ declarations.push(
70
+ `--wp--preset--${ cssVarInfix }--${ kebabCase(
71
+ value.slug
72
+ ) }: ${ value[ valueKey ] }`
73
+ );
74
+ } else if (
75
+ valueFunc &&
76
+ typeof valueFunc === 'function'
77
+ ) {
78
+ declarations.push(
79
+ `--wp--preset--${ cssVarInfix }--${ kebabCase(
80
+ value.slug
81
+ ) }: ${ valueFunc( value ) }`
82
+ );
83
+ }
72
84
  } );
73
85
  }
74
86
  } );
@@ -123,6 +135,25 @@ function getPresetsClasses( blockSelector, blockPresets = {} ) {
123
135
  );
124
136
  }
125
137
 
138
+ function getPresetsSvgFilters( blockPresets = {} ) {
139
+ return PRESET_METADATA.filter(
140
+ // Duotone are the only type of filters for now.
141
+ ( metadata ) => metadata.path.at( -1 ) === 'duotone'
142
+ ).flatMap( ( metadata ) => {
143
+ const presetByOrigin = get( blockPresets, metadata.path, {} );
144
+ return [ 'default', 'theme' ]
145
+ .filter( ( origin ) => presetByOrigin[ origin ] )
146
+ .flatMap( ( origin ) =>
147
+ presetByOrigin[ origin ].map( ( preset ) => (
148
+ <PresetDuotoneFilter
149
+ preset={ preset }
150
+ key={ preset.slug }
151
+ />
152
+ ) )
153
+ );
154
+ } );
155
+ }
156
+
126
157
  function flattenTree( input = {}, prefix, token ) {
127
158
  let result = [];
128
159
  Object.keys( input ).forEach( ( key ) => {
@@ -215,7 +246,9 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
215
246
 
216
247
  const pickStyleKeys = ( treeToPickFrom ) =>
217
248
  pickBy( treeToPickFrom, ( value, key ) =>
218
- [ 'border', 'color', 'spacing', 'typography' ].includes( key )
249
+ [ 'border', 'color', 'spacing', 'typography', 'filter' ].includes(
250
+ key
251
+ )
219
252
  );
220
253
 
221
254
  // Top-level.
@@ -242,6 +275,7 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
242
275
  nodes.push( {
243
276
  styles: blockStyles,
244
277
  selector: blockSelectors[ blockName ].selector,
278
+ duotoneSelector: blockSelectors[ blockName ].duotoneSelector,
245
279
  } );
246
280
  }
247
281
 
@@ -333,9 +367,34 @@ export const toStyles = ( tree, blockSelectors ) => {
333
367
  const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
334
368
  const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );
335
369
 
336
- let ruleset =
337
- '.wp-site-blocks > * { margin-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }';
338
- nodesWithStyles.forEach( ( { selector, styles } ) => {
370
+ /*
371
+ * Reset default browser margin on the root body element.
372
+ * This is set on the root selector **before** generating the ruleset
373
+ * from the `theme.json`. This is to ensure that if the `theme.json` declares
374
+ * `margin` in its `spacing` declaration for the `body` element then these
375
+ * user-generated values take precedence in the CSS cascade.
376
+ * @link https://github.com/WordPress/gutenberg/issues/36147.
377
+ */
378
+ let ruleset = 'body {margin: 0;}';
379
+ nodesWithStyles.forEach( ( { selector, duotoneSelector, styles } ) => {
380
+ const duotoneStyles = {};
381
+ if ( styles?.filter ) {
382
+ duotoneStyles.filter = styles.filter;
383
+ delete styles.filter;
384
+ }
385
+
386
+ // Process duotone styles (they use color.__experimentalDuotone selector).
387
+ if ( duotoneSelector ) {
388
+ const duotoneDeclarations = getStylesDeclarations( duotoneStyles );
389
+ if ( duotoneDeclarations.length === 0 ) {
390
+ return;
391
+ }
392
+ ruleset =
393
+ ruleset +
394
+ `${ duotoneSelector }{${ duotoneDeclarations.join( ';' ) };}`;
395
+ }
396
+
397
+ // Process the remaning block styles (they use either normal block class or __experimentalSelector).
339
398
  const declarations = getStylesDeclarations( styles );
340
399
  if ( declarations.length === 0 ) {
341
400
  return;
@@ -358,6 +417,13 @@ export const toStyles = ( tree, blockSelectors ) => {
358
417
  return ruleset;
359
418
  };
360
419
 
420
+ export function toSvgFilters( tree, blockSelectors ) {
421
+ const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );
422
+ return nodesWithSettings.flatMap( ( { presets } ) => {
423
+ return getPresetsSvgFilters( presets );
424
+ } );
425
+ }
426
+
361
427
  const getBlockSelectors = ( blockTypes ) => {
362
428
  const result = {};
363
429
  blockTypes.forEach( ( blockType ) => {
@@ -365,9 +431,12 @@ const getBlockSelectors = ( blockTypes ) => {
365
431
  const selector =
366
432
  blockType?.supports?.__experimentalSelector ??
367
433
  '.wp-block-' + name.replace( 'core/', '' ).replace( '/', '-' );
434
+ const duotoneSelector =
435
+ blockType?.supports?.color?.__experimentalDuotone ?? null;
368
436
  result[ name ] = {
369
437
  name,
370
438
  selector,
439
+ duotoneSelector,
371
440
  };
372
441
  } );
373
442
 
@@ -377,6 +446,7 @@ const getBlockSelectors = ( blockTypes ) => {
377
446
  export function useGlobalStylesOutput() {
378
447
  const [ stylesheets, setStylesheets ] = useState( [] );
379
448
  const [ settings, setSettings ] = useState( {} );
449
+ const [ svgFilters, setSvgFilters ] = useState( {} );
380
450
  const { merged: mergedConfig } = useContext( GlobalStylesContext );
381
451
 
382
452
  useEffect( () => {
@@ -390,6 +460,7 @@ export function useGlobalStylesOutput() {
390
460
  blockSelectors
391
461
  );
392
462
  const globalStyles = toStyles( mergedConfig, blockSelectors );
463
+ const filters = toSvgFilters( mergedConfig, blockSelectors );
393
464
  setStylesheets( [
394
465
  {
395
466
  css: customProperties,
@@ -401,7 +472,8 @@ export function useGlobalStylesOutput() {
401
472
  },
402
473
  ] );
403
474
  setSettings( mergedConfig.settings );
475
+ setSvgFilters( filters );
404
476
  }, [ mergedConfig ] );
405
477
 
406
- return [ stylesheets, settings ];
478
+ return [ stylesheets, settings, svgFilters ];
407
479
  }
@@ -49,6 +49,12 @@ export const PRESET_METADATA = [
49
49
  },
50
50
  ],
51
51
  },
52
+ {
53
+ path: [ 'color', 'duotone' ],
54
+ cssVarInfix: 'duotone',
55
+ valueFunc: ( { slug } ) => `url( '#wp-duotone-${ slug }' )`,
56
+ classes: [],
57
+ },
52
58
  {
53
59
  path: [ 'typography', 'fontSizes' ],
54
60
  valueKey: 'size',