@wordpress/edit-site 5.1.0 → 5.2.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 (180) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/LICENSE.md +1 -1
  3. package/build/components/add-new-template/new-template-part.js +21 -1
  4. package/build/components/add-new-template/new-template-part.js.map +1 -1
  5. package/build/components/add-new-template/utils.js +9 -1
  6. package/build/components/add-new-template/utils.js.map +1 -1
  7. package/build/components/block-editor/editor-canvas.js +0 -1
  8. package/build/components/block-editor/editor-canvas.js.map +1 -1
  9. package/build/components/block-editor/index.js +15 -51
  10. package/build/components/block-editor/index.js.map +1 -1
  11. package/build/components/block-editor/resize-handle.js +2 -1
  12. package/build/components/block-editor/resize-handle.js.map +1 -1
  13. package/build/components/editor/index.js +1 -1
  14. package/build/components/editor/index.js.map +1 -1
  15. package/build/components/global-styles/block-preview-panel.js +8 -2
  16. package/build/components/global-styles/block-preview-panel.js.map +1 -1
  17. package/build/components/global-styles/border-panel.js +5 -4
  18. package/build/components/global-styles/border-panel.js.map +1 -1
  19. package/build/components/global-styles/context-menu.js +9 -1
  20. package/build/components/global-styles/context-menu.js.map +1 -1
  21. package/build/components/global-styles/dimensions-panel.js +16 -11
  22. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  23. package/build/components/global-styles/screen-background-color.js +6 -5
  24. package/build/components/global-styles/screen-background-color.js.map +1 -1
  25. package/build/components/global-styles/screen-block-list.js +4 -1
  26. package/build/components/global-styles/screen-block-list.js.map +1 -1
  27. package/build/components/global-styles/screen-border.js +9 -3
  28. package/build/components/global-styles/screen-border.js.map +1 -1
  29. package/build/components/global-styles/screen-button-color.js +3 -2
  30. package/build/components/global-styles/screen-button-color.js.map +1 -1
  31. package/build/components/global-styles/screen-colors.js +50 -26
  32. package/build/components/global-styles/screen-colors.js.map +1 -1
  33. package/build/components/global-styles/screen-heading-color.js +8 -7
  34. package/build/components/global-styles/screen-heading-color.js.map +1 -1
  35. package/build/components/global-styles/screen-layout.js +9 -3
  36. package/build/components/global-styles/screen-layout.js.map +1 -1
  37. package/build/components/global-styles/screen-link-color.js +8 -7
  38. package/build/components/global-styles/screen-link-color.js.map +1 -1
  39. package/build/components/global-styles/screen-text-color.js +4 -3
  40. package/build/components/global-styles/screen-text-color.js.map +1 -1
  41. package/build/components/global-styles/screen-typography.js +8 -2
  42. package/build/components/global-styles/screen-typography.js.map +1 -1
  43. package/build/components/global-styles/screen-variations.js +71 -0
  44. package/build/components/global-styles/screen-variations.js.map +1 -0
  45. package/build/components/global-styles/typography-panel.js +9 -8
  46. package/build/components/global-styles/typography-panel.js.map +1 -1
  47. package/build/components/global-styles/ui.js +85 -18
  48. package/build/components/global-styles/ui.js.map +1 -1
  49. package/build/components/global-styles/use-global-styles-output.js +119 -33
  50. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  51. package/build/components/global-styles/utils.js +49 -2
  52. package/build/components/global-styles/utils.js.map +1 -1
  53. package/build/components/global-styles/variations-panel.js +85 -0
  54. package/build/components/global-styles/variations-panel.js.map +1 -0
  55. package/build/components/layout/index.js +81 -8
  56. package/build/components/layout/index.js.map +1 -1
  57. package/build/components/sidebar-edit-mode/navigation-menu-sidebar/navigation-inspector.js +2 -0
  58. package/build/components/sidebar-edit-mode/navigation-menu-sidebar/navigation-inspector.js.map +1 -1
  59. package/build/components/site-hub/index.js +9 -9
  60. package/build/components/site-hub/index.js.map +1 -1
  61. package/build/components/sync-state-with-url/use-sync-canvas-mode-with-url.js +54 -0
  62. package/build/components/sync-state-with-url/use-sync-canvas-mode-with-url.js.map +1 -0
  63. package/build/components/template-details/edit-template-title.js +1 -0
  64. package/build/components/template-details/edit-template-title.js.map +1 -1
  65. package/build/components/template-details/template-part-area-selector.js +1 -0
  66. package/build/components/template-details/template-part-area-selector.js.map +1 -1
  67. package/build/hooks/push-changes-to-global-styles/index.js +3 -3
  68. package/build/hooks/push-changes-to-global-styles/index.js.map +1 -1
  69. package/build/store/reducer.js +1 -1
  70. package/build/store/reducer.js.map +1 -1
  71. package/build-module/components/add-new-template/new-template-part.js +20 -1
  72. package/build-module/components/add-new-template/new-template-part.js.map +1 -1
  73. package/build-module/components/add-new-template/utils.js +5 -0
  74. package/build-module/components/add-new-template/utils.js.map +1 -1
  75. package/build-module/components/block-editor/editor-canvas.js +0 -1
  76. package/build-module/components/block-editor/editor-canvas.js.map +1 -1
  77. package/build-module/components/block-editor/index.js +17 -49
  78. package/build-module/components/block-editor/index.js.map +1 -1
  79. package/build-module/components/block-editor/resize-handle.js +2 -1
  80. package/build-module/components/block-editor/resize-handle.js.map +1 -1
  81. package/build-module/components/editor/index.js +1 -1
  82. package/build-module/components/editor/index.js.map +1 -1
  83. package/build-module/components/global-styles/block-preview-panel.js +8 -2
  84. package/build-module/components/global-styles/block-preview-panel.js.map +1 -1
  85. package/build-module/components/global-styles/border-panel.js +5 -4
  86. package/build-module/components/global-styles/border-panel.js.map +1 -1
  87. package/build-module/components/global-styles/context-menu.js +7 -1
  88. package/build-module/components/global-styles/context-menu.js.map +1 -1
  89. package/build-module/components/global-styles/dimensions-panel.js +16 -11
  90. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  91. package/build-module/components/global-styles/screen-background-color.js +6 -5
  92. package/build-module/components/global-styles/screen-background-color.js.map +1 -1
  93. package/build-module/components/global-styles/screen-block-list.js +3 -1
  94. package/build-module/components/global-styles/screen-block-list.js.map +1 -1
  95. package/build-module/components/global-styles/screen-border.js +8 -3
  96. package/build-module/components/global-styles/screen-border.js.map +1 -1
  97. package/build-module/components/global-styles/screen-button-color.js +3 -2
  98. package/build-module/components/global-styles/screen-button-color.js.map +1 -1
  99. package/build-module/components/global-styles/screen-colors.js +49 -26
  100. package/build-module/components/global-styles/screen-colors.js.map +1 -1
  101. package/build-module/components/global-styles/screen-heading-color.js +8 -7
  102. package/build-module/components/global-styles/screen-heading-color.js.map +1 -1
  103. package/build-module/components/global-styles/screen-layout.js +8 -3
  104. package/build-module/components/global-styles/screen-layout.js.map +1 -1
  105. package/build-module/components/global-styles/screen-link-color.js +8 -7
  106. package/build-module/components/global-styles/screen-link-color.js.map +1 -1
  107. package/build-module/components/global-styles/screen-text-color.js +4 -3
  108. package/build-module/components/global-styles/screen-text-color.js.map +1 -1
  109. package/build-module/components/global-styles/screen-typography.js +7 -2
  110. package/build-module/components/global-styles/screen-typography.js.map +1 -1
  111. package/build-module/components/global-styles/screen-variations.js +54 -0
  112. package/build-module/components/global-styles/screen-variations.js.map +1 -0
  113. package/build-module/components/global-styles/typography-panel.js +9 -8
  114. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  115. package/build-module/components/global-styles/ui.js +84 -19
  116. package/build-module/components/global-styles/ui.js.map +1 -1
  117. package/build-module/components/global-styles/use-global-styles-output.js +121 -35
  118. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  119. package/build-module/components/global-styles/utils.js +47 -2
  120. package/build-module/components/global-styles/utils.js.map +1 -1
  121. package/build-module/components/global-styles/variations-panel.js +68 -0
  122. package/build-module/components/global-styles/variations-panel.js.map +1 -0
  123. package/build-module/components/layout/index.js +81 -10
  124. package/build-module/components/layout/index.js.map +1 -1
  125. package/build-module/components/sidebar-edit-mode/navigation-menu-sidebar/navigation-inspector.js +2 -0
  126. package/build-module/components/sidebar-edit-mode/navigation-menu-sidebar/navigation-inspector.js.map +1 -1
  127. package/build-module/components/site-hub/index.js +10 -9
  128. package/build-module/components/site-hub/index.js.map +1 -1
  129. package/build-module/components/sync-state-with-url/use-sync-canvas-mode-with-url.js +43 -0
  130. package/build-module/components/sync-state-with-url/use-sync-canvas-mode-with-url.js.map +1 -0
  131. package/build-module/components/template-details/edit-template-title.js +1 -0
  132. package/build-module/components/template-details/edit-template-title.js.map +1 -1
  133. package/build-module/components/template-details/template-part-area-selector.js +1 -0
  134. package/build-module/components/template-details/template-part-area-selector.js.map +1 -1
  135. package/build-module/hooks/push-changes-to-global-styles/index.js +3 -3
  136. package/build-module/hooks/push-changes-to-global-styles/index.js.map +1 -1
  137. package/build-module/store/reducer.js +1 -1
  138. package/build-module/store/reducer.js.map +1 -1
  139. package/build-style/style-rtl.css +93 -21
  140. package/build-style/style.css +93 -21
  141. package/package.json +30 -30
  142. package/src/components/add-new-template/new-template-part.js +23 -1
  143. package/src/components/add-new-template/utils.js +14 -0
  144. package/src/components/block-editor/editor-canvas.js +0 -1
  145. package/src/components/block-editor/index.js +11 -54
  146. package/src/components/block-editor/resize-handle.js +6 -2
  147. package/src/components/block-editor/style.scss +43 -7
  148. package/src/components/editor/index.js +1 -1
  149. package/src/components/global-styles/block-preview-panel.js +14 -2
  150. package/src/components/global-styles/border-panel.js +8 -4
  151. package/src/components/global-styles/context-menu.js +6 -0
  152. package/src/components/global-styles/dimensions-panel.js +32 -15
  153. package/src/components/global-styles/screen-background-color.js +12 -5
  154. package/src/components/global-styles/screen-block-list.js +6 -1
  155. package/src/components/global-styles/screen-border.js +7 -4
  156. package/src/components/global-styles/screen-button-color.js +2 -2
  157. package/src/components/global-styles/screen-colors.js +82 -21
  158. package/src/components/global-styles/screen-heading-color.js +7 -7
  159. package/src/components/global-styles/screen-layout.js +10 -4
  160. package/src/components/global-styles/screen-link-color.js +19 -7
  161. package/src/components/global-styles/screen-text-color.js +7 -3
  162. package/src/components/global-styles/screen-typography.js +11 -4
  163. package/src/components/global-styles/screen-variations.js +47 -0
  164. package/src/components/global-styles/style.scss +9 -0
  165. package/src/components/global-styles/test/use-global-styles-output.js +1 -1
  166. package/src/components/global-styles/typography-panel.js +31 -8
  167. package/src/components/global-styles/ui.js +101 -13
  168. package/src/components/global-styles/use-global-styles-output.js +137 -14
  169. package/src/components/global-styles/utils.js +46 -2
  170. package/src/components/global-styles/variations-panel.js +78 -0
  171. package/src/components/layout/index.js +107 -19
  172. package/src/components/layout/style.scss +30 -5
  173. package/src/components/sidebar-edit-mode/navigation-menu-sidebar/navigation-inspector.js +2 -0
  174. package/src/components/sidebar-edit-mode/navigation-menu-sidebar/style.scss +4 -0
  175. package/src/components/site-hub/index.js +120 -109
  176. package/src/components/sync-state-with-url/use-sync-canvas-mode-with-url.js +40 -0
  177. package/src/components/template-details/edit-template-title.js +1 -0
  178. package/src/components/template-details/template-part-area-selector.js +1 -0
  179. package/src/hooks/push-changes-to-global-styles/index.js +3 -3
  180. package/src/store/reducer.js +1 -1
@@ -6,7 +6,9 @@ import {
6
6
  __experimentalNavigatorScreen as NavigatorScreen,
7
7
  __experimentalUseNavigator as useNavigator,
8
8
  } from '@wordpress/components';
9
- import { getBlockTypes } from '@wordpress/blocks';
9
+ import { getBlockTypes, store as blocksStore } from '@wordpress/blocks';
10
+
11
+ import { useSelect } from '@wordpress/data';
10
12
 
11
13
  /**
12
14
  * Internal dependencies
@@ -25,6 +27,7 @@ import ScreenHeadingColor from './screen-heading-color';
25
27
  import ScreenButtonColor from './screen-button-color';
26
28
  import ScreenLayout from './screen-layout';
27
29
  import ScreenStyleVariations from './screen-style-variations';
30
+ import { ScreenVariation } from './screen-variations';
28
31
  import ScreenBorder from './screen-border';
29
32
  import StyleBook from '../style-book';
30
33
  import ScreenCSS from './screen-css';
@@ -43,14 +46,67 @@ function GlobalStylesNavigationScreen( { className, ...props } ) {
43
46
  );
44
47
  }
45
48
 
46
- function ContextScreens( { name } ) {
47
- const parentMenu =
48
- name === undefined ? '' : '/blocks/' + encodeURIComponent( name );
49
+ function BlockStyleVariationsScreens( { name } ) {
50
+ const blockStyleVariations = useSelect(
51
+ ( select ) => {
52
+ const { getBlockStyles } = select( blocksStore );
53
+ return getBlockStyles( name );
54
+ },
55
+ [ name ]
56
+ );
57
+ if ( ! blockStyleVariations?.length ) {
58
+ return null;
59
+ }
60
+
61
+ return blockStyleVariations.map( ( variation ) => (
62
+ <ContextScreens
63
+ key={ variation.name + name }
64
+ name={ name }
65
+ parentMenu={
66
+ '/blocks/' +
67
+ encodeURIComponent( name ) +
68
+ '/variations/' +
69
+ encodeURIComponent( variation.name )
70
+ }
71
+ />
72
+ ) );
73
+ }
74
+
75
+ function ContextScreens( { name, parentMenu = '' } ) {
76
+ const hasVariationPath = parentMenu.search( 'variations' );
77
+ const variationPath =
78
+ hasVariationPath !== -1
79
+ ? parentMenu
80
+ .substring( hasVariationPath )
81
+ .replace( '/', '.' )
82
+ .concat( '', '.' )
83
+ : '';
84
+ const blockStyleVariations = useSelect(
85
+ ( select ) => {
86
+ const { getBlockStyles } = select( blocksStore );
87
+ return getBlockStyles( name );
88
+ },
89
+ [ name ]
90
+ );
91
+
92
+ const BlockStylesNavigationScreens = ( { blockStyles, blockName } ) => {
93
+ return blockStyles.map( ( style, index ) => (
94
+ <GlobalStylesNavigationScreen
95
+ key={ index }
96
+ path={ parentMenu + '/variations/' + style.name }
97
+ >
98
+ <ScreenVariation blockName={ blockName } style={ style } />
99
+ </GlobalStylesNavigationScreen>
100
+ ) );
101
+ };
49
102
 
50
103
  return (
51
104
  <>
52
105
  <GlobalStylesNavigationScreen path={ parentMenu + '/typography' }>
53
- <ScreenTypography name={ name } />
106
+ <ScreenTypography
107
+ name={ name }
108
+ variationPath={ variationPath }
109
+ />
54
110
  </GlobalStylesNavigationScreen>
55
111
 
56
112
  <GlobalStylesNavigationScreen
@@ -78,7 +134,7 @@ function ContextScreens( { name } ) {
78
134
  </GlobalStylesNavigationScreen>
79
135
 
80
136
  <GlobalStylesNavigationScreen path={ parentMenu + '/colors' }>
81
- <ScreenColors name={ name } />
137
+ <ScreenColors name={ name } variationPath={ variationPath } />
82
138
  </GlobalStylesNavigationScreen>
83
139
 
84
140
  <GlobalStylesNavigationScreen
@@ -90,36 +146,58 @@ function ContextScreens( { name } ) {
90
146
  <GlobalStylesNavigationScreen
91
147
  path={ parentMenu + '/colors/background' }
92
148
  >
93
- <ScreenBackgroundColor name={ name } />
149
+ <ScreenBackgroundColor
150
+ name={ name }
151
+ variationPath={ variationPath }
152
+ />
94
153
  </GlobalStylesNavigationScreen>
95
154
 
96
155
  <GlobalStylesNavigationScreen path={ parentMenu + '/colors/text' }>
97
- <ScreenTextColor name={ name } />
156
+ <ScreenTextColor
157
+ name={ name }
158
+ variationPath={ variationPath }
159
+ />
98
160
  </GlobalStylesNavigationScreen>
99
161
 
100
162
  <GlobalStylesNavigationScreen path={ parentMenu + '/colors/link' }>
101
- <ScreenLinkColor name={ name } />
163
+ <ScreenLinkColor
164
+ name={ name }
165
+ variationPath={ variationPath }
166
+ />
102
167
  </GlobalStylesNavigationScreen>
103
168
 
104
169
  <GlobalStylesNavigationScreen
105
170
  path={ parentMenu + '/colors/heading' }
106
171
  >
107
- <ScreenHeadingColor name={ name } />
172
+ <ScreenHeadingColor
173
+ name={ name }
174
+ variationPath={ variationPath }
175
+ />
108
176
  </GlobalStylesNavigationScreen>
109
177
 
110
178
  <GlobalStylesNavigationScreen
111
179
  path={ parentMenu + '/colors/button' }
112
180
  >
113
- <ScreenButtonColor name={ name } />
181
+ <ScreenButtonColor
182
+ name={ name }
183
+ variationPath={ variationPath }
184
+ />
114
185
  </GlobalStylesNavigationScreen>
115
186
 
116
187
  <GlobalStylesNavigationScreen path={ parentMenu + '/border' }>
117
- <ScreenBorder name={ name } />
188
+ <ScreenBorder name={ name } variationPath={ variationPath } />
118
189
  </GlobalStylesNavigationScreen>
119
190
 
120
191
  <GlobalStylesNavigationScreen path={ parentMenu + '/layout' }>
121
- <ScreenLayout name={ name } />
192
+ <ScreenLayout name={ name } variationPath={ variationPath } />
122
193
  </GlobalStylesNavigationScreen>
194
+
195
+ { !! blockStyleVariations?.length && (
196
+ <BlockStylesNavigationScreens
197
+ blockStyles={ blockStyleVariations }
198
+ blockName={ name }
199
+ />
200
+ ) }
123
201
  </>
124
202
  );
125
203
  }
@@ -154,6 +232,7 @@ function GlobalStylesStyleBook( { onClose } ) {
154
232
 
155
233
  function GlobalStylesUI( { isStyleBookOpened, onCloseStyleBook } ) {
156
234
  const blocks = getBlockTypes();
235
+
157
236
  return (
158
237
  <NavigatorProvider
159
238
  className="edit-site-global-styles-sidebar__navigator-provider"
@@ -186,9 +265,18 @@ function GlobalStylesUI( { isStyleBookOpened, onCloseStyleBook } ) {
186
265
  <ContextScreens
187
266
  key={ 'screens-block-' + block.name }
188
267
  name={ block.name }
268
+ parentMenu={ '/blocks/' + encodeURIComponent( block.name ) }
189
269
  />
190
270
  ) ) }
191
271
 
272
+ { blocks.map( ( block, index ) => {
273
+ return (
274
+ <BlockStyleVariationsScreens
275
+ key={ 'screens-block-styles-' + block.name + index }
276
+ name={ block.name }
277
+ />
278
+ );
279
+ } ) }
192
280
  { isStyleBookOpened && (
193
281
  <GlobalStylesStyleBook onClose={ onCloseStyleBook } />
194
282
  ) }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { get, isEmpty, kebabCase, pickBy, set } from 'lodash';
4
+ import { get, isEmpty, kebabCase, set } from 'lodash';
5
5
 
6
6
  /**
7
7
  * WordPress dependencies
@@ -10,6 +10,7 @@ import {
10
10
  __EXPERIMENTAL_STYLE_PROPERTY as STYLE_PROPERTY,
11
11
  __EXPERIMENTAL_ELEMENTS as ELEMENTS,
12
12
  getBlockTypes,
13
+ store as blocksStore,
13
14
  } from '@wordpress/blocks';
14
15
  import { useSelect } from '@wordpress/data';
15
16
  import { useContext, useMemo } from '@wordpress/element';
@@ -171,6 +172,29 @@ function flattenTree( input = {}, prefix, token ) {
171
172
  return result;
172
173
  }
173
174
 
175
+ /**
176
+ * Gets variation selector string from feature selector.
177
+ *
178
+ * @param {string} featureSelector The feature selector.
179
+ *
180
+ * @param {string} styleVariationSelector The style variation selector.
181
+ * @return {string} Combined selector string.
182
+ *
183
+ */
184
+ function concatFeatureVariationSelectorString(
185
+ featureSelector,
186
+ styleVariationSelector
187
+ ) {
188
+ const featureSelectors = featureSelector.split( ',' );
189
+ const combinedSelectors = [];
190
+ featureSelectors.forEach( ( selector ) => {
191
+ combinedSelectors.push(
192
+ `${ styleVariationSelector.trim() }${ selector.trim() }`
193
+ );
194
+ } );
195
+ return combinedSelectors.join( ', ' );
196
+ }
197
+
174
198
  /**
175
199
  * Transform given style tree into a set of style declarations.
176
200
  *
@@ -449,17 +473,19 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
449
473
  }
450
474
 
451
475
  const pickStyleKeys = ( treeToPickFrom ) =>
452
- pickBy( treeToPickFrom, ( value, key ) =>
453
- [
454
- 'border',
455
- 'color',
456
- 'dimensions',
457
- 'spacing',
458
- 'typography',
459
- 'filter',
460
- 'outline',
461
- 'shadow',
462
- ].includes( key )
476
+ Object.fromEntries(
477
+ Object.entries( treeToPickFrom ?? {} ).filter( ( [ key ] ) =>
478
+ [
479
+ 'border',
480
+ 'color',
481
+ 'dimensions',
482
+ 'spacing',
483
+ 'typography',
484
+ 'filter',
485
+ 'outline',
486
+ 'shadow',
487
+ ].includes( key )
488
+ )
463
489
  );
464
490
 
465
491
  // Top-level.
@@ -484,6 +510,16 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
484
510
  Object.entries( tree.styles?.blocks ?? {} ).forEach(
485
511
  ( [ blockName, node ] ) => {
486
512
  const blockStyles = pickStyleKeys( node );
513
+
514
+ if ( node?.variations ) {
515
+ const variations = {};
516
+ Object.keys( node.variations ).forEach( ( variation ) => {
517
+ variations[ variation ] = pickStyleKeys(
518
+ node.variations[ variation ]
519
+ );
520
+ } );
521
+ blockStyles.variations = variations;
522
+ }
487
523
  if (
488
524
  !! blockStyles &&
489
525
  !! blockSelectors?.[ blockName ]?.selector
@@ -499,6 +535,8 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
499
535
  styles: blockStyles,
500
536
  featureSelectors:
501
537
  blockSelectors[ blockName ].featureSelectors,
538
+ styleVariationSelectors:
539
+ blockSelectors[ blockName ].styleVariationSelectors,
502
540
  } );
503
541
  }
504
542
 
@@ -647,6 +685,7 @@ export const toStyles = (
647
685
  fallbackGapValue,
648
686
  hasLayoutSupport,
649
687
  featureSelectors,
688
+ styleVariationSelectors,
650
689
  } ) => {
651
690
  // Process styles for block support features with custom feature level
652
691
  // CSS selectors set.
@@ -673,6 +712,69 @@ export const toStyles = (
673
712
  );
674
713
  }
675
714
 
715
+ if ( styleVariationSelectors ) {
716
+ Object.entries( styleVariationSelectors ).forEach(
717
+ ( [ styleVariationName, styleVariationSelector ] ) => {
718
+ if ( styles?.variations?.[ styleVariationName ] ) {
719
+ // If the block uses any custom selectors for block support, add those first.
720
+ if ( featureSelectors ) {
721
+ Object.entries( featureSelectors ).forEach(
722
+ ( [ featureName, featureSelector ] ) => {
723
+ if (
724
+ styles?.variations?.[
725
+ styleVariationName
726
+ ]?.[ featureName ]
727
+ ) {
728
+ const featureStyles = {
729
+ [ featureName ]:
730
+ styles.variations[
731
+ styleVariationName
732
+ ][ featureName ],
733
+ };
734
+ const featureDeclarations =
735
+ getStylesDeclarations(
736
+ featureStyles
737
+ );
738
+ delete styles.variations[
739
+ styleVariationName
740
+ ][ featureName ];
741
+
742
+ if (
743
+ !! featureDeclarations.length
744
+ ) {
745
+ ruleset =
746
+ ruleset +
747
+ `${ concatFeatureVariationSelectorString(
748
+ featureSelector,
749
+ styleVariationSelector
750
+ ) }{${ featureDeclarations.join(
751
+ ';'
752
+ ) } }`;
753
+ }
754
+ }
755
+ }
756
+ );
757
+ }
758
+ // Otherwise add regular selectors.
759
+ const styleVariationDeclarations =
760
+ getStylesDeclarations(
761
+ styles?.variations?.[ styleVariationName ],
762
+ styleVariationSelector,
763
+ useRootPaddingAlign,
764
+ tree
765
+ );
766
+ if ( !! styleVariationDeclarations.length ) {
767
+ ruleset =
768
+ ruleset +
769
+ `${ styleVariationSelector }{${ styleVariationDeclarations.join(
770
+ ';'
771
+ ) }}`;
772
+ }
773
+ }
774
+ }
775
+ );
776
+ }
777
+
676
778
  const duotoneStyles = {};
677
779
  if ( styles?.filter ) {
678
780
  duotoneStyles.filter = styles.filter;
@@ -802,7 +904,7 @@ export function toSvgFilters( tree, blockSelectors ) {
802
904
  } );
803
905
  }
804
906
 
805
- export const getBlockSelectors = ( blockTypes ) => {
907
+ export const getBlockSelectors = ( blockTypes, getBlockStyles ) => {
806
908
  const result = {};
807
909
  blockTypes.forEach( ( blockType ) => {
808
910
  const name = blockType.name;
@@ -815,6 +917,15 @@ export const getBlockSelectors = ( blockTypes ) => {
815
917
  const fallbackGapValue =
816
918
  blockType?.supports?.spacing?.blockGap?.__experimentalDefault;
817
919
 
920
+ const blockStyleVariations = getBlockStyles( name );
921
+ const styleVariationSelectors = {};
922
+ if ( blockStyleVariations?.length ) {
923
+ blockStyleVariations.forEach( ( variation ) => {
924
+ const styleVariationSelector = `.is-style-${ variation.name }${ selector }`;
925
+ styleVariationSelectors[ variation.name ] =
926
+ styleVariationSelector;
927
+ } );
928
+ }
818
929
  // For each block support feature add any custom selectors.
819
930
  const featureSelectors = {};
820
931
  Object.entries( BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS ).forEach(
@@ -840,6 +951,10 @@ export const getBlockSelectors = ( blockTypes ) => {
840
951
  hasLayoutSupport,
841
952
  name,
842
953
  selector,
954
+ styleVariationSelectors: Object.keys( styleVariationSelectors )
955
+ .length
956
+ ? styleVariationSelectors
957
+ : undefined,
843
958
  };
844
959
  } );
845
960
 
@@ -892,12 +1007,19 @@ export function useGlobalStylesOutput() {
892
1007
  return !! getSettings().disableLayoutStyles;
893
1008
  } );
894
1009
 
1010
+ const getBlockStyles = useSelect( ( select ) => {
1011
+ return select( blocksStore ).getBlockStyles;
1012
+ }, [] );
1013
+
895
1014
  return useMemo( () => {
896
1015
  if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) {
897
1016
  return [];
898
1017
  }
899
1018
  mergedConfig = updateConfigWithSeparator( mergedConfig );
900
- const blockSelectors = getBlockSelectors( getBlockTypes() );
1019
+ const blockSelectors = getBlockSelectors(
1020
+ getBlockTypes(),
1021
+ getBlockStyles
1022
+ );
901
1023
  const customProperties = toCustomProperties(
902
1024
  mergedConfig,
903
1025
  blockSelectors
@@ -909,6 +1031,7 @@ export function useGlobalStylesOutput() {
909
1031
  hasFallbackGapSupport,
910
1032
  disableLayoutStyles
911
1033
  );
1034
+
912
1035
  const filters = toSvgFilters( mergedConfig, blockSelectors );
913
1036
  const stylesheets = [
914
1037
  {
@@ -90,11 +90,42 @@ export const STYLE_PATH_TO_CSS_VAR_INFIX = {
90
90
  'color.background': 'color',
91
91
  'color.text': 'color',
92
92
  'elements.link.color.text': 'color',
93
+ 'elements.link.:hover.color.text': 'color',
94
+ 'elements.link.typography.fontFamily': 'font-family',
95
+ 'elements.link.typography.fontSize': 'font-size',
93
96
  'elements.button.color.text': 'color',
94
- 'elements.button.backgroundColor': 'background-color',
97
+ 'elements.button.color.background': 'color',
98
+ 'elements.button.typography.fontFamily': 'font-family',
99
+ 'elements.button.typography.fontSize': 'font-size',
95
100
  'elements.heading.color': 'color',
96
- 'elements.heading.backgroundColor': 'background-color',
101
+ 'elements.heading.color.background': 'color',
102
+ 'elements.heading.typography.fontFamily': 'font-family',
97
103
  'elements.heading.gradient': 'gradient',
104
+ 'elements.heading.color.gradient': 'gradient',
105
+ 'elements.h1.color': 'color',
106
+ 'elements.h1.color.background': 'color',
107
+ 'elements.h1.typography.fontFamily': 'font-family',
108
+ 'elements.h1.color.gradient': 'gradient',
109
+ 'elements.h2.color': 'color',
110
+ 'elements.h2.color.background': 'color',
111
+ 'elements.h2.typography.fontFamily': 'font-family',
112
+ 'elements.h2.color.gradient': 'gradient',
113
+ 'elements.h3.color': 'color',
114
+ 'elements.h3.color.background': 'color',
115
+ 'elements.h3.typography.fontFamily': 'font-family',
116
+ 'elements.h3.color.gradient': 'gradient',
117
+ 'elements.h4.color': 'color',
118
+ 'elements.h4.color.background': 'color',
119
+ 'elements.h4.typography.fontFamily': 'font-family',
120
+ 'elements.h4.color.gradient': 'gradient',
121
+ 'elements.h5.color': 'color',
122
+ 'elements.h5.color.background': 'color',
123
+ 'elements.h5.typography.fontFamily': 'font-family',
124
+ 'elements.h5.color.gradient': 'gradient',
125
+ 'elements.h6.color': 'color',
126
+ 'elements.h6.color.background': 'color',
127
+ 'elements.h6.typography.fontFamily': 'font-family',
128
+ 'elements.h6.color.gradient': 'gradient',
98
129
  'color.gradient': 'gradient',
99
130
  'typography.fontSize': 'font-size',
100
131
  'typography.fontFamily': 'font-family',
@@ -333,3 +364,16 @@ export function scopeSelector( scope, selector ) {
333
364
 
334
365
  return selectorsScoped.join( ', ' );
335
366
  }
367
+
368
+ /**
369
+ *
370
+ * @param {string} path The variation path in the Global Styles tree.
371
+ *
372
+ * @return {string} The variation class name.
373
+ */
374
+ export function getVariationClassNameFromPath( path ) {
375
+ if ( ! path ) {
376
+ return '';
377
+ }
378
+ return `is-style-${ path.split( '.' )[ 1 ] }`;
379
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { store as blocksStore } from '@wordpress/blocks';
5
+ import { useSelect } from '@wordpress/data';
6
+ import { __experimentalItemGroup as ItemGroup } from '@wordpress/components';
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+
11
+ import { NavigationButtonAsItem } from './navigation-button';
12
+ import ContextMenu from './context-menu';
13
+
14
+ function getCoreBlockStyles( blockStyles ) {
15
+ return blockStyles?.filter( ( style ) => style.source === 'block' );
16
+ }
17
+
18
+ export function useHasVariationsPanel( name, parentMenu = '' ) {
19
+ const isInsideVariationsPanel = parentMenu.includes( 'variations' );
20
+ const blockStyles = useSelect(
21
+ ( select ) => {
22
+ const { getBlockStyles } = select( blocksStore );
23
+ return getBlockStyles( name );
24
+ },
25
+ [ name ]
26
+ );
27
+ const coreBlockStyles = getCoreBlockStyles( blockStyles );
28
+ return !! coreBlockStyles?.length && ! isInsideVariationsPanel;
29
+ }
30
+
31
+ export function VariationsPanel( { name } ) {
32
+ const blockStyles = useSelect(
33
+ ( select ) => {
34
+ const { getBlockStyles } = select( blocksStore );
35
+ return getBlockStyles( name );
36
+ },
37
+ [ name ]
38
+ );
39
+ const coreBlockStyles = getCoreBlockStyles( blockStyles );
40
+
41
+ return (
42
+ <ItemGroup isBordered isSeparated>
43
+ { coreBlockStyles.map( ( style, index ) => {
44
+ if ( style?.isDefault ) {
45
+ return null;
46
+ }
47
+ return (
48
+ <NavigationButtonAsItem
49
+ key={ index }
50
+ path={
51
+ '/blocks/' +
52
+ encodeURIComponent( name ) +
53
+ '/variations/' +
54
+ encodeURIComponent( style.name )
55
+ }
56
+ aria-label={ style.label }
57
+ >
58
+ { style.label }
59
+ </NavigationButtonAsItem>
60
+ );
61
+ } ) }
62
+ </ItemGroup>
63
+ );
64
+ }
65
+
66
+ export function VariationPanel( { blockName, styleName } ) {
67
+ return (
68
+ <ContextMenu
69
+ parentMenu={
70
+ '/blocks/' +
71
+ encodeURIComponent( blockName ) +
72
+ '/variations/' +
73
+ encodeURIComponent( styleName )
74
+ }
75
+ name={ blockName }
76
+ />
77
+ );
78
+ }