@wordpress/block-editor 11.7.0 → 11.8.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 (225) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +42 -55
  3. package/build/components/block-list/block.native.js +4 -3
  4. package/build/components/block-list/block.native.js.map +1 -1
  5. package/build/components/block-list/index.native.js +11 -21
  6. package/build/components/block-list/index.native.js.map +1 -1
  7. package/build/components/block-list/use-in-between-inserter.js +3 -1
  8. package/build/components/block-list/use-in-between-inserter.js.map +1 -1
  9. package/build/components/block-popover/inbetween.js +2 -9
  10. package/build/components/block-popover/inbetween.js.map +1 -1
  11. package/build/components/block-settings-menu/block-settings-dropdown.js +1 -10
  12. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  13. package/build/components/caption/index.native.js +0 -1
  14. package/build/components/caption/index.native.js.map +1 -1
  15. package/build/components/date-format-picker/index.js +1 -1
  16. package/build/components/date-format-picker/index.js.map +1 -1
  17. package/build/components/global-styles/border-panel.js +15 -29
  18. package/build/components/global-styles/border-panel.js.map +1 -1
  19. package/build/components/global-styles/dimensions-panel.js +15 -14
  20. package/build/components/global-styles/dimensions-panel.js.map +1 -1
  21. package/build/components/global-styles/effects-panel.js +244 -0
  22. package/build/components/global-styles/effects-panel.js.map +1 -0
  23. package/build/components/global-styles/filters-panel.js +151 -0
  24. package/build/components/global-styles/filters-panel.js.map +1 -0
  25. package/build/components/global-styles/get-block-css-selector.js +1 -12
  26. package/build/components/global-styles/get-block-css-selector.js.map +1 -1
  27. package/build/components/global-styles/hooks.js +7 -0
  28. package/build/components/global-styles/hooks.js.map +1 -1
  29. package/build/components/global-styles/index.js +28 -0
  30. package/build/components/global-styles/index.js.map +1 -1
  31. package/build/components/global-styles/use-global-styles-output.js +15 -7
  32. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  33. package/build/components/iframe/index.js +1 -1
  34. package/build/components/iframe/index.js.map +1 -1
  35. package/build/components/image-size-control/use-dimension-handler.js +5 -3
  36. package/build/components/image-size-control/use-dimension-handler.js.map +1 -1
  37. package/build/components/index.js +16 -0
  38. package/build/components/index.js.map +1 -1
  39. package/build/components/inserter/block-patterns-tab.js +4 -2
  40. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  41. package/build/components/inspector-controls-tabs/utils.js +5 -3
  42. package/build/components/inspector-controls-tabs/utils.js.map +1 -1
  43. package/build/components/list-view/block.js +1 -0
  44. package/build/components/list-view/block.js.map +1 -1
  45. package/build/components/list-view/index.js +22 -4
  46. package/build/components/list-view/index.js.map +1 -1
  47. package/build/components/list-view/use-list-view-client-ids.js +7 -3
  48. package/build/components/list-view/use-list-view-client-ids.js.map +1 -1
  49. package/build/components/list-view/use-list-view-drop-zone.js +8 -2
  50. package/build/components/list-view/use-list-view-drop-zone.js.map +1 -1
  51. package/build/components/off-canvas-editor/block-contents.js +6 -1
  52. package/build/components/off-canvas-editor/block-contents.js.map +1 -1
  53. package/build/components/off-canvas-editor/index.js +17 -14
  54. package/build/components/off-canvas-editor/index.js.map +1 -1
  55. package/build/components/resizable-box-popover/index.js +38 -0
  56. package/build/components/resizable-box-popover/index.js.map +1 -0
  57. package/build/components/rich-text/index.js +0 -1
  58. package/build/components/rich-text/index.js.map +1 -1
  59. package/build/components/rich-text/index.native.js +7 -11
  60. package/build/components/rich-text/index.native.js.map +1 -1
  61. package/build/components/spacing-sizes-control/spacing-input-control.js +8 -0
  62. package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  63. package/build/hooks/anchor.js +1 -1
  64. package/build/hooks/anchor.js.map +1 -1
  65. package/build/hooks/border.js +1 -1
  66. package/build/hooks/border.js.map +1 -1
  67. package/build/hooks/duotone.js +92 -66
  68. package/build/hooks/duotone.js.map +1 -1
  69. package/build/hooks/margin.js +27 -17
  70. package/build/hooks/margin.js.map +1 -1
  71. package/build/hooks/padding.js +19 -9
  72. package/build/hooks/padding.js.map +1 -1
  73. package/build/hooks/utils.js +7 -4
  74. package/build/hooks/utils.js.map +1 -1
  75. package/build/layouts/utils.js +3 -2
  76. package/build/layouts/utils.js.map +1 -1
  77. package/build/private-apis.js +4 -1
  78. package/build/private-apis.js.map +1 -1
  79. package/build/store/actions.js +1 -1
  80. package/build/store/actions.js.map +1 -1
  81. package/build/utils/object.js +1 -1
  82. package/build/utils/object.js.map +1 -1
  83. package/build-module/components/block-list/block.native.js +4 -3
  84. package/build-module/components/block-list/block.native.js.map +1 -1
  85. package/build-module/components/block-list/index.native.js +11 -19
  86. package/build-module/components/block-list/index.native.js.map +1 -1
  87. package/build-module/components/block-list/use-in-between-inserter.js +2 -1
  88. package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
  89. package/build-module/components/block-popover/inbetween.js +2 -9
  90. package/build-module/components/block-popover/inbetween.js.map +1 -1
  91. package/build-module/components/block-settings-menu/block-settings-dropdown.js +1 -9
  92. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  93. package/build-module/components/caption/index.native.js +0 -1
  94. package/build-module/components/caption/index.native.js.map +1 -1
  95. package/build-module/components/date-format-picker/index.js +1 -1
  96. package/build-module/components/date-format-picker/index.js.map +1 -1
  97. package/build-module/components/global-styles/border-panel.js +15 -29
  98. package/build-module/components/global-styles/border-panel.js.map +1 -1
  99. package/build-module/components/global-styles/dimensions-panel.js +15 -14
  100. package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
  101. package/build-module/components/global-styles/effects-panel.js +228 -0
  102. package/build-module/components/global-styles/effects-panel.js.map +1 -0
  103. package/build-module/components/global-styles/filters-panel.js +139 -0
  104. package/build-module/components/global-styles/filters-panel.js.map +1 -0
  105. package/build-module/components/global-styles/get-block-css-selector.js +1 -12
  106. package/build-module/components/global-styles/get-block-css-selector.js.map +1 -1
  107. package/build-module/components/global-styles/hooks.js +7 -0
  108. package/build-module/components/global-styles/hooks.js.map +1 -1
  109. package/build-module/components/global-styles/index.js +2 -0
  110. package/build-module/components/global-styles/index.js.map +1 -1
  111. package/build-module/components/global-styles/use-global-styles-output.js +16 -8
  112. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  113. package/build-module/components/iframe/index.js +1 -1
  114. package/build-module/components/iframe/index.js.map +1 -1
  115. package/build-module/components/image-size-control/use-dimension-handler.js +5 -3
  116. package/build-module/components/image-size-control/use-dimension-handler.js.map +1 -1
  117. package/build-module/components/index.js +1 -0
  118. package/build-module/components/index.js.map +1 -1
  119. package/build-module/components/inserter/block-patterns-tab.js +5 -2
  120. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  121. package/build-module/components/inspector-controls-tabs/utils.js +4 -3
  122. package/build-module/components/inspector-controls-tabs/utils.js.map +1 -1
  123. package/build-module/components/list-view/block.js +1 -0
  124. package/build-module/components/list-view/block.js.map +1 -1
  125. package/build-module/components/list-view/index.js +21 -4
  126. package/build-module/components/list-view/index.js.map +1 -1
  127. package/build-module/components/list-view/use-list-view-client-ids.js +7 -3
  128. package/build-module/components/list-view/use-list-view-client-ids.js.map +1 -1
  129. package/build-module/components/list-view/use-list-view-drop-zone.js +8 -4
  130. package/build-module/components/list-view/use-list-view-drop-zone.js.map +1 -1
  131. package/build-module/components/off-canvas-editor/block-contents.js +5 -1
  132. package/build-module/components/off-canvas-editor/block-contents.js.map +1 -1
  133. package/build-module/components/off-canvas-editor/index.js +17 -14
  134. package/build-module/components/off-canvas-editor/index.js.map +1 -1
  135. package/build-module/components/resizable-box-popover/index.js +26 -0
  136. package/build-module/components/resizable-box-popover/index.js.map +1 -0
  137. package/build-module/components/rich-text/index.js +0 -1
  138. package/build-module/components/rich-text/index.js.map +1 -1
  139. package/build-module/components/rich-text/index.native.js +7 -10
  140. package/build-module/components/rich-text/index.native.js.map +1 -1
  141. package/build-module/components/spacing-sizes-control/spacing-input-control.js +7 -0
  142. package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
  143. package/build-module/hooks/anchor.js +1 -1
  144. package/build-module/hooks/anchor.js.map +1 -1
  145. package/build-module/hooks/border.js +1 -1
  146. package/build-module/hooks/border.js.map +1 -1
  147. package/build-module/hooks/duotone.js +90 -66
  148. package/build-module/hooks/duotone.js.map +1 -1
  149. package/build-module/hooks/margin.js +29 -18
  150. package/build-module/hooks/margin.js.map +1 -1
  151. package/build-module/hooks/padding.js +21 -10
  152. package/build-module/hooks/padding.js.map +1 -1
  153. package/build-module/hooks/utils.js +8 -5
  154. package/build-module/hooks/utils.js.map +1 -1
  155. package/build-module/layouts/utils.js +3 -2
  156. package/build-module/layouts/utils.js.map +1 -1
  157. package/build-module/private-apis.js +3 -1
  158. package/build-module/private-apis.js.map +1 -1
  159. package/build-module/store/actions.js +1 -1
  160. package/build-module/store/actions.js.map +1 -1
  161. package/build-module/utils/object.js +1 -1
  162. package/build-module/utils/object.js.map +1 -1
  163. package/build-style/style-rtl.css +51 -10
  164. package/build-style/style.css +51 -10
  165. package/package.json +31 -31
  166. package/src/components/block-inspector/style.scss +6 -4
  167. package/src/components/block-list/block.native.js +3 -2
  168. package/src/components/block-list/index.native.js +19 -38
  169. package/src/components/block-list/use-in-between-inserter.js +4 -1
  170. package/src/components/block-popover/inbetween.js +2 -13
  171. package/src/components/block-settings-menu/block-settings-dropdown.js +2 -12
  172. package/src/components/caption/index.native.js +0 -1
  173. package/src/components/date-format-picker/index.js +1 -1
  174. package/src/components/global-styles/README.md +129 -16
  175. package/src/components/global-styles/border-panel.js +13 -32
  176. package/src/components/global-styles/dimensions-panel.js +30 -13
  177. package/src/components/global-styles/effects-panel.js +228 -0
  178. package/src/components/global-styles/filters-panel.js +157 -0
  179. package/src/components/global-styles/get-block-css-selector.js +0 -11
  180. package/src/components/global-styles/hooks.js +10 -0
  181. package/src/components/global-styles/index.js +2 -0
  182. package/src/components/global-styles/style.scss +42 -0
  183. package/src/components/global-styles/test/use-global-styles-output.js +4 -4
  184. package/src/components/global-styles/use-global-styles-output.js +27 -11
  185. package/src/components/iframe/index.js +1 -1
  186. package/src/components/image-size-control/use-dimension-handler.js +4 -3
  187. package/src/components/index.js +4 -1
  188. package/src/components/inserter/block-patterns-tab.js +3 -1
  189. package/src/components/inspector-controls-tabs/utils.js +4 -3
  190. package/src/components/list-view/README.md +2 -0
  191. package/src/components/list-view/block.js +1 -0
  192. package/src/components/list-view/index.js +18 -2
  193. package/src/components/list-view/style.scss +3 -1
  194. package/src/components/list-view/test/use-list-view-drop-zone.js +188 -0
  195. package/src/components/list-view/use-list-view-client-ids.js +5 -3
  196. package/src/components/list-view/use-list-view-drop-zone.js +9 -3
  197. package/src/components/off-canvas-editor/block-contents.js +4 -0
  198. package/src/components/off-canvas-editor/index.js +15 -11
  199. package/src/components/resizable-box-popover/index.js +27 -0
  200. package/src/components/rich-text/index.js +0 -1
  201. package/src/components/rich-text/index.native.js +2 -5
  202. package/src/components/spacing-sizes-control/spacing-input-control.js +10 -0
  203. package/src/components/spacing-sizes-control/style.scss +7 -7
  204. package/src/hooks/anchor.js +1 -1
  205. package/src/hooks/border.js +1 -1
  206. package/src/hooks/duotone.js +116 -74
  207. package/src/hooks/margin.js +31 -26
  208. package/src/hooks/padding.js +24 -18
  209. package/src/hooks/utils.js +4 -4
  210. package/src/layouts/utils.js +2 -2
  211. package/src/private-apis.js +2 -0
  212. package/src/store/actions.js +1 -1
  213. package/src/style.scss +1 -0
  214. package/src/utils/object.js +1 -1
  215. package/src/utils/test/object.js +38 -0
  216. package/build/components/rich-text/use-native-props.js +0 -11
  217. package/build/components/rich-text/use-native-props.js.map +0 -1
  218. package/build/components/rich-text/use-native-props.native.js +0 -24
  219. package/build/components/rich-text/use-native-props.native.js.map +0 -1
  220. package/build-module/components/rich-text/use-native-props.js +0 -4
  221. package/build-module/components/rich-text/use-native-props.js.map +0 -1
  222. package/build-module/components/rich-text/use-native-props.native.js +0 -15
  223. package/build-module/components/rich-text/use-native-props.native.js.map +0 -1
  224. package/src/components/rich-text/use-native-props.js +0 -3
  225. package/src/components/rich-text/use-native-props.native.js +0 -17
@@ -14,9 +14,7 @@ import { useGlobalStylesReset } from '@wordpress/block-editor';
14
14
  function MyComponent() {
15
15
  const [ canReset, reset ] = useGlobalStylesReset();
16
16
 
17
- return canReset
18
- ? <Button onClick={ () => reset() }>Reset</Button>
19
- : null;
17
+ return canReset ? <Button onClick={ () => reset() }>Reset</Button> : null;
20
18
  }
21
19
  ```
22
20
 
@@ -25,17 +23,25 @@ function MyComponent() {
25
23
  A React hook used to retrieve the styles array and settings to provide for block editor instances based on the current global styles.
26
24
 
27
25
  ```js
28
- import { useGlobalStylesOutput, BlockEditorProvider, BlockList } from '@wordpress/block-editor';
26
+ import {
27
+ useGlobalStylesOutput,
28
+ BlockEditorProvider,
29
+ BlockList,
30
+ } from '@wordpress/block-editor';
29
31
 
30
32
  function MyComponent() {
31
33
  const [ styles, settings ] = useGlobalStylesOutput();
32
34
 
33
- return <BlockEditorProvider settings={{
34
- styles,
35
- __experimentalFeatures: settings
36
- }}>
37
- <BlockList />
38
- </BlockEditorProvider>
35
+ return (
36
+ <BlockEditorProvider
37
+ settings={ {
38
+ styles,
39
+ __experimentalFeatures: settings,
40
+ } }
41
+ >
42
+ <BlockList />
43
+ </BlockEditorProvider>
44
+ );
39
45
  }
40
46
  ```
41
47
 
@@ -48,12 +54,16 @@ import { useGlobalStyle } from '@wordpress/block-editor';
48
54
 
49
55
  function MyComponent() {
50
56
  // Text color for the site root.
51
- const [ color, setColor ] = useGlobalStyle( 'color.text' );
57
+ const [ color, setColor ] = useGlobalStyle( 'color.text' );
52
58
 
53
59
  // The user modified color for the core paragraph block.
54
- const [ pColor, setPColor ] = useGlobalStyle( 'color.text', 'core/paragraph', 'user' );
60
+ const [ pColor, setPColor ] = useGlobalStyle(
61
+ 'color.text',
62
+ 'core/paragraph',
63
+ 'user'
64
+ );
55
65
 
56
- return "Something";
66
+ return 'Something';
57
67
  }
58
68
  ```
59
69
 
@@ -66,12 +76,115 @@ import { useGlobalSetting } from '@wordpress/block-editor';
66
76
 
67
77
  function MyComponent() {
68
78
  // The theme color palette.
69
- const [ colorPalette, setColorPalette ] = useGlobalSetting( 'color.palette.theme' );
79
+ const [ colorPalette, setColorPalette ] = useGlobalSetting(
80
+ 'color.palette.theme'
81
+ );
70
82
 
71
83
  // The theme color palette for the paragraph block, ignoring user changes.
72
84
  // If the palette is not defined for the paragraph block, the root one is returned.
73
- const [ pColor, setPColor ] = useGlobalSetting( 'color.palette.theme', 'core/paragraph', 'base' );
85
+ const [ pColor, setPColor ] = useGlobalSetting(
86
+ 'color.palette.theme',
87
+ 'core/paragraph',
88
+ 'base'
89
+ );
74
90
 
75
- return "Something";
91
+ return 'Something';
76
92
  }
77
93
  ```
94
+
95
+ ## UI Components
96
+
97
+ The global styles folder also offers a set of reusable UI components. These components follow a strict set of guidelines:
98
+
99
+ - They are independent of any context or any store dependency. They only rely on the props passed to them.
100
+ - They receive a similar set of props:
101
+
102
+ - `value`: The value is a style object that maps closely the format used in `theme.json` and is also very close to the format of the `style` attributes for blocks. There are some differences with the block attributes due to the iteration process and the fact that we need to maintain compatibility with the existing blocks even if they predate the introduction of Global Styles and these UI components. An example value for a style object is:
103
+
104
+ ```js
105
+ {
106
+ color: {
107
+ text: 'var:preset|color|blue',
108
+ background: '#FF0000',
109
+ },
110
+ typography: {
111
+ fontFamily: 'var:preset|font-family|base',
112
+ fontSize: '10px',
113
+ lineHeight: 1.5,
114
+ },
115
+ spacing: {
116
+ padding: 'var:preset|spacing|medium',
117
+ },
118
+ elements: {
119
+ link: {
120
+ color: {
121
+ text: 'var:preset|color|green',
122
+ },
123
+ },
124
+ },
125
+ }
126
+ ```
127
+
128
+ - `onChange`: A callback that receives the new value and is called when the user changes the value of the UI component.
129
+ - `inheritedValue`: The inherited value is a style object that represents the combined value of the style inherited from the parent context in addition to the style applied to the current context. The format is the same as the `value` prop.
130
+ - `settings`: The settings are the theme.json settings. They are used to provide the UI components with the necessary information to render the UI. An example value for the settings is:
131
+
132
+ ```js
133
+ {
134
+ color: {
135
+ palette: {
136
+ custom: [
137
+ {
138
+ slug: 'black',
139
+ color: '#000000',
140
+ },
141
+ {
142
+ slug: 'white',
143
+ color: '#FFFFFF',
144
+ },
145
+ {
146
+ slug: 'blue',
147
+ color: '#0000FF',
148
+ },
149
+ ]
150
+ },
151
+ gradients: {
152
+ custom: [
153
+ {
154
+ slug: 'gradient-1',
155
+ gradient: 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
156
+ },
157
+ {
158
+ slug: 'gradient-2',
159
+ gradient: 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
160
+ },
161
+ ]
162
+ },
163
+ },
164
+ typography: {
165
+ fontSizes: [
166
+ {
167
+ slug: 'small',
168
+ size: '12px',
169
+ },
170
+ {
171
+ slug: 'medium',
172
+ size: '16px',
173
+ },
174
+ {
175
+ slug: 'large',
176
+ size: '24px',
177
+ },
178
+ ],
179
+ }
180
+ }
181
+ ```
182
+ - `defaultControls`: The default controls are the controls that are used by default to render the UI. They are used to provide the UI components with the necessary information to render the UI. An example value for the default controls for the `ColorPanel` component is:
183
+
184
+ ```js
185
+ {
186
+ background: true,
187
+ text: true,
188
+ link: true,
189
+ },
190
+ ```
@@ -186,39 +186,20 @@ export default function BorderPanel( {
186
186
  const onBorderChange = ( newBorder ) => {
187
187
  // Ensure we have a visible border style when a border width or
188
188
  // color is being selected.
189
- const newBorderWithStyle = applyAllFallbackStyles( newBorder );
189
+ const updatedBorder = applyAllFallbackStyles( newBorder );
190
190
 
191
- // As we can't conditionally generate styles based on if other
192
- // style properties have been set we need to force split border
193
- // definitions for user set border styles. Border radius is derived
194
- // from the same property i.e. `border.radius` if it is a string
195
- // that is used. The longhand border radii styles are only generated
196
- // if that property is an object.
197
- //
198
- // For borders (color, style, and width) those are all properties on
199
- // the `border` style property. This means if the theme.json defined
200
- // split borders and the user condenses them into a flat border or
201
- // vice-versa we'd get both sets of styles which would conflict.
202
- const updatedBorder = ! hasSplitBorders( newBorderWithStyle )
203
- ? {
204
- top: newBorderWithStyle,
205
- right: newBorderWithStyle,
206
- bottom: newBorderWithStyle,
207
- left: newBorderWithStyle,
208
- }
209
- : {
210
- color: null,
211
- style: null,
212
- width: null,
213
- ...newBorderWithStyle,
214
- };
215
-
216
- [ 'top', 'right', 'bottom', 'left' ].forEach( ( side ) => {
217
- updatedBorder[ side ] = {
218
- ...updatedBorder[ side ],
219
- color: encodeColorValue( updatedBorder[ side ]?.color ),
220
- };
221
- } );
191
+ if ( hasSplitBorders( updatedBorder ) ) {
192
+ [ 'top', 'right', 'bottom', 'left' ].forEach( ( side ) => {
193
+ if ( updatedBorder[ side ] ) {
194
+ updatedBorder[ side ] = {
195
+ ...updatedBorder[ side ],
196
+ color: encodeColorValue( updatedBorder[ side ]?.color ),
197
+ };
198
+ }
199
+ } );
200
+ } else if ( updatedBorder ) {
201
+ updatedBorder.color = encodeColorValue( updatedBorder.color );
202
+ }
222
203
 
223
204
  // As radius is maintained separately to color, style, and width
224
205
  // maintain its value. Undefined values here will be cleaned when
@@ -184,12 +184,13 @@ function DimensionsToolsPanel( {
184
184
  }
185
185
 
186
186
  const DEFAULT_CONTROLS = {
187
- contentSize: true,
188
- wideSize: true,
189
- padding: true,
190
- margin: true,
191
- blockGap: true,
192
- minHeight: true,
187
+ contentSize: false,
188
+ wideSize: false,
189
+ padding: false,
190
+ margin: false,
191
+ blockGap: false,
192
+ minHeight: false,
193
+ childLayout: true,
193
194
  };
194
195
 
195
196
  export default function DimensionsPanel( {
@@ -391,7 +392,10 @@ export default function DimensionsPanel( {
391
392
  label={ __( 'Content size' ) }
392
393
  hasValue={ hasUserSetContentSizeValue }
393
394
  onDeselect={ resetContentSizeValue }
394
- isShownByDefault={ defaultControls.contentSize }
395
+ isShownByDefault={
396
+ defaultControls.contentSize ??
397
+ DEFAULT_CONTROLS.contentSize
398
+ }
395
399
  panelId={ panelId }
396
400
  >
397
401
  <HStack alignment="flex-end" justify="flex-start">
@@ -417,7 +421,9 @@ export default function DimensionsPanel( {
417
421
  label={ __( 'Wide size' ) }
418
422
  hasValue={ hasUserSetWideSizeValue }
419
423
  onDeselect={ resetWideSizeValue }
420
- isShownByDefault={ defaultControls.wideSize }
424
+ isShownByDefault={
425
+ defaultControls.wideSize ?? DEFAULT_CONTROLS.wideSize
426
+ }
421
427
  panelId={ panelId }
422
428
  >
423
429
  <HStack alignment="flex-end" justify="flex-start">
@@ -442,7 +448,9 @@ export default function DimensionsPanel( {
442
448
  hasValue={ hasPaddingValue }
443
449
  label={ __( 'Padding' ) }
444
450
  onDeselect={ resetPaddingValue }
445
- isShownByDefault={ defaultControls.padding }
451
+ isShownByDefault={
452
+ defaultControls.padding ?? DEFAULT_CONTROLS.padding
453
+ }
446
454
  className={ classnames( {
447
455
  'tools-panel-item-spacing': showSpacingPresetsControl,
448
456
  } ) }
@@ -481,7 +489,9 @@ export default function DimensionsPanel( {
481
489
  hasValue={ hasMarginValue }
482
490
  label={ __( 'Margin' ) }
483
491
  onDeselect={ resetMarginValue }
484
- isShownByDefault={ defaultControls.margin }
492
+ isShownByDefault={
493
+ defaultControls.margin ?? DEFAULT_CONTROLS.margin
494
+ }
485
495
  className={ classnames( {
486
496
  'tools-panel-item-spacing': showSpacingPresetsControl,
487
497
  } ) }
@@ -520,7 +530,9 @@ export default function DimensionsPanel( {
520
530
  hasValue={ hasGapValue }
521
531
  label={ __( 'Block spacing' ) }
522
532
  onDeselect={ resetGapValue }
523
- isShownByDefault={ defaultControls.blockGap }
533
+ isShownByDefault={
534
+ defaultControls.blockGap ?? DEFAULT_CONTROLS.blockGap
535
+ }
524
536
  className={ classnames( {
525
537
  'tools-panel-item-spacing': showSpacingPresetsControl,
526
538
  } ) }
@@ -566,7 +578,9 @@ export default function DimensionsPanel( {
566
578
  hasValue={ hasMinHeightValue }
567
579
  label={ __( 'Min. height' ) }
568
580
  onDeselect={ resetMinHeightValue }
569
- isShownByDefault={ defaultControls.minHeight }
581
+ isShownByDefault={
582
+ defaultControls.minHeight ?? DEFAULT_CONTROLS.minHeight
583
+ }
570
584
  panelId={ panelId }
571
585
  >
572
586
  <HeightControl
@@ -583,7 +597,10 @@ export default function DimensionsPanel( {
583
597
  hasValue={ hasChildLayoutValue }
584
598
  label={ childLayoutOrientationLabel }
585
599
  onDeselect={ resetChildLayoutValue }
586
- isShownByDefault={ defaultControls.childLayout }
600
+ isShownByDefault={
601
+ defaultControls.childLayout ??
602
+ DEFAULT_CONTROLS.childLayout
603
+ }
587
604
  panelId={ panelId }
588
605
  >
589
606
  <ChildLayoutControl
@@ -0,0 +1,228 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import {
10
+ __experimentalToolsPanel as ToolsPanel,
11
+ __experimentalToolsPanelItem as ToolsPanelItem,
12
+ __experimentalItemGroup as ItemGroup,
13
+ __experimentalHStack as HStack,
14
+ __experimentalVStack as VStack,
15
+ __experimentalGrid as Grid,
16
+ __experimentalHeading as Heading,
17
+ FlexItem,
18
+ Dropdown,
19
+ __experimentalDropdownContentWrapper as DropdownContentWrapper,
20
+ Button,
21
+ } from '@wordpress/components';
22
+ import { __ } from '@wordpress/i18n';
23
+ import { useCallback } from '@wordpress/element';
24
+ import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
25
+
26
+ /**
27
+ * Internal dependencies
28
+ */
29
+ import { getValueFromVariable } from './utils';
30
+ import { immutableSet } from '../../utils/object';
31
+
32
+ export function useHasEffectsPanel( settings ) {
33
+ const hasShadowControl = useHasShadowControl( settings );
34
+ return hasShadowControl;
35
+ }
36
+
37
+ function useHasShadowControl( settings ) {
38
+ return !! settings?.shadow;
39
+ }
40
+
41
+ function EffectsToolsPanel( {
42
+ resetAllFilter,
43
+ onChange,
44
+ value,
45
+ panelId,
46
+ children,
47
+ } ) {
48
+ const resetAll = () => {
49
+ const updatedValue = resetAllFilter( value );
50
+ onChange( updatedValue );
51
+ };
52
+
53
+ return (
54
+ <ToolsPanel
55
+ label={ __( 'Effects' ) }
56
+ resetAll={ resetAll }
57
+ panelId={ panelId }
58
+ >
59
+ { children }
60
+ </ToolsPanel>
61
+ );
62
+ }
63
+
64
+ const DEFAULT_CONTROLS = {
65
+ shadow: true,
66
+ };
67
+
68
+ export default function EffectsPanel( {
69
+ as: Wrapper = EffectsToolsPanel,
70
+ value,
71
+ onChange,
72
+ inheritedValue = value,
73
+ settings,
74
+ panelId,
75
+ defaultControls = DEFAULT_CONTROLS,
76
+ } ) {
77
+ const decodeValue = ( rawValue ) =>
78
+ getValueFromVariable( { settings }, '', rawValue );
79
+
80
+ // Shadow
81
+ const hasShadowEnabled = useHasShadowControl( settings );
82
+ const shadow = decodeValue( inheritedValue?.shadow );
83
+ const setShadow = ( newValue ) => {
84
+ onChange( immutableSet( value, [ 'shadow' ], newValue ) );
85
+ };
86
+ const hasShadow = () => !! value?.shadow;
87
+ const resetShadow = () => setShadow( undefined );
88
+
89
+ const resetAllFilter = useCallback( ( previousValue ) => {
90
+ return {
91
+ ...previousValue,
92
+ shadow: undefined,
93
+ };
94
+ }, [] );
95
+
96
+ return (
97
+ <Wrapper
98
+ resetAllFilter={ resetAllFilter }
99
+ value={ value }
100
+ onChange={ onChange }
101
+ panelId={ panelId }
102
+ >
103
+ { hasShadowEnabled && (
104
+ <ToolsPanelItem
105
+ label={ __( 'Shadow' ) }
106
+ hasValue={ hasShadow }
107
+ onDeselect={ resetShadow }
108
+ isShownByDefault={ defaultControls.shadow }
109
+ panelId={ panelId }
110
+ >
111
+ <ItemGroup isBordered isSeparated>
112
+ <ShadowPopover
113
+ shadow={ shadow }
114
+ onShadowChange={ setShadow }
115
+ settings={ settings }
116
+ />
117
+ </ItemGroup>
118
+ </ToolsPanelItem>
119
+ ) }
120
+ </Wrapper>
121
+ );
122
+ }
123
+
124
+ const ShadowPopover = ( { shadow, onShadowChange, settings } ) => {
125
+ const popoverProps = {
126
+ placement: 'left-start',
127
+ offset: 36,
128
+ shift: true,
129
+ };
130
+
131
+ return (
132
+ <Dropdown
133
+ popoverProps={ popoverProps }
134
+ className="block-editor-global-styles-effects-panel__shadow-dropdown"
135
+ renderToggle={ renderShadowToggle() }
136
+ renderContent={ () => (
137
+ <DropdownContentWrapper paddingSize="medium">
138
+ <ShadowPopoverContainer
139
+ shadow={ shadow }
140
+ onShadowChange={ onShadowChange }
141
+ settings={ settings }
142
+ />
143
+ </DropdownContentWrapper>
144
+ ) }
145
+ />
146
+ );
147
+ };
148
+
149
+ function renderShadowToggle() {
150
+ return ( { onToggle, isOpen } ) => {
151
+ const toggleProps = {
152
+ onClick: onToggle,
153
+ className: classnames( { 'is-open': isOpen } ),
154
+ 'aria-expanded': isOpen,
155
+ };
156
+
157
+ return (
158
+ <Button { ...toggleProps }>
159
+ <HStack justify="flex-start">
160
+ <Icon
161
+ className="block-editor-global-styles-effects-panel__toggle-icon"
162
+ icon={ shadowIcon }
163
+ size={ 24 }
164
+ />
165
+ <FlexItem>{ __( 'Shadow' ) }</FlexItem>
166
+ </HStack>
167
+ </Button>
168
+ );
169
+ };
170
+ }
171
+
172
+ function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
173
+ const defaultShadows = settings?.shadow?.presets?.default;
174
+ const themeShadows = settings?.shadow?.presets?.theme;
175
+ const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
176
+
177
+ const shadows = [
178
+ ...( defaultPresetsEnabled ? defaultShadows : [] ),
179
+ ...( themeShadows || [] ),
180
+ ];
181
+
182
+ return (
183
+ <div className="block-editor-global-styles-effects-panel__shadow-popover-container">
184
+ <VStack spacing={ 4 }>
185
+ <Heading level={ 5 }>{ __( 'Shadow' ) }</Heading>
186
+ <ShadowPresets
187
+ presets={ shadows }
188
+ activeShadow={ shadow }
189
+ onSelect={ onShadowChange }
190
+ />
191
+ </VStack>
192
+ </div>
193
+ );
194
+ }
195
+
196
+ function ShadowPresets( { presets, activeShadow, onSelect } ) {
197
+ return ! presets ? null : (
198
+ <Grid columns={ 6 } gap={ 0 } align="center" justify="center">
199
+ { presets.map( ( { name, slug, shadow } ) => (
200
+ <ShadowIndicator
201
+ key={ slug }
202
+ label={ name }
203
+ isActive={ shadow === activeShadow }
204
+ onSelect={ () =>
205
+ onSelect( shadow === activeShadow ? undefined : shadow )
206
+ }
207
+ shadow={ shadow }
208
+ />
209
+ ) ) }
210
+ </Grid>
211
+ );
212
+ }
213
+
214
+ function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
215
+ return (
216
+ <div className="block-editor-global-styles-effects-panel__shadow-indicator-wrapper">
217
+ <Button
218
+ className="block-editor-global-styles-effects-panel__shadow-indicator"
219
+ onClick={ onSelect }
220
+ label={ label }
221
+ style={ { boxShadow: shadow } }
222
+ showTooltip
223
+ >
224
+ { isActive && <Icon icon={ check } /> }
225
+ </Button>
226
+ </div>
227
+ );
228
+ }