@wordpress/block-editor 12.19.3 → 12.19.5

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 (165) hide show
  1. package/build/components/block-actions/index.js +45 -32
  2. package/build/components/block-actions/index.js.map +1 -1
  3. package/build/components/block-bindings-toolbar-indicator/index.js +25 -0
  4. package/build/components/block-bindings-toolbar-indicator/index.js.map +1 -0
  5. package/build/components/block-edit/context.js +2 -1
  6. package/build/components/block-edit/context.js.map +1 -1
  7. package/build/components/block-edit/index.js +8 -3
  8. package/build/components/block-edit/index.js.map +1 -1
  9. package/build/components/block-inspector/index.js +5 -4
  10. package/build/components/block-inspector/index.js.map +1 -1
  11. package/build/components/block-list/use-block-props/index.js +8 -1
  12. package/build/components/block-list/use-block-props/index.js.map +1 -1
  13. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  14. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  15. package/build/components/block-preview/index.js +4 -0
  16. package/build/components/block-preview/index.js.map +1 -1
  17. package/build/components/block-settings-menu/block-settings-dropdown.js +12 -10
  18. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  19. package/build/components/block-toolbar/index.js +14 -5
  20. package/build/components/block-toolbar/index.js.map +1 -1
  21. package/build/components/global-styles/border-panel.js +21 -8
  22. package/build/components/global-styles/border-panel.js.map +1 -1
  23. package/build/components/global-styles/index.js +6 -0
  24. package/build/components/global-styles/index.js.map +1 -1
  25. package/build/components/global-styles/shadow-panel-components.js +80 -23
  26. package/build/components/global-styles/shadow-panel-components.js.map +1 -1
  27. package/build/components/inspector-controls-tabs/styles-tab.js +1 -1
  28. package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  29. package/build/components/link-control/link-preview.js +4 -1
  30. package/build/components/link-control/link-preview.js.map +1 -1
  31. package/build/components/list-view/block-select-button.js +10 -2
  32. package/build/components/list-view/block-select-button.js.map +1 -1
  33. package/build/components/list-view/use-clipboard-handler.js +2 -1
  34. package/build/components/list-view/use-clipboard-handler.js.map +1 -1
  35. package/build/components/rich-text/index.js +46 -26
  36. package/build/components/rich-text/index.js.map +1 -1
  37. package/build/components/rich-text/use-enter.js +3 -0
  38. package/build/components/rich-text/use-enter.js.map +1 -1
  39. package/build/components/url-popover/index.js +3 -3
  40. package/build/components/url-popover/index.js.map +1 -1
  41. package/build/components/writing-flow/use-clipboard-handler.js +2 -1
  42. package/build/components/writing-flow/use-clipboard-handler.js.map +1 -1
  43. package/build/components/writing-flow/utils.js +23 -6
  44. package/build/components/writing-flow/utils.js.map +1 -1
  45. package/build/hooks/block-hooks.js +34 -8
  46. package/build/hooks/block-hooks.js.map +1 -1
  47. package/build/hooks/border.js +6 -4
  48. package/build/hooks/border.js.map +1 -1
  49. package/build/hooks/use-bindings-attributes.js +171 -48
  50. package/build/hooks/use-bindings-attributes.js.map +1 -1
  51. package/build/private-apis.js +5 -1
  52. package/build/private-apis.js.map +1 -1
  53. package/build/store/actions.js +40 -6
  54. package/build/store/actions.js.map +1 -1
  55. package/build/store/private-actions.js +0 -10
  56. package/build/store/private-actions.js.map +1 -1
  57. package/build/store/private-selectors.js +0 -8
  58. package/build/store/private-selectors.js.map +1 -1
  59. package/build/store/reducer.js +1 -16
  60. package/build/store/reducer.js.map +1 -1
  61. package/build-module/components/block-actions/index.js +45 -32
  62. package/build-module/components/block-actions/index.js.map +1 -1
  63. package/build-module/components/block-bindings-toolbar-indicator/index.js +18 -0
  64. package/build-module/components/block-bindings-toolbar-indicator/index.js.map +1 -0
  65. package/build-module/components/block-edit/context.js +1 -0
  66. package/build-module/components/block-edit/context.js.map +1 -1
  67. package/build-module/components/block-edit/index.js +9 -4
  68. package/build-module/components/block-edit/index.js.map +1 -1
  69. package/build-module/components/block-inspector/index.js +6 -5
  70. package/build-module/components/block-inspector/index.js.map +1 -1
  71. package/build-module/components/block-list/use-block-props/index.js +9 -2
  72. package/build-module/components/block-list/use-block-props/index.js.map +1 -1
  73. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  74. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  75. package/build-module/components/block-preview/index.js +4 -0
  76. package/build-module/components/block-preview/index.js.map +1 -1
  77. package/build-module/components/block-settings-menu/block-settings-dropdown.js +12 -10
  78. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  79. package/build-module/components/block-toolbar/index.js +14 -5
  80. package/build-module/components/block-toolbar/index.js.map +1 -1
  81. package/build-module/components/global-styles/border-panel.js +22 -10
  82. package/build-module/components/global-styles/border-panel.js.map +1 -1
  83. package/build-module/components/global-styles/index.js +1 -1
  84. package/build-module/components/global-styles/index.js.map +1 -1
  85. package/build-module/components/global-styles/shadow-panel-components.js +82 -24
  86. package/build-module/components/global-styles/shadow-panel-components.js.map +1 -1
  87. package/build-module/components/inspector-controls-tabs/styles-tab.js +2 -2
  88. package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  89. package/build-module/components/link-control/link-preview.js +5 -2
  90. package/build-module/components/link-control/link-preview.js.map +1 -1
  91. package/build-module/components/list-view/block-select-button.js +11 -3
  92. package/build-module/components/list-view/block-select-button.js.map +1 -1
  93. package/build-module/components/list-view/use-clipboard-handler.js +3 -2
  94. package/build-module/components/list-view/use-clipboard-handler.js.map +1 -1
  95. package/build-module/components/rich-text/index.js +47 -28
  96. package/build-module/components/rich-text/index.js.map +1 -1
  97. package/build-module/components/rich-text/use-enter.js +3 -0
  98. package/build-module/components/rich-text/use-enter.js.map +1 -1
  99. package/build-module/components/url-popover/index.js +3 -3
  100. package/build-module/components/url-popover/index.js.map +1 -1
  101. package/build-module/components/writing-flow/use-clipboard-handler.js +3 -2
  102. package/build-module/components/writing-flow/use-clipboard-handler.js.map +1 -1
  103. package/build-module/components/writing-flow/utils.js +22 -7
  104. package/build-module/components/writing-flow/utils.js.map +1 -1
  105. package/build-module/hooks/block-hooks.js +34 -8
  106. package/build-module/hooks/block-hooks.js.map +1 -1
  107. package/build-module/hooks/border.js +7 -5
  108. package/build-module/hooks/border.js.map +1 -1
  109. package/build-module/hooks/use-bindings-attributes.js +172 -49
  110. package/build-module/hooks/use-bindings-attributes.js.map +1 -1
  111. package/build-module/private-apis.js +5 -1
  112. package/build-module/private-apis.js.map +1 -1
  113. package/build-module/store/actions.js +40 -6
  114. package/build-module/store/actions.js.map +1 -1
  115. package/build-module/store/private-actions.js +0 -9
  116. package/build-module/store/private-actions.js.map +1 -1
  117. package/build-module/store/private-selectors.js +0 -6
  118. package/build-module/store/private-selectors.js.map +1 -1
  119. package/build-module/store/reducer.js +1 -16
  120. package/build-module/store/reducer.js.map +1 -1
  121. package/build-style/content-rtl.css +1 -0
  122. package/build-style/content.css +1 -0
  123. package/build-style/default-editor-styles-rtl.css +1 -0
  124. package/build-style/default-editor-styles.css +1 -0
  125. package/build-style/style-rtl.css +70 -14
  126. package/build-style/style.css +70 -14
  127. package/package.json +8 -8
  128. package/src/components/block-actions/index.js +57 -47
  129. package/src/components/block-bindings-toolbar-indicator/index.js +20 -0
  130. package/src/components/block-bindings-toolbar-indicator/style.scss +14 -0
  131. package/src/components/block-edit/context.js +1 -0
  132. package/src/components/block-edit/index.js +5 -1
  133. package/src/components/block-inspector/index.js +7 -5
  134. package/src/components/block-list/use-block-props/index.js +12 -2
  135. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -7
  136. package/src/components/block-preview/index.js +6 -1
  137. package/src/components/block-settings-menu/block-settings-dropdown.js +12 -9
  138. package/src/components/block-toolbar/index.js +14 -4
  139. package/src/components/block-toolbar/style.scss +11 -6
  140. package/src/components/global-styles/border-panel.js +33 -22
  141. package/src/components/global-styles/index.js +5 -1
  142. package/src/components/global-styles/shadow-panel-components.js +92 -23
  143. package/src/components/global-styles/style.scss +33 -10
  144. package/src/components/inspector-controls-tabs/styles-tab.js +2 -2
  145. package/src/components/link-control/link-preview.js +9 -2
  146. package/src/components/link-control/style.scss +9 -0
  147. package/src/components/list-view/block-select-button.js +16 -2
  148. package/src/components/list-view/style.scss +8 -0
  149. package/src/components/list-view/use-clipboard-handler.js +3 -2
  150. package/src/components/rich-text/index.js +75 -52
  151. package/src/components/rich-text/use-enter.js +4 -0
  152. package/src/components/url-popover/index.js +5 -5
  153. package/src/components/url-popover/style.scss +1 -0
  154. package/src/components/writing-flow/use-clipboard-handler.js +3 -2
  155. package/src/components/writing-flow/utils.js +31 -16
  156. package/src/hooks/block-hooks.js +46 -8
  157. package/src/hooks/block-hooks.scss +6 -0
  158. package/src/hooks/border.js +16 -4
  159. package/src/hooks/use-bindings-attributes.js +215 -65
  160. package/src/private-apis.js +4 -0
  161. package/src/store/actions.js +54 -14
  162. package/src/store/private-actions.js +0 -10
  163. package/src/store/private-selectors.js +0 -8
  164. package/src/store/reducer.js +0 -15
  165. package/src/style.scss +1 -0
@@ -22,7 +22,7 @@ import { store as blockEditorStore } from '../../../store';
22
22
  export function useEventHandlers( { clientId, isSelected } ) {
23
23
  const { getBlockRootClientId, getBlockIndex } =
24
24
  useSelect( blockEditorStore );
25
- const { insertDefaultBlock, removeBlock } = useDispatch( blockEditorStore );
25
+ const { insertAfterBlock, removeBlock } = useDispatch( blockEditorStore );
26
26
 
27
27
  return useRefEffect(
28
28
  ( node ) => {
@@ -57,11 +57,7 @@ export function useEventHandlers( { clientId, isSelected } ) {
57
57
  event.preventDefault();
58
58
 
59
59
  if ( keyCode === ENTER ) {
60
- insertDefaultBlock(
61
- {},
62
- getBlockRootClientId( clientId ),
63
- getBlockIndex( clientId ) + 1
64
- );
60
+ insertAfterBlock( clientId );
65
61
  } else {
66
62
  removeBlock( clientId );
67
63
  }
@@ -90,7 +86,7 @@ export function useEventHandlers( { clientId, isSelected } ) {
90
86
  isSelected,
91
87
  getBlockRootClientId,
92
88
  getBlockIndex,
93
- insertDefaultBlock,
89
+ insertAfterBlock,
94
90
  removeBlock,
95
91
  ]
96
92
  );
@@ -54,7 +54,11 @@ export function BlockPreview( {
54
54
  []
55
55
  );
56
56
  const settings = useMemo(
57
- () => ( { ...originalSettings, __unstableIsPreviewMode: true } ),
57
+ () => ( {
58
+ ...originalSettings,
59
+ focusMode: false, // Disable "Spotlight mode".
60
+ __unstableIsPreviewMode: true,
61
+ } ),
58
62
  [ originalSettings ]
59
63
  );
60
64
  const renderedBlocks = useMemo(
@@ -117,6 +121,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) {
117
121
  () => ( {
118
122
  ...originalSettings,
119
123
  styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles.
124
+ focusMode: false, // Disable "Spotlight mode".
120
125
  __unstableIsPreviewMode: true,
121
126
  } ),
122
127
  [ originalSettings ]
@@ -39,8 +39,12 @@ const POPOVER_PROPS = {
39
39
  placement: 'bottom-start',
40
40
  };
41
41
 
42
- function CopyMenuItem( { blocks, onCopy, label } ) {
43
- const ref = useCopyToClipboard( () => serialize( blocks ), onCopy );
42
+ function CopyMenuItem( { clientIds, onCopy, label } ) {
43
+ const { getBlocksByClientId } = useSelect( blockEditorStore );
44
+ const ref = useCopyToClipboard(
45
+ () => serialize( getBlocksByClientId( clientIds ) ),
46
+ onCopy
47
+ );
44
48
  const copyMenuItemLabel = label ? label : __( 'Copy' );
45
49
  return <MenuItem ref={ ref }>{ copyMenuItemLabel }</MenuItem>;
46
50
  }
@@ -239,7 +243,7 @@ export function BlockSettingsDropdown( {
239
243
  { ( {
240
244
  canCopyStyles,
241
245
  canDuplicate,
242
- canInsertDefaultBlock,
246
+ canInsertBlock,
243
247
  canMove,
244
248
  canRemove,
245
249
  onDuplicate,
@@ -249,7 +253,6 @@ export function BlockSettingsDropdown( {
249
253
  onCopy,
250
254
  onPasteStyles,
251
255
  onMoveTo,
252
- blocks,
253
256
  } ) => (
254
257
  <DropdownMenu
255
258
  icon={ moreVertical }
@@ -286,7 +289,7 @@ export function BlockSettingsDropdown( {
286
289
  'core/block-editor/insert-after',
287
290
  event
288
291
  ) &&
289
- canInsertDefaultBlock
292
+ canInsertBlock
290
293
  ) {
291
294
  event.preventDefault();
292
295
  setOpenedBlockSettingsMenu( undefined );
@@ -296,7 +299,7 @@ export function BlockSettingsDropdown( {
296
299
  'core/block-editor/insert-before',
297
300
  event
298
301
  ) &&
299
- canInsertDefaultBlock
302
+ canInsertBlock
300
303
  ) {
301
304
  event.preventDefault();
302
305
  setOpenedBlockSettingsMenu( undefined );
@@ -327,7 +330,7 @@ export function BlockSettingsDropdown( {
327
330
  />
328
331
  ) }
329
332
  <CopyMenuItem
330
- blocks={ blocks }
333
+ clientIds={ clientIds }
331
334
  onCopy={ onCopy }
332
335
  />
333
336
  { canDuplicate && (
@@ -342,7 +345,7 @@ export function BlockSettingsDropdown( {
342
345
  { __( 'Duplicate' ) }
343
346
  </MenuItem>
344
347
  ) }
345
- { canInsertDefaultBlock && (
348
+ { canInsertBlock && (
346
349
  <>
347
350
  <MenuItem
348
351
  onClick={ pipe(
@@ -368,7 +371,7 @@ export function BlockSettingsDropdown( {
368
371
  { canCopyStyles && (
369
372
  <MenuGroup>
370
373
  <CopyMenuItem
371
- blocks={ blocks }
374
+ clientIds={ clientIds }
372
375
  onCopy={ onCopy }
373
376
  label={ __( 'Copy styles' ) }
374
377
  />
@@ -35,6 +35,8 @@ import { store as blockEditorStore } from '../../store';
35
35
  import __unstableBlockNameContext from './block-name-context';
36
36
  import NavigableToolbar from '../navigable-toolbar';
37
37
  import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls';
38
+ import BlockBindingsIndicator from '../block-bindings-toolbar-indicator';
39
+ import { canBindBlock } from '../../hooks/use-bindings-attributes';
38
40
 
39
41
  /**
40
42
  * Renders the block toolbar.
@@ -60,8 +62,10 @@ export function PrivateBlockToolbar( {
60
62
  blockClientIds,
61
63
  isDefaultEditingMode,
62
64
  blockType,
65
+ blockName,
63
66
  shouldShowVisualToolbar,
64
67
  showParentSelector,
68
+ isUsingBindings,
65
69
  } = useSelect( ( select ) => {
66
70
  const {
67
71
  getBlockName,
@@ -71,6 +75,7 @@ export function PrivateBlockToolbar( {
71
75
  isBlockValid,
72
76
  getBlockRootClientId,
73
77
  getBlockEditingMode,
78
+ getBlockAttributes,
74
79
  } = select( blockEditorStore );
75
80
  const selectedBlockClientIds = getSelectedBlockClientIds();
76
81
  const selectedBlockClientId = selectedBlockClientIds[ 0 ];
@@ -81,20 +86,21 @@ export function PrivateBlockToolbar( {
81
86
  const parentBlockType = getBlockType( parentBlockName );
82
87
  const _isDefaultEditingMode =
83
88
  getBlockEditingMode( selectedBlockClientId ) === 'default';
89
+ const _blockName = getBlockName( selectedBlockClientId );
84
90
  const isValid = selectedBlockClientIds.every( ( id ) =>
85
91
  isBlockValid( id )
86
92
  );
87
93
  const isVisual = selectedBlockClientIds.every(
88
94
  ( id ) => getBlockMode( id ) === 'visual'
89
95
  );
96
+ const _isUsingBindings = !! getBlockAttributes( selectedBlockClientId )
97
+ ?.metadata?.bindings;
90
98
  return {
91
99
  blockClientId: selectedBlockClientId,
92
100
  blockClientIds: selectedBlockClientIds,
93
101
  isDefaultEditingMode: _isDefaultEditingMode,
94
- blockType:
95
- selectedBlockClientId &&
96
- getBlockType( getBlockName( selectedBlockClientId ) ),
97
-
102
+ blockName: _blockName,
103
+ blockType: selectedBlockClientId && getBlockType( _blockName ),
98
104
  shouldShowVisualToolbar: isValid && isVisual,
99
105
  rootClientId: blockRootClientId,
100
106
  showParentSelector:
@@ -107,6 +113,7 @@ export function PrivateBlockToolbar( {
107
113
  ) &&
108
114
  selectedBlockClientIds.length === 1 &&
109
115
  _isDefaultEditingMode,
116
+ isUsingBindings: _isUsingBindings,
110
117
  };
111
118
  }, [] );
112
119
 
@@ -165,6 +172,9 @@ export function PrivateBlockToolbar( {
165
172
  { ! isMultiToolbar &&
166
173
  isLargeViewport &&
167
174
  isDefaultEditingMode && <BlockParentSelector /> }
175
+ { isUsingBindings && canBindBlock( blockName ) && (
176
+ <BlockBindingsIndicator />
177
+ ) }
168
178
  { ( shouldShowVisualToolbar || isMultiToolbar ) &&
169
179
  isDefaultEditingMode && (
170
180
  <div
@@ -207,17 +207,18 @@
207
207
  }
208
208
  }
209
209
 
210
- .block-editor-block-mover .block-editor-block-mover__move-button-container {
211
- width: auto;
212
-
213
- @include break-small() {
210
+ .block-editor-block-mover {
211
+ .block-editor-block-mover__move-button-container {
212
+ width: auto;
214
213
  position: relative;
214
+ }
215
215
 
216
- &::before {
216
+ &:not(.is-horizontal) .block-editor-block-mover__move-button-container::before {
217
+ @include break-small() {
217
218
  content: "";
218
219
  height: $border-width;
219
220
  width: 100%;
220
- background: $gray-900;
221
+ background: $gray-200;
221
222
  position: absolute;
222
223
  top: 50%;
223
224
  left: 50%;
@@ -226,6 +227,10 @@
226
227
  transform: translate(-50%, 0);
227
228
  margin-top: -$border-width * 0.5;
228
229
  }
230
+
231
+ @include break-medium {
232
+ background: $gray-900;
233
+ }
229
234
  }
230
235
  }
231
236
 
@@ -21,23 +21,24 @@ import { useColorsPerOrigin } from './hooks';
21
21
  import { getValueFromVariable, TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils';
22
22
  import { overrideOrigins } from '../../store/get-block-settings';
23
23
  import { setImmutably } from '../../utils/object';
24
- import { getBorderPanelLabel } from '../../hooks/border';
25
- import { ShadowPopover } from './shadow-panel-components';
24
+ import { useBorderPanelLabel } from '../../hooks/border';
25
+ import { ShadowPopover, useShadowPresets } from './shadow-panel-components';
26
26
 
27
- function useHasShadowControl( settings ) {
28
- return !! settings?.shadow;
27
+ export function useHasBorderPanel( settings ) {
28
+ const controls = Object.values( useHasBorderPanelControls( settings ) );
29
+ return controls.some( Boolean );
29
30
  }
30
31
 
31
- export function useHasBorderPanel( settings ) {
32
- const controls = [
33
- useHasBorderColorControl( settings ),
34
- useHasBorderRadiusControl( settings ),
35
- useHasBorderStyleControl( settings ),
36
- useHasBorderWidthControl( settings ),
37
- useHasShadowControl( settings ),
38
- ];
32
+ export function useHasBorderPanelControls( settings ) {
33
+ const controls = {
34
+ hasBorderColor: useHasBorderColorControl( settings ),
35
+ hasBorderRadius: useHasBorderRadiusControl( settings ),
36
+ hasBorderStyle: useHasBorderStyleControl( settings ),
37
+ hasBorderWidth: useHasBorderWidthControl( settings ),
38
+ hasShadow: useHasShadowControl( settings ),
39
+ };
39
40
 
40
- return controls.some( Boolean );
41
+ return controls;
41
42
  }
42
43
 
43
44
  function useHasBorderColorControl( settings ) {
@@ -56,6 +57,11 @@ function useHasBorderWidthControl( settings ) {
56
57
  return settings?.border?.width;
57
58
  }
58
59
 
60
+ function useHasShadowControl( settings ) {
61
+ const shadows = useShadowPresets( settings );
62
+ return !! settings?.shadow && shadows.length > 0;
63
+ }
64
+
59
65
  function BorderToolsPanel( {
60
66
  resetAllFilter,
61
67
  onChange,
@@ -215,14 +221,16 @@ export default function BorderPanel( {
215
221
  const showBorderByDefault =
216
222
  defaultControls?.color || defaultControls?.width;
217
223
 
218
- const label = getBorderPanelLabel( {
224
+ const hasBorderControl =
225
+ showBorderColor ||
226
+ showBorderStyle ||
227
+ showBorderWidth ||
228
+ showBorderRadius;
229
+
230
+ const label = useBorderPanelLabel( {
219
231
  blockName: name,
220
232
  hasShadowControl,
221
- hasBorderControl:
222
- showBorderColor ||
223
- showBorderStyle ||
224
- showBorderWidth ||
225
- showBorderRadius,
233
+ hasBorderControl,
226
234
  } );
227
235
 
228
236
  return (
@@ -280,9 +288,12 @@ export default function BorderPanel( {
280
288
  isShownByDefault={ defaultControls.shadow }
281
289
  panelId={ panelId }
282
290
  >
283
- <BaseControl.VisualLabel as="legend">
284
- { __( 'Shadow' ) }
285
- </BaseControl.VisualLabel>
291
+ { hasBorderControl ? (
292
+ <BaseControl.VisualLabel as="legend">
293
+ { __( 'Shadow' ) }
294
+ </BaseControl.VisualLabel>
295
+ ) : null }
296
+
286
297
  <ItemGroup isBordered isSeparated>
287
298
  <ShadowPopover
288
299
  shadow={ shadow }
@@ -19,7 +19,11 @@ export {
19
19
  default as DimensionsPanel,
20
20
  useHasDimensionsPanel,
21
21
  } from './dimensions-panel';
22
- export { default as BorderPanel, useHasBorderPanel } from './border-panel';
22
+ export {
23
+ default as BorderPanel,
24
+ useHasBorderPanel,
25
+ useHasBorderPanelControls,
26
+ } from './border-panel';
23
27
  export { default as ColorPanel, useHasColorPanel } from './color-panel';
24
28
  export { default as FiltersPanel, useHasFiltersPanel } from './filters-panel';
25
29
  export {
@@ -5,28 +5,36 @@ import { __ } from '@wordpress/i18n';
5
5
  import {
6
6
  __experimentalVStack as VStack,
7
7
  __experimentalHeading as Heading,
8
- __experimentalGrid as Grid,
9
8
  __experimentalHStack as HStack,
10
9
  __experimentalDropdownContentWrapper as DropdownContentWrapper,
11
10
  Button,
12
11
  FlexItem,
13
12
  Dropdown,
13
+ privateApis as componentsPrivateApis,
14
14
  } from '@wordpress/components';
15
+ import { useMemo } from '@wordpress/element';
15
16
  import { shadow as shadowIcon, Icon, check } from '@wordpress/icons';
17
+
16
18
  /**
17
19
  * External dependencies
18
20
  */
19
21
  import classNames from 'classnames';
20
22
 
21
- export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
22
- const defaultShadows = settings?.shadow?.presets?.default || [];
23
- const themeShadows = settings?.shadow?.presets?.theme || [];
24
- const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
23
+ /**
24
+ * Internal dependencies
25
+ */
26
+ import { unlock } from '../../lock-unlock';
25
27
 
26
- const shadows = [
27
- ...( defaultPresetsEnabled ? defaultShadows : [] ),
28
- ...themeShadows,
29
- ];
28
+ /**
29
+ * Shared reference to an empty array for cases where it is important to avoid
30
+ * returning a new array reference on every invocation.
31
+ *
32
+ * @type {Array}
33
+ */
34
+ const EMPTY_ARRAY = [];
35
+
36
+ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
37
+ const shadows = useShadowPresets( settings );
30
38
 
31
39
  return (
32
40
  <div className="block-editor-global-styles__shadow-popover-container">
@@ -37,42 +45,76 @@ export function ShadowPopoverContainer( { shadow, onShadowChange, settings } ) {
37
45
  activeShadow={ shadow }
38
46
  onSelect={ onShadowChange }
39
47
  />
48
+ <div className="block-editor-global-styles__clear-shadow">
49
+ <Button
50
+ variant="tertiary"
51
+ onClick={ () => onShadowChange( undefined ) }
52
+ >
53
+ { __( 'Clear' ) }
54
+ </Button>
55
+ </div>
40
56
  </VStack>
41
57
  </div>
42
58
  );
43
59
  }
44
60
 
45
61
  export function ShadowPresets( { presets, activeShadow, onSelect } ) {
62
+ const { CompositeV2: Composite, useCompositeStoreV2: useCompositeStore } =
63
+ unlock( componentsPrivateApis );
64
+ const compositeStore = useCompositeStore();
46
65
  return ! presets ? null : (
47
- <Grid columns={ 6 } gap={ 0 } align="center" justify="center">
66
+ <Composite
67
+ store={ compositeStore }
68
+ role="listbox"
69
+ className="block-editor-global-styles__shadow__list"
70
+ aria-label={ __( 'Drop shadows' ) }
71
+ >
48
72
  { presets.map( ( { name, slug, shadow } ) => (
49
73
  <ShadowIndicator
50
74
  key={ slug }
51
75
  label={ name }
52
76
  isActive={ shadow === activeShadow }
77
+ type={ slug === 'unset' ? 'unset' : 'preset' }
53
78
  onSelect={ () =>
54
79
  onSelect( shadow === activeShadow ? undefined : shadow )
55
80
  }
56
81
  shadow={ shadow }
57
82
  />
58
83
  ) ) }
59
- </Grid>
84
+ </Composite>
60
85
  );
61
86
  }
62
87
 
63
- export function ShadowIndicator( { label, isActive, onSelect, shadow } ) {
88
+ export function ShadowIndicator( { type, label, isActive, onSelect, shadow } ) {
89
+ const { CompositeItemV2: CompositeItem } = unlock( componentsPrivateApis );
64
90
  return (
65
- <div className="block-editor-global-styles__shadow-indicator-wrapper">
66
- <Button
67
- className="block-editor-global-styles__shadow-indicator"
68
- onClick={ onSelect }
69
- label={ label }
70
- style={ { boxShadow: shadow } }
71
- showTooltip
72
- >
73
- { isActive && <Icon icon={ check } /> }
74
- </Button>
75
- </div>
91
+ <CompositeItem
92
+ role="option"
93
+ aria-label={ label }
94
+ aria-selected={ isActive }
95
+ className={ classNames(
96
+ 'block-editor-global-styles__shadow__item',
97
+ {
98
+ 'is-active': isActive,
99
+ }
100
+ ) }
101
+ render={
102
+ <Button
103
+ className={ classNames(
104
+ 'block-editor-global-styles__shadow-indicator',
105
+ {
106
+ unset: type === 'unset',
107
+ }
108
+ ) }
109
+ onClick={ onSelect }
110
+ label={ label }
111
+ style={ { boxShadow: shadow } }
112
+ showTooltip
113
+ >
114
+ { isActive && <Icon icon={ check } /> }
115
+ </Button>
116
+ }
117
+ />
76
118
  );
77
119
  }
78
120
 
@@ -123,3 +165,30 @@ function renderShadowToggle() {
123
165
  );
124
166
  };
125
167
  }
168
+
169
+ export function useShadowPresets( settings ) {
170
+ return useMemo( () => {
171
+ if ( ! settings?.shadow ) {
172
+ return EMPTY_ARRAY;
173
+ }
174
+
175
+ const defaultPresetsEnabled = settings?.shadow?.defaultPresets;
176
+ const { default: defaultShadows, theme: themeShadows } =
177
+ settings?.shadow?.presets ?? {};
178
+ const unsetShadow = {
179
+ name: __( 'Unset' ),
180
+ slug: 'unset',
181
+ shadow: 'none',
182
+ };
183
+
184
+ const shadowPresets = [
185
+ ...( ( defaultPresetsEnabled && defaultShadows ) || EMPTY_ARRAY ),
186
+ ...( themeShadows || EMPTY_ARRAY ),
187
+ ];
188
+ if ( shadowPresets.length ) {
189
+ shadowPresets.unshift( unsetShadow );
190
+ }
191
+
192
+ return shadowPresets;
193
+ }, [ settings ] );
194
+ }
@@ -2,10 +2,24 @@
2
2
  fill: currentColor;
3
3
  }
4
4
 
5
+ // @todo: Ideally, popover, swatch size, and gap values should be CSS variables
6
+ // to apply precise grid layouts.
7
+ // https://github.com/WordPress/gutenberg/blob/954ecae571abbddc113d3a4bd8e1a72230180554/packages/block-editor/src/components/duotone-control/style.scss#L3-L9
5
8
  .block-editor-global-styles__shadow-popover-container {
6
9
  width: 230px;
7
10
  }
8
11
 
12
+ .block-editor-global-styles__shadow__list {
13
+ display: flex;
14
+ gap: 12px;
15
+ flex-wrap: wrap;
16
+ padding-bottom: $grid-unit-10;
17
+ }
18
+
19
+ .block-editor-global-styles__clear-shadow {
20
+ text-align: right;
21
+ }
22
+
9
23
  .block-editor-global-styles-filters-panel__dropdown,
10
24
  .block-editor-global-styles__shadow-dropdown {
11
25
  display: block;
@@ -21,14 +35,6 @@
21
35
  }
22
36
  }
23
37
 
24
- // wrapper to clip the shadow beyond 6px
25
- .block-editor-global-styles__shadow-indicator-wrapper {
26
- padding: $grid-unit-15 * 0.5;
27
- display: flex;
28
- align-items: center;
29
- justify-content: center;
30
- }
31
-
32
38
  // These styles are similar to the color palette.
33
39
  .block-editor-global-styles__shadow-indicator {
34
40
  color: $gray-800;
@@ -37,8 +43,25 @@
37
43
  cursor: pointer;
38
44
  padding: 0;
39
45
 
40
- height: $button-size-small;
41
- width: $button-size-small;
46
+ height: $button-size-small + 2 * $border-width;
47
+ width: $button-size-small + 2 * $border-width;
48
+ box-sizing: border-box;
49
+
50
+ transform: scale(1);
51
+ transition: transform 0.1s ease;
52
+ will-change: transform;
53
+
54
+ &:focus {
55
+ border: #{ $border-width * 2 } solid $gray-700;
56
+ }
57
+
58
+ &:hover {
59
+ transform: scale(1.2);
60
+ }
61
+
62
+ &.unset {
63
+ background: linear-gradient(-45deg, transparent 48%, $gray-300 48%, $gray-300 52%, transparent 52%);
64
+ }
42
65
  }
43
66
 
44
67
  .block-editor-global-styles-advanced-panel__custom-css-input textarea {
@@ -11,10 +11,10 @@ import { __ } from '@wordpress/i18n';
11
11
  import BlockStyles from '../block-styles';
12
12
  import DefaultStylePicker from '../default-style-picker';
13
13
  import InspectorControls from '../inspector-controls';
14
- import { getBorderPanelLabel } from '../../hooks/border';
14
+ import { useBorderPanelLabel } from '../../hooks/border';
15
15
 
16
16
  const StylesTab = ( { blockName, clientId, hasBlockStyles } ) => {
17
- const borderPanelLabel = getBorderPanelLabel( { blockName } );
17
+ const borderPanelLabel = useBorderPanelLabel( { blockName } );
18
18
 
19
19
  return (
20
20
  <>
@@ -16,8 +16,9 @@ import { useCopyToClipboard } from '@wordpress/compose';
16
16
  import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url';
17
17
  import { Icon, globe, info, linkOff, edit, copySmall } from '@wordpress/icons';
18
18
  import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
19
- import { useDispatch } from '@wordpress/data';
19
+ import { useDispatch, useSelect } from '@wordpress/data';
20
20
  import { store as noticesStore } from '@wordpress/notices';
21
+ import { store as preferencesStore } from '@wordpress/preferences';
21
22
 
22
23
  /**
23
24
  * Internal dependencies
@@ -33,6 +34,12 @@ export default function LinkPreview( {
33
34
  hasUnlinkControl = false,
34
35
  onRemove,
35
36
  } ) {
37
+ const showIconLabels = useSelect(
38
+ ( select ) =>
39
+ select( preferencesStore ).get( 'core', 'showIconLabels' ),
40
+ []
41
+ );
42
+
36
43
  // Avoid fetching if rich previews are not desired.
37
44
  const showRichPreviews = hasRichPreviews ? value?.url : null;
38
45
 
@@ -139,7 +146,7 @@ export default function LinkPreview( {
139
146
  label={ sprintf(
140
147
  // Translators: %s is a placeholder for the link URL and an optional colon, (if a Link URL is present).
141
148
  __( 'Copy link%s' ), // Ends up looking like "Copy link: https://example.com".
142
- isEmptyURL ? '' : ': ' + value.url
149
+ isEmptyURL || showIconLabels ? '' : ': ' + value.url
143
150
  ) }
144
151
  ref={ ref }
145
152
  disabled={ isEmptyURL }
@@ -34,6 +34,15 @@ $block-editor-link-control-number-of-actions: 1;
34
34
  content: attr(aria-label);
35
35
  }
36
36
  }
37
+
38
+ .block-editor-link-control__search-item-top {
39
+ gap: $grid-unit-10;
40
+
41
+ .components-button.has-icon {
42
+ min-width: inherit;
43
+ width: min-content;
44
+ }
45
+ }
37
46
  }
38
47
  }
39
48