@wordpress/block-editor 12.22.0 → 12.23.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 (273) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +4 -0
  3. package/build/components/block-list/block.js +11 -3
  4. package/build/components/block-list/block.js.map +1 -1
  5. package/build/components/block-mover/button.js +4 -1
  6. package/build/components/block-mover/button.js.map +1 -1
  7. package/build/components/block-mover/index.js +5 -1
  8. package/build/components/block-mover/index.js.map +1 -1
  9. package/build/components/block-patterns-list/index.js +4 -1
  10. package/build/components/block-patterns-list/index.js.map +1 -1
  11. package/build/components/block-settings-menu/block-settings-dropdown.js +7 -3
  12. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  13. package/build/components/block-switcher/index.js +4 -3
  14. package/build/components/block-switcher/index.js.map +1 -1
  15. package/build/components/block-toolbar/index.js +5 -4
  16. package/build/components/block-toolbar/index.js.map +1 -1
  17. package/build/components/block-toolbar/shuffle.js +18 -9
  18. package/build/components/block-toolbar/shuffle.js.map +1 -1
  19. package/build/components/block-tools/block-selection-button.js +48 -8
  20. package/build/components/block-tools/block-selection-button.js.map +1 -1
  21. package/build/components/block-tools/index.js +14 -2
  22. package/build/components/block-tools/index.js.map +1 -1
  23. package/build/components/global-styles/advanced-panel.js +9 -2
  24. package/build/components/global-styles/advanced-panel.js.map +1 -1
  25. package/build/components/global-styles/background-panel.js +444 -0
  26. package/build/components/global-styles/background-panel.js.map +1 -0
  27. package/build/components/global-styles/color-panel.js +2 -1
  28. package/build/components/global-styles/color-panel.js.map +1 -1
  29. package/build/components/global-styles/get-global-styles-changes.js +3 -0
  30. package/build/components/global-styles/get-global-styles-changes.js.map +1 -1
  31. package/build/components/global-styles/hooks.js +1 -1
  32. package/build/components/global-styles/hooks.js.map +1 -1
  33. package/build/components/global-styles/index.js +13 -0
  34. package/build/components/global-styles/index.js.map +1 -1
  35. package/build/components/global-styles/use-global-styles-output.js +15 -14
  36. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  37. package/build/components/global-styles/utils.js +2 -1
  38. package/build/components/global-styles/utils.js.map +1 -1
  39. package/build/components/iframe/index.js +9 -4
  40. package/build/components/iframe/index.js.map +1 -1
  41. package/build/components/inserter/block-patterns-tab/index.js.map +1 -1
  42. package/build/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +5 -0
  43. package/build/components/inserter/block-patterns-tab/pattern-category-preview-panel.js.map +1 -1
  44. package/build/components/inserter/library.js +2 -0
  45. package/build/components/inserter/library.js.map +1 -1
  46. package/build/components/inserter/menu.js +8 -2
  47. package/build/components/inserter/menu.js.map +1 -1
  48. package/build/components/inserter/search-items.js +36 -15
  49. package/build/components/inserter/search-items.js.map +1 -1
  50. package/build/components/keyboard-shortcuts/index.js +11 -0
  51. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  52. package/build/components/list-view/block-select-button.js +16 -0
  53. package/build/components/list-view/block-select-button.js.map +1 -1
  54. package/build/components/list-view/block.js +1 -1
  55. package/build/components/list-view/block.js.map +1 -1
  56. package/build/components/list-view/index.js +17 -2
  57. package/build/components/list-view/index.js.map +1 -1
  58. package/build/components/list-view/use-list-view-collapse-items.js +47 -0
  59. package/build/components/list-view/use-list-view-collapse-items.js.map +1 -0
  60. package/build/components/rich-text/index.js +14 -11
  61. package/build/components/rich-text/index.js.map +1 -1
  62. package/build/components/rich-text/index.native.js +17 -11
  63. package/build/components/rich-text/index.native.js.map +1 -1
  64. package/build/components/rich-text/native/get-format-colors.native.js +1 -1
  65. package/build/components/rich-text/native/get-format-colors.native.js.map +1 -1
  66. package/build/components/rich-text/native/index.native.js +2 -2
  67. package/build/components/rich-text/native/index.native.js.map +1 -1
  68. package/build/components/rich-text/with-deprecations.js +0 -3
  69. package/build/components/rich-text/with-deprecations.js.map +1 -1
  70. package/build/components/url-popover/image-url-input-ui.js +50 -36
  71. package/build/components/url-popover/image-url-input-ui.js.map +1 -1
  72. package/build/components/use-block-display-information/index.js +4 -6
  73. package/build/components/use-block-display-information/index.js.map +1 -1
  74. package/build/hooks/anchor.js +2 -2
  75. package/build/hooks/anchor.js.map +1 -1
  76. package/build/hooks/background.js +70 -424
  77. package/build/hooks/background.js.map +1 -1
  78. package/build/hooks/index.js +7 -0
  79. package/build/hooks/index.js.map +1 -1
  80. package/build/hooks/use-zoom-out.js +47 -0
  81. package/build/hooks/use-zoom-out.js.map +1 -0
  82. package/build/index.js +7 -0
  83. package/build/index.js.map +1 -1
  84. package/build/private-apis.js +6 -1
  85. package/build/private-apis.js.map +1 -1
  86. package/build/private-apis.native.js +3 -1
  87. package/build/private-apis.native.js.map +1 -1
  88. package/build/store/private-actions.js +13 -0
  89. package/build/store/private-actions.js.map +1 -1
  90. package/build/store/private-keys.js +2 -1
  91. package/build/store/private-keys.js.map +1 -1
  92. package/build/store/private-selectors.js +24 -3
  93. package/build/store/private-selectors.js.map +1 -1
  94. package/build/store/reducer.js +22 -0
  95. package/build/store/reducer.js.map +1 -1
  96. package/build/store/selectors.js +34 -32
  97. package/build/store/selectors.js.map +1 -1
  98. package/build/store/utils.js +7 -1
  99. package/build/store/utils.js.map +1 -1
  100. package/build/utils/transform-styles/index.js +2 -1
  101. package/build/utils/transform-styles/index.js.map +1 -1
  102. package/build-module/components/block-list/block.js +11 -3
  103. package/build-module/components/block-list/block.js.map +1 -1
  104. package/build-module/components/block-mover/button.js +4 -1
  105. package/build-module/components/block-mover/button.js.map +1 -1
  106. package/build-module/components/block-mover/index.js +5 -1
  107. package/build-module/components/block-mover/index.js.map +1 -1
  108. package/build-module/components/block-patterns-list/index.js +4 -1
  109. package/build-module/components/block-patterns-list/index.js.map +1 -1
  110. package/build-module/components/block-settings-menu/block-settings-dropdown.js +7 -3
  111. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  112. package/build-module/components/block-switcher/index.js +4 -3
  113. package/build-module/components/block-switcher/index.js.map +1 -1
  114. package/build-module/components/block-toolbar/index.js +5 -4
  115. package/build-module/components/block-toolbar/index.js.map +1 -1
  116. package/build-module/components/block-toolbar/shuffle.js +18 -9
  117. package/build-module/components/block-toolbar/shuffle.js.map +1 -1
  118. package/build-module/components/block-tools/block-selection-button.js +50 -10
  119. package/build-module/components/block-tools/block-selection-button.js.map +1 -1
  120. package/build-module/components/block-tools/index.js +14 -2
  121. package/build-module/components/block-tools/index.js.map +1 -1
  122. package/build-module/components/global-styles/advanced-panel.js +9 -2
  123. package/build-module/components/global-styles/advanced-panel.js.map +1 -1
  124. package/build-module/components/global-styles/background-panel.js +430 -0
  125. package/build-module/components/global-styles/background-panel.js.map +1 -0
  126. package/build-module/components/global-styles/color-panel.js +2 -1
  127. package/build-module/components/global-styles/color-panel.js.map +1 -1
  128. package/build-module/components/global-styles/get-global-styles-changes.js +3 -0
  129. package/build-module/components/global-styles/get-global-styles-changes.js.map +1 -1
  130. package/build-module/components/global-styles/hooks.js +1 -1
  131. package/build-module/components/global-styles/hooks.js.map +1 -1
  132. package/build-module/components/global-styles/index.js +1 -0
  133. package/build-module/components/global-styles/index.js.map +1 -1
  134. package/build-module/components/global-styles/use-global-styles-output.js +16 -15
  135. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  136. package/build-module/components/global-styles/utils.js +1 -0
  137. package/build-module/components/global-styles/utils.js.map +1 -1
  138. package/build-module/components/iframe/index.js +9 -4
  139. package/build-module/components/iframe/index.js.map +1 -1
  140. package/build-module/components/inserter/block-patterns-tab/index.js.map +1 -1
  141. package/build-module/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +5 -0
  142. package/build-module/components/inserter/block-patterns-tab/pattern-category-preview-panel.js.map +1 -1
  143. package/build-module/components/inserter/library.js +2 -0
  144. package/build-module/components/inserter/library.js.map +1 -1
  145. package/build-module/components/inserter/menu.js +8 -2
  146. package/build-module/components/inserter/menu.js.map +1 -1
  147. package/build-module/components/inserter/search-items.js +33 -15
  148. package/build-module/components/inserter/search-items.js.map +1 -1
  149. package/build-module/components/keyboard-shortcuts/index.js +11 -0
  150. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  151. package/build-module/components/list-view/block-select-button.js +16 -0
  152. package/build-module/components/list-view/block-select-button.js.map +1 -1
  153. package/build-module/components/list-view/block.js +1 -1
  154. package/build-module/components/list-view/block.js.map +1 -1
  155. package/build-module/components/list-view/index.js +17 -2
  156. package/build-module/components/list-view/index.js.map +1 -1
  157. package/build-module/components/list-view/use-list-view-collapse-items.js +40 -0
  158. package/build-module/components/list-view/use-list-view-collapse-items.js.map +1 -0
  159. package/build-module/components/rich-text/index.js +15 -12
  160. package/build-module/components/rich-text/index.js.map +1 -1
  161. package/build-module/components/rich-text/index.native.js +16 -11
  162. package/build-module/components/rich-text/index.native.js.map +1 -1
  163. package/build-module/components/rich-text/native/get-format-colors.native.js +1 -1
  164. package/build-module/components/rich-text/native/get-format-colors.native.js.map +1 -1
  165. package/build-module/components/rich-text/native/index.native.js +2 -2
  166. package/build-module/components/rich-text/native/index.native.js.map +1 -1
  167. package/build-module/components/rich-text/with-deprecations.js +0 -3
  168. package/build-module/components/rich-text/with-deprecations.js.map +1 -1
  169. package/build-module/components/url-popover/image-url-input-ui.js +50 -36
  170. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  171. package/build-module/components/use-block-display-information/index.js +5 -7
  172. package/build-module/components/use-block-display-information/index.js.map +1 -1
  173. package/build-module/hooks/anchor.js +2 -2
  174. package/build-module/hooks/anchor.js.map +1 -1
  175. package/build-module/hooks/background.js +67 -419
  176. package/build-module/hooks/background.js.map +1 -1
  177. package/build-module/hooks/index.js +1 -0
  178. package/build-module/hooks/index.js.map +1 -1
  179. package/build-module/hooks/use-zoom-out.js +41 -0
  180. package/build-module/hooks/use-zoom-out.js.map +1 -0
  181. package/build-module/index.js +1 -1
  182. package/build-module/index.js.map +1 -1
  183. package/build-module/private-apis.js +7 -2
  184. package/build-module/private-apis.js.map +1 -1
  185. package/build-module/private-apis.native.js +3 -1
  186. package/build-module/private-apis.native.js.map +1 -1
  187. package/build-module/store/private-actions.js +12 -0
  188. package/build-module/store/private-actions.js.map +1 -1
  189. package/build-module/store/private-keys.js +1 -0
  190. package/build-module/store/private-keys.js.map +1 -1
  191. package/build-module/store/private-selectors.js +22 -4
  192. package/build-module/store/private-selectors.js.map +1 -1
  193. package/build-module/store/reducer.js +21 -0
  194. package/build-module/store/reducer.js.map +1 -1
  195. package/build-module/store/selectors.js +35 -33
  196. package/build-module/store/selectors.js.map +1 -1
  197. package/build-module/store/utils.js +6 -1
  198. package/build-module/store/utils.js.map +1 -1
  199. package/build-module/utils/transform-styles/index.js +2 -1
  200. package/build-module/utils/transform-styles/index.js.map +1 -1
  201. package/build-style/content-rtl.css +4 -1
  202. package/build-style/content.css +4 -1
  203. package/build-style/style-rtl.css +84 -79
  204. package/build-style/style.css +84 -79
  205. package/package.json +31 -31
  206. package/src/components/block-list/block.js +19 -3
  207. package/src/components/block-mover/button.js +4 -1
  208. package/src/components/block-mover/index.js +8 -1
  209. package/src/components/block-patterns-list/index.js +22 -17
  210. package/src/components/block-preview/style.scss +28 -0
  211. package/src/components/block-settings-menu/block-settings-dropdown.js +8 -2
  212. package/src/components/block-switcher/index.js +5 -3
  213. package/src/components/block-switcher/style.scss +1 -1
  214. package/src/components/block-toolbar/index.js +22 -19
  215. package/src/components/block-toolbar/shuffle.js +19 -13
  216. package/src/components/block-toolbar/style.scss +1 -1
  217. package/src/components/block-tools/block-selection-button.js +66 -9
  218. package/src/components/block-tools/index.js +18 -1
  219. package/src/components/button-block-appender/content.scss +5 -1
  220. package/src/components/default-block-appender/content.scss +2 -2
  221. package/src/components/global-styles/advanced-panel.js +8 -2
  222. package/src/components/global-styles/background-panel.js +591 -0
  223. package/src/components/global-styles/color-panel.js +2 -1
  224. package/src/components/global-styles/get-global-styles-changes.js +3 -0
  225. package/src/components/global-styles/hooks.js +1 -0
  226. package/src/components/global-styles/index.js +4 -0
  227. package/src/components/global-styles/style.scss +78 -1
  228. package/src/{hooks/test/background.js → components/global-styles/test/background-panel.js} +36 -1
  229. package/src/components/global-styles/test/get-global-styles-changes.js +22 -3
  230. package/src/components/global-styles/test/use-global-styles-output.js +9 -9
  231. package/src/components/global-styles/use-global-styles-output.js +27 -16
  232. package/src/components/global-styles/utils.js +1 -0
  233. package/src/components/iframe/index.js +19 -9
  234. package/src/components/inserter/block-patterns-tab/index.js +1 -0
  235. package/src/components/inserter/block-patterns-tab/pattern-category-preview-panel.js +5 -0
  236. package/src/components/inserter/library.js +4 -0
  237. package/src/components/inserter/menu.js +8 -1
  238. package/src/components/inserter/search-items.js +37 -15
  239. package/src/components/inserter/style.scss +6 -12
  240. package/src/components/keyboard-shortcuts/index.js +11 -0
  241. package/src/components/list-view/block-select-button.js +13 -1
  242. package/src/components/list-view/block.js +1 -1
  243. package/src/components/list-view/index.js +18 -1
  244. package/src/components/list-view/style.scss +4 -4
  245. package/src/components/list-view/use-list-view-collapse-items.js +33 -0
  246. package/src/components/rich-text/index.js +30 -13
  247. package/src/components/rich-text/index.native.js +14 -11
  248. package/src/components/rich-text/native/get-format-colors.native.js +1 -1
  249. package/src/components/rich-text/native/index.native.js +2 -2
  250. package/src/components/rich-text/with-deprecations.js +0 -3
  251. package/src/components/url-popover/image-url-input-ui.js +68 -51
  252. package/src/components/use-block-display-information/index.js +8 -10
  253. package/src/hooks/anchor.js +11 -9
  254. package/src/hooks/background.js +77 -538
  255. package/src/hooks/index.js +1 -0
  256. package/src/hooks/use-zoom-out.js +36 -0
  257. package/src/index.js +1 -0
  258. package/src/private-apis.js +13 -1
  259. package/src/private-apis.native.js +2 -0
  260. package/src/store/private-actions.js +12 -0
  261. package/src/store/private-keys.js +1 -0
  262. package/src/store/private-selectors.js +54 -27
  263. package/src/store/reducer.js +22 -0
  264. package/src/store/selectors.js +195 -180
  265. package/src/store/test/private-actions.js +10 -0
  266. package/src/store/test/private-selectors.js +13 -0
  267. package/src/store/test/reducer.js +26 -0
  268. package/src/store/test/selectors.js +90 -199
  269. package/src/store/utils.js +13 -0
  270. package/src/style.scss +0 -2
  271. package/src/utils/transform-styles/index.js +2 -1
  272. package/src/hooks/anchor.scss +0 -4
  273. package/src/hooks/background.scss +0 -75
@@ -112,7 +112,10 @@ function BlockListBlock( {
112
112
  ...context
113
113
  } = useContext( PrivateBlockContext );
114
114
  const { removeBlock } = useDispatch( blockEditorStore );
115
- const onRemove = useCallback( () => removeBlock( clientId ), [ clientId ] );
115
+ const onRemove = useCallback(
116
+ () => removeBlock( clientId ),
117
+ [ clientId, removeBlock ]
118
+ );
116
119
 
117
120
  const parentLayout = useLayout() || {};
118
121
 
@@ -222,6 +225,11 @@ function BlockListBlock( {
222
225
  // We set a new context with the adjusted and filtered wrapperProps (through
223
226
  // `editor.BlockListBlock`), which the `BlockListBlockProvider` did not have
224
227
  // access to.
228
+ // Note that the context value doesn't have to be memoized in this case
229
+ // because when it changes, this component will be re-rendered anyway, and
230
+ // none of the consumers (BlockListBlock and useBlockProps) are memoized or
231
+ // "pure". This is different from the public BlockEditContext, where
232
+ // consumers might be memoized or "pure".
225
233
  return (
226
234
  <PrivateBlockContext.Provider
227
235
  value={ {
@@ -451,8 +459,16 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
451
459
  }
452
460
 
453
461
  moveFirstItemUp( rootClientId );
454
- } else {
455
- removeBlock( clientId );
462
+ } else if (
463
+ getBlockName( clientId ) !== getDefaultBlockName()
464
+ ) {
465
+ const replacement = switchToBlockType(
466
+ getBlock( clientId ),
467
+ getDefaultBlockName()
468
+ );
469
+ if ( replacement && replacement.length ) {
470
+ replaceBlocks( clientId, replacement );
471
+ }
456
472
  }
457
473
  }
458
474
  },
@@ -65,6 +65,7 @@ const BlockMoverButton = forwardRef(
65
65
  ? clientIds
66
66
  : [ clientIds ];
67
67
  const blocksCount = normalizedClientIds.length;
68
+ const { disabled } = props;
68
69
 
69
70
  const {
70
71
  blockType,
@@ -98,7 +99,9 @@ const BlockMoverButton = forwardRef(
98
99
 
99
100
  return {
100
101
  blockType: block ? getBlockType( block.name ) : null,
101
- isDisabled: direction === 'up' ? isFirstBlock : isLastBlock,
102
+ isDisabled:
103
+ disabled ||
104
+ ( direction === 'up' ? isFirstBlock : isLastBlock ),
102
105
  rootClientId: blockRootClientId,
103
106
  firstIndex: firstBlockIndex,
104
107
  isFirst: isFirstBlock,
@@ -19,7 +19,12 @@ import BlockDraggable from '../block-draggable';
19
19
  import { BlockMoverUpButton, BlockMoverDownButton } from './button';
20
20
  import { store as blockEditorStore } from '../../store';
21
21
 
22
- function BlockMover( { clientIds, hideDragHandle } ) {
22
+ function BlockMover( {
23
+ clientIds,
24
+ hideDragHandle,
25
+ isBlockMoverUpButtonDisabled,
26
+ isBlockMoverDownButtonDisabled,
27
+ } ) {
23
28
  const { canMove, rootClientId, isFirst, isLast, orientation } = useSelect(
24
29
  ( select ) => {
25
30
  const {
@@ -83,6 +88,7 @@ function BlockMover( { clientIds, hideDragHandle } ) {
83
88
  <ToolbarItem>
84
89
  { ( itemProps ) => (
85
90
  <BlockMoverUpButton
91
+ disabled={ isBlockMoverUpButtonDisabled }
86
92
  clientIds={ clientIds }
87
93
  { ...itemProps }
88
94
  />
@@ -91,6 +97,7 @@ function BlockMover( { clientIds, hideDragHandle } ) {
91
97
  <ToolbarItem>
92
98
  { ( itemProps ) => (
93
99
  <BlockMoverDownButton
100
+ disabled={ isBlockMoverDownButtonDisabled }
94
101
  clientIds={ clientIds }
95
102
  { ...itemProps }
96
103
  />
@@ -45,6 +45,7 @@ function BlockPattern( {
45
45
  pattern,
46
46
  onClick,
47
47
  onHover,
48
+ showTitle = true,
48
49
  showTooltip,
49
50
  } ) {
50
51
  const [ isDragging, setIsDragging ] = useState( false );
@@ -122,25 +123,27 @@ function BlockPattern( {
122
123
  viewportWidth={ viewportWidth }
123
124
  />
124
125
 
125
- <HStack className="block-editor-patterns__pattern-details">
126
- { pattern.type ===
127
- INSERTER_PATTERN_TYPES.user &&
128
- ! pattern.syncStatus && (
129
- <div className="block-editor-patterns__pattern-icon-wrapper">
130
- <Icon
131
- className="block-editor-patterns__pattern-icon"
132
- icon={ symbol }
133
- />
126
+ { showTitle && (
127
+ <HStack className="block-editor-patterns__pattern-details">
128
+ { pattern.type ===
129
+ INSERTER_PATTERN_TYPES.user &&
130
+ ! pattern.syncStatus && (
131
+ <div className="block-editor-patterns__pattern-icon-wrapper">
132
+ <Icon
133
+ className="block-editor-patterns__pattern-icon"
134
+ icon={ symbol }
135
+ />
136
+ </div>
137
+ ) }
138
+ { ( ! showTooltip ||
139
+ pattern.type ===
140
+ INSERTER_PATTERN_TYPES.user ) && (
141
+ <div className="block-editor-block-patterns-list__item-title">
142
+ { pattern.title }
134
143
  </div>
135
144
  ) }
136
- { ( ! showTooltip ||
137
- pattern.type ===
138
- INSERTER_PATTERN_TYPES.user ) && (
139
- <div className="block-editor-block-patterns-list__item-title">
140
- { pattern.title }
141
- </div>
142
- ) }
143
- </HStack>
145
+ </HStack>
146
+ ) }
144
147
 
145
148
  { !! pattern.description && (
146
149
  <VisuallyHidden id={ descriptionId }>
@@ -170,6 +173,7 @@ function BlockPatternsList(
170
173
  onClickPattern,
171
174
  orientation,
172
175
  label = __( 'Block patterns' ),
176
+ showTitle = true,
173
177
  showTitlesAsTooltip,
174
178
  pagingProps,
175
179
  },
@@ -203,6 +207,7 @@ function BlockPatternsList(
203
207
  onClick={ onClickPattern }
204
208
  onHover={ onHover }
205
209
  isDraggable={ isDraggable }
210
+ showTitle={ showTitle }
206
211
  showTooltip={ showTitlesAsTooltip }
207
212
  />
208
213
  ) : (
@@ -48,3 +48,31 @@
48
48
  bottom: 0;
49
49
  z-index: 1;
50
50
  }
51
+
52
+ // Restrict these shadows to the context of the inspector.
53
+ .interface-interface-skeleton__sidebar {
54
+ .block-editor-block-patterns-list__list-item {
55
+ .block-editor-block-preview__container {
56
+ box-shadow: 0 0 $border-width rgba($black, 0.1);
57
+ }
58
+ &:hover {
59
+ .block-editor-block-preview__container {
60
+ box-shadow: 0 0 0 2px $gray-900;
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ // Restrict these shadows to the context of the inserter.
67
+ .editor-inserter-sidebar {
68
+ .block-editor-block-patterns-list__list-item {
69
+ .block-editor-block-preview__container {
70
+ box-shadow: 0 15px 25px rgb(0 0 0 / 7%);
71
+ }
72
+ &:hover {
73
+ .block-editor-block-preview__container {
74
+ box-shadow: 0 0 0 2px $gray-900, 0 15px 25px rgb(0 0 0 / 7%);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -11,6 +11,7 @@ import { useDispatch, useSelect } from '@wordpress/data';
11
11
  import { moreVertical } from '@wordpress/icons';
12
12
  import { Children, cloneElement } from '@wordpress/element';
13
13
  import { __ } from '@wordpress/i18n';
14
+ import { displayShortcut } from '@wordpress/keycodes';
14
15
  import {
15
16
  store as keyboardShortcutsStore,
16
17
  __unstableUseShortcutEventMatch,
@@ -33,14 +34,18 @@ const POPOVER_PROPS = {
33
34
  placement: 'bottom-start',
34
35
  };
35
36
 
36
- function CopyMenuItem( { clientIds, onCopy, label } ) {
37
+ function CopyMenuItem( { clientIds, onCopy, label, shortcut } ) {
37
38
  const { getBlocksByClientId } = useSelect( blockEditorStore );
38
39
  const ref = useCopyToClipboard(
39
40
  () => serialize( getBlocksByClientId( clientIds ) ),
40
41
  onCopy
41
42
  );
42
43
  const copyMenuItemLabel = label ? label : __( 'Copy' );
43
- return <MenuItem ref={ ref }>{ copyMenuItemLabel }</MenuItem>;
44
+ return (
45
+ <MenuItem ref={ ref } shortcut={ shortcut }>
46
+ { copyMenuItemLabel }
47
+ </MenuItem>
48
+ );
44
49
  }
45
50
 
46
51
  export function BlockSettingsDropdown( {
@@ -279,6 +284,7 @@ export function BlockSettingsDropdown( {
279
284
  <CopyMenuItem
280
285
  clientIds={ clientIds }
281
286
  onCopy={ onCopy }
287
+ shortcut={ displayShortcut.primary( 'c' ) }
282
288
  />
283
289
  { canDuplicate && (
284
290
  <MenuItem
@@ -160,7 +160,7 @@ function BlockSwitcherDropdownMenuContents( {
160
160
  );
161
161
  }
162
162
 
163
- export const BlockSwitcher = ( { clientIds } ) => {
163
+ export const BlockSwitcher = ( { clientIds, disabled } ) => {
164
164
  const {
165
165
  canRemove,
166
166
  hasBlockStyles,
@@ -182,7 +182,9 @@ export const BlockSwitcher = ( { clientIds } ) => {
182
182
  if ( ! _blocks.length || _blocks.some( ( block ) => ! block ) ) {
183
183
  return { invalidBlocks: true };
184
184
  }
185
- const rootClientId = getBlockRootClientId( clientIds );
185
+ const rootClientId = getBlockRootClientId(
186
+ Array.isArray( clientIds ) ? clientIds[ 0 ] : clientIds
187
+ );
186
188
  const [ { name: firstBlockName } ] = _blocks;
187
189
  const _isSingleBlockSelected = _blocks.length === 1;
188
190
  const blockType = getBlockType( firstBlockName );
@@ -229,8 +231,8 @@ export const BlockSwitcher = ( { clientIds } ) => {
229
231
  const blockSwitcherLabel = isSingleBlock
230
232
  ? blockTitle
231
233
  : __( 'Multiple blocks selected' );
232
- const hideDropdown = ! hasBlockStyles && ! canRemove;
233
234
 
235
+ const hideDropdown = disabled || ( ! hasBlockStyles && ! canRemove );
234
236
  if ( hideDropdown ) {
235
237
  return (
236
238
  <ToolbarGroup>
@@ -1,7 +1,7 @@
1
1
  .block-editor-block-switcher {
2
2
  position: relative;
3
3
 
4
- // @todo: override toolbar group inherited paddings from components/block-tools/style.scss.
4
+ // @todo override toolbar group inherited paddings from components/block-tools/style.scss.
5
5
  // This is best fixed by making the mover control area a proper single toolbar group.
6
6
  // It needs specificity due to style inherited from .components-accessible-toolbar .components-button.has-icon.has-icon.
7
7
  .components-button.components-dropdown-menu__toggle.has-icon.has-icon {
@@ -170,26 +170,29 @@ export function PrivateBlockToolbar( {
170
170
  { isUsingBindings && canBindBlock( blockName ) && (
171
171
  <BlockBindingsIndicator />
172
172
  ) }
173
- { ( shouldShowVisualToolbar || isMultiToolbar ) &&
174
- isDefaultEditingMode && (
175
- <div
176
- ref={ nodeRef }
177
- { ...showHoveredOrFocusedGestures }
178
- >
179
- <ToolbarGroup className="block-editor-block-toolbar__block-controls">
180
- <BlockSwitcher clientIds={ blockClientIds } />
181
- { ! isMultiToolbar && (
182
- <BlockLockToolbar
183
- clientId={ blockClientId }
173
+ { ( shouldShowVisualToolbar || isMultiToolbar ) && (
174
+ <div ref={ nodeRef } { ...showHoveredOrFocusedGestures }>
175
+ <ToolbarGroup className="block-editor-block-toolbar__block-controls">
176
+ <BlockSwitcher
177
+ clientIds={ blockClientIds }
178
+ disabled={ ! isDefaultEditingMode }
179
+ />
180
+ { isDefaultEditingMode && (
181
+ <>
182
+ { ! isMultiToolbar && (
183
+ <BlockLockToolbar
184
+ clientId={ blockClientId }
185
+ />
186
+ ) }
187
+ <BlockMover
188
+ clientIds={ blockClientIds }
189
+ hideDragHandle={ hideDragHandle }
184
190
  />
185
- ) }
186
- <BlockMover
187
- clientIds={ blockClientIds }
188
- hideDragHandle={ hideDragHandle }
189
- />
190
- </ToolbarGroup>
191
- </div>
192
- ) }
191
+ </>
192
+ ) }
193
+ </ToolbarGroup>
194
+ </div>
195
+ ) }
193
196
  <Shuffle clientId={ blockClientId } />
194
197
  { shouldShowVisualToolbar && isMultiToolbar && (
195
198
  <BlockGroupToolbar />
@@ -23,7 +23,7 @@ function Container( props ) {
23
23
  }
24
24
 
25
25
  export default function Shuffle( { clientId, as = Container } ) {
26
- const { categories, patterns } = useSelect(
26
+ const { categories, patterns, patternName } = useSelect(
27
27
  ( select ) => {
28
28
  const {
29
29
  getBlockAttributes,
@@ -32,11 +32,13 @@ export default function Shuffle( { clientId, as = Container } ) {
32
32
  } = select( blockEditorStore );
33
33
  const attributes = getBlockAttributes( clientId );
34
34
  const _categories = attributes?.metadata?.categories || EMPTY_ARRAY;
35
+ const _patternName = attributes?.metadata?.patternName;
35
36
  const rootBlock = getBlockRootClientId( clientId );
36
37
  const _patterns = __experimentalGetAllowedPatterns( rootBlock );
37
38
  return {
38
39
  categories: _categories,
39
40
  patterns: _patterns,
41
+ patternName: _patternName,
40
42
  };
41
43
  },
42
44
  [ clientId ]
@@ -65,28 +67,32 @@ export default function Shuffle( { clientId, as = Container } ) {
65
67
  if ( sameCategoryPatternsWithSingleWrapper.length === 0 ) {
66
68
  return null;
67
69
  }
70
+
71
+ function getNextPattern() {
72
+ const numberOfPatterns = sameCategoryPatternsWithSingleWrapper.length;
73
+ const patternIndex = sameCategoryPatternsWithSingleWrapper.findIndex(
74
+ ( { name } ) => name === patternName
75
+ );
76
+ const nextPatternIndex =
77
+ patternIndex + 1 < numberOfPatterns ? patternIndex + 1 : 0;
78
+ return sameCategoryPatternsWithSingleWrapper[ nextPatternIndex ];
79
+ }
80
+
68
81
  const ComponentToUse = as;
69
82
  return (
70
83
  <ComponentToUse
71
84
  label={ __( 'Shuffle' ) }
72
85
  icon={ shuffle }
73
86
  onClick={ () => {
74
- const randomPattern =
75
- sameCategoryPatternsWithSingleWrapper[
76
- Math.floor(
77
- // eslint-disable-next-line no-restricted-syntax
78
- Math.random() *
79
- sameCategoryPatternsWithSingleWrapper.length
80
- )
81
- ];
82
- randomPattern.blocks[ 0 ].attributes = {
83
- ...randomPattern.blocks[ 0 ].attributes,
87
+ const nextPattern = getNextPattern();
88
+ nextPattern.blocks[ 0 ].attributes = {
89
+ ...nextPattern.blocks[ 0 ].attributes,
84
90
  metadata: {
85
- ...randomPattern.blocks[ 0 ].attributes.metadata,
91
+ ...nextPattern.blocks[ 0 ].attributes.metadata,
86
92
  categories,
87
93
  },
88
94
  };
89
- replaceBlocks( clientId, randomPattern.blocks );
95
+ replaceBlocks( clientId, nextPattern.blocks );
90
96
  } }
91
97
  />
92
98
  );
@@ -133,7 +133,7 @@
133
133
  }
134
134
  }
135
135
 
136
- // @todo: override toolbar group inherited paddings from components/block-tools/style.scss.
136
+ // @todo override toolbar group inherited paddings from components/block-tools/style.scss.
137
137
  // This is best fixed by making the mover control area a proper single toolbar group.
138
138
  .components-toolbar-group {
139
139
  padding: 0;
@@ -6,8 +6,8 @@ import classnames from 'classnames';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { dragHandle } from '@wordpress/icons';
10
- import { Button, Flex, FlexItem } from '@wordpress/components';
9
+ import { dragHandle, trash } from '@wordpress/icons';
10
+ import { Button, Flex, FlexItem, ToolbarButton } from '@wordpress/components';
11
11
  import { useSelect, useDispatch } from '@wordpress/data';
12
12
  import { useEffect, useRef } from '@wordpress/element';
13
13
  import {
@@ -60,6 +60,9 @@ function BlockSelectionButton( { clientId, rootClientId } ) {
60
60
  hasBlockMovingClientId,
61
61
  getBlockListSettings,
62
62
  __unstableGetEditorMode,
63
+ getNextBlockClientId,
64
+ getPreviousBlockClientId,
65
+ canRemoveBlock,
63
66
  } = select( blockEditorStore );
64
67
  const { getActiveBlockVariation, getBlockType } =
65
68
  select( blocksStore );
@@ -69,6 +72,26 @@ function BlockSelectionButton( { clientId, rootClientId } ) {
69
72
  const orientation =
70
73
  getBlockListSettings( rootClientId )?.orientation;
71
74
  const match = getActiveBlockVariation( name, attributes );
75
+ const isBlockTemplatePart =
76
+ blockType?.name === 'core/template-part';
77
+
78
+ let isNextBlockTemplatePart = false;
79
+ const nextClientId = getNextBlockClientId();
80
+ if ( nextClientId ) {
81
+ const { name: nextName } = getBlock( nextClientId );
82
+ const nextBlockType = getBlockType( nextName );
83
+ isNextBlockTemplatePart =
84
+ nextBlockType?.name === 'core/template-part';
85
+ }
86
+
87
+ let isPrevBlockTemplatePart = false;
88
+ const prevClientId = getPreviousBlockClientId();
89
+ if ( prevClientId ) {
90
+ const { name: prevName } = getBlock( prevClientId );
91
+ const prevBlockType = getBlockType( prevName );
92
+ isPrevBlockTemplatePart =
93
+ prevBlockType?.name === 'core/template-part';
94
+ }
72
95
 
73
96
  return {
74
97
  blockMovingMode: hasBlockMovingClientId(),
@@ -80,20 +103,34 @@ function BlockSelectionButton( { clientId, rootClientId } ) {
80
103
  index + 1,
81
104
  orientation
82
105
  ),
106
+ isBlockTemplatePart,
107
+ isNextBlockTemplatePart,
108
+ isPrevBlockTemplatePart,
109
+ canRemove: canRemoveBlock( clientId, rootClientId ),
83
110
  };
84
111
  },
85
112
  [ clientId, rootClientId ]
86
113
  );
87
- const { label, icon, blockMovingMode, editorMode } = selected;
114
+ const {
115
+ label,
116
+ icon,
117
+ blockMovingMode,
118
+ editorMode,
119
+ isBlockTemplatePart,
120
+ isNextBlockTemplatePart,
121
+ isPrevBlockTemplatePart,
122
+ canRemove,
123
+ } = selected;
88
124
  const { setNavigationMode, removeBlock } = useDispatch( blockEditorStore );
89
125
  const ref = useRef();
90
126
 
91
127
  // Focus the breadcrumb in navigation mode.
92
128
  useEffect( () => {
93
- ref.current.focus();
94
-
95
- speak( label );
96
- }, [ label ] );
129
+ if ( editorMode === 'navigation' ) {
130
+ ref.current.focus();
131
+ speak( label );
132
+ }
133
+ }, [ label, editorMode ] );
97
134
  const blockElement = useBlockElement( clientId );
98
135
 
99
136
  const {
@@ -252,8 +289,17 @@ function BlockSelectionButton( { clientId, rootClientId } ) {
252
289
  <BlockIcon icon={ icon } showColors />
253
290
  </FlexItem>
254
291
  <FlexItem>
255
- { editorMode === 'zoom-out' && (
256
- <BlockMover clientIds={ [ clientId ] } hideDragHandle />
292
+ { editorMode === 'zoom-out' && ! isBlockTemplatePart && (
293
+ <BlockMover
294
+ clientIds={ [ clientId ] }
295
+ hideDragHandle
296
+ isBlockMoverUpButtonDisabled={
297
+ isPrevBlockTemplatePart
298
+ }
299
+ isBlockMoverDownButtonDisabled={
300
+ isNextBlockTemplatePart
301
+ }
302
+ />
257
303
  ) }
258
304
  { editorMode === 'navigation' && (
259
305
  <BlockDraggable clientIds={ [ clientId ] }>
@@ -275,6 +321,17 @@ function BlockSelectionButton( { clientId, rootClientId } ) {
275
321
  { editorMode === 'zoom-out' && (
276
322
  <Shuffle clientId={ clientId } as={ Button } />
277
323
  ) }
324
+ { canRemove &&
325
+ editorMode === 'zoom-out' &&
326
+ ! isBlockTemplatePart && (
327
+ <ToolbarButton
328
+ icon={ trash }
329
+ label="Delete"
330
+ onClick={ () => {
331
+ removeBlock( clientId );
332
+ } }
333
+ />
334
+ ) }
278
335
  <FlexItem>
279
336
  <Button
280
337
  ref={ ref }
@@ -2,6 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { useSelect, useDispatch } from '@wordpress/data';
5
+ import { isTextField } from '@wordpress/dom';
5
6
  import { Popover } from '@wordpress/components';
6
7
  import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
7
8
  import { useRef } from '@wordpress/element';
@@ -20,6 +21,7 @@ import { store as blockEditorStore } from '../../store';
20
21
  import usePopoverScroll from '../block-popover/use-popover-scroll';
21
22
  import ZoomOutModeInserters from './zoom-out-mode-inserters';
22
23
  import { useShowBlockTools } from './use-show-block-tools';
24
+ import { unlock } from '../../lock-unlock';
23
25
 
24
26
  function selector( select ) {
25
27
  const {
@@ -79,7 +81,8 @@ export default function BlockTools( {
79
81
  selectBlock,
80
82
  moveBlocksUp,
81
83
  moveBlocksDown,
82
- } = useDispatch( blockEditorStore );
84
+ expandBlock,
85
+ } = unlock( useDispatch( blockEditorStore ) );
83
86
 
84
87
  function onKeyDown( event ) {
85
88
  if ( event.defaultPrevented ) return;
@@ -140,6 +143,20 @@ export default function BlockTools( {
140
143
  // In effect, to the user this feels like deselecting the multi-selection.
141
144
  selectBlock( clientIds[ 0 ] );
142
145
  }
146
+ } else if ( isMatch( 'core/block-editor/collapse-list-view', event ) ) {
147
+ // If focus is currently within a text field, such as a rich text block or other editable field,
148
+ // skip collapsing the list view, and allow the keyboard shortcut to be handled by the text field.
149
+ // This condition checks for both the active element and the active element within an iframed editor.
150
+ if (
151
+ isTextField( event.target ) ||
152
+ isTextField(
153
+ event.target?.contentWindow?.document?.activeElement
154
+ )
155
+ ) {
156
+ return;
157
+ }
158
+ event.preventDefault();
159
+ expandBlock( clientId );
143
160
  }
144
161
  }
145
162
 
@@ -56,7 +56,11 @@
56
56
  }
57
57
 
58
58
  .block-editor-inserter {
59
- visibility: hidden;
59
+ opacity: 0;
60
+
61
+ &:focus-within {
62
+ opacity: 1;
63
+ }
60
64
  }
61
65
 
62
66
  &.is-drag-over {
@@ -101,7 +101,7 @@
101
101
  height: $button-size-small;
102
102
  }
103
103
 
104
- // @todo: these are currently two separate components. Since we're now
104
+ // @todo these are currently two separate components. Since we're now
105
105
  // treating them the same, one or both can be retired.
106
106
  .block-editor-inserter__toggle.components-button.has-icon,
107
107
  .block-list-appender__toggle {
@@ -134,7 +134,7 @@
134
134
 
135
135
  // These could be avoided by employing a :not(:only-child) on the parent,
136
136
  // but this should be more performant.
137
- // @todo: These styles can almost certainly be refactored away we refactor
137
+ // @todo These styles can almost certainly be refactored away we refactor
138
138
  // the markup and classes of the component itself. The rules provide some
139
139
  // baseline styles for when the block is the only one inside.
140
140
  &:only-child {
@@ -28,9 +28,12 @@ export default function AdvancedPanel( {
28
28
  css: newValue,
29
29
  } );
30
30
  if ( cssError ) {
31
+ // Check if the new value is valid CSS, and pass a wrapping selector
32
+ // to ensure that `transformStyles` validates the CSS. Note that the
33
+ // wrapping selector here is not used in the actual output of any styles.
31
34
  const [ transformed ] = transformStyles(
32
35
  [ { css: newValue } ],
33
- '.editor-styles-wrapper'
36
+ '.for-validation-only'
34
37
  );
35
38
  if ( transformed ) {
36
39
  setCSSError( null );
@@ -43,9 +46,12 @@ export default function AdvancedPanel( {
43
46
  return;
44
47
  }
45
48
 
49
+ // Check if the new value is valid CSS, and pass a wrapping selector
50
+ // to ensure that `transformStyles` validates the CSS. Note that the
51
+ // wrapping selector here is not used in the actual output of any styles.
46
52
  const [ transformed ] = transformStyles(
47
53
  [ { css: event.target.value } ],
48
- '.editor-styles-wrapper'
54
+ '.for-validation-only'
49
55
  );
50
56
 
51
57
  setCSSError(