@wordpress/block-editor 14.3.5 → 14.3.7

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 (157) hide show
  1. package/README.md +6 -2
  2. package/build/components/block-list/block.js +0 -3
  3. package/build/components/block-list/block.js.map +1 -1
  4. package/build/components/block-list/use-block-props/index.js +1 -4
  5. package/build/components/block-list/use-block-props/index.js.map +1 -1
  6. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js +14 -6
  7. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  8. package/build/components/block-list/use-block-props/use-zoom-out-mode-exit.js +9 -12
  9. package/build/components/block-list/use-block-props/use-zoom-out-mode-exit.js.map +1 -1
  10. package/build/components/block-list/zoom-out-separator.js +10 -7
  11. package/build/components/block-list/zoom-out-separator.js.map +1 -1
  12. package/build/components/block-popover/index.js +1 -1
  13. package/build/components/block-popover/index.js.map +1 -1
  14. package/build/components/block-toolbar/index.js +28 -16
  15. package/build/components/block-toolbar/index.js.map +1 -1
  16. package/build/components/block-toolbar/use-has-block-toolbar.js +3 -3
  17. package/build/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  18. package/build/components/block-tools/index.js +1 -6
  19. package/build/components/block-tools/index.js.map +1 -1
  20. package/build/components/block-tools/use-show-block-tools.js +4 -6
  21. package/build/components/block-tools/use-show-block-tools.js.map +1 -1
  22. package/build/components/block-tools/zoom-out-mode-inserters.js +22 -36
  23. package/build/components/block-tools/zoom-out-mode-inserters.js.map +1 -1
  24. package/build/components/iframe/index.js +45 -10
  25. package/build/components/iframe/index.js.map +1 -1
  26. package/build/components/inserter/block-patterns-tab/index.js +4 -0
  27. package/build/components/inserter/block-patterns-tab/index.js.map +1 -1
  28. package/build/components/inserter/hooks/use-insertion-point.js +16 -4
  29. package/build/components/inserter/hooks/use-insertion-point.js.map +1 -1
  30. package/build/components/inserter/media-tab/media-tab.js +4 -0
  31. package/build/components/inserter/media-tab/media-tab.js.map +1 -1
  32. package/build/components/inserter/menu.js +8 -2
  33. package/build/components/inserter/menu.js.map +1 -1
  34. package/build/components/tool-selector/index.js +5 -1
  35. package/build/components/tool-selector/index.js.map +1 -1
  36. package/build/components/use-resize-canvas/index.js +1 -2
  37. package/build/components/use-resize-canvas/index.js.map +1 -1
  38. package/build/hooks/block-bindings.js +12 -1
  39. package/build/hooks/block-bindings.js.map +1 -1
  40. package/build/hooks/grid-visualizer.js +13 -11
  41. package/build/hooks/grid-visualizer.js.map +1 -1
  42. package/build/hooks/layout-child.js +41 -3
  43. package/build/hooks/layout-child.js.map +1 -1
  44. package/build/hooks/use-zoom-out.js +24 -16
  45. package/build/hooks/use-zoom-out.js.map +1 -1
  46. package/build/private-apis.js +2 -0
  47. package/build/private-apis.js.map +1 -1
  48. package/build/store/private-selectors.js +37 -2
  49. package/build/store/private-selectors.js.map +1 -1
  50. package/build/store/selectors.js +15 -8
  51. package/build/store/selectors.js.map +1 -1
  52. package/build/utils/block-bindings.js +9 -6
  53. package/build/utils/block-bindings.js.map +1 -1
  54. package/build-module/components/block-list/block.js +0 -3
  55. package/build-module/components/block-list/block.js.map +1 -1
  56. package/build-module/components/block-list/use-block-props/index.js +1 -4
  57. package/build-module/components/block-list/use-block-props/index.js.map +1 -1
  58. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js +14 -6
  59. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  60. package/build-module/components/block-list/use-block-props/use-zoom-out-mode-exit.js +9 -12
  61. package/build-module/components/block-list/use-block-props/use-zoom-out-mode-exit.js.map +1 -1
  62. package/build-module/components/block-list/zoom-out-separator.js +10 -7
  63. package/build-module/components/block-list/zoom-out-separator.js.map +1 -1
  64. package/build-module/components/block-popover/index.js +1 -1
  65. package/build-module/components/block-popover/index.js.map +1 -1
  66. package/build-module/components/block-toolbar/index.js +30 -18
  67. package/build-module/components/block-toolbar/index.js.map +1 -1
  68. package/build-module/components/block-toolbar/use-has-block-toolbar.js +3 -3
  69. package/build-module/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  70. package/build-module/components/block-tools/index.js +1 -6
  71. package/build-module/components/block-tools/index.js.map +1 -1
  72. package/build-module/components/block-tools/use-show-block-tools.js +4 -6
  73. package/build-module/components/block-tools/use-show-block-tools.js.map +1 -1
  74. package/build-module/components/block-tools/zoom-out-mode-inserters.js +22 -36
  75. package/build-module/components/block-tools/zoom-out-mode-inserters.js.map +1 -1
  76. package/build-module/components/iframe/index.js +45 -10
  77. package/build-module/components/iframe/index.js.map +1 -1
  78. package/build-module/components/inserter/block-patterns-tab/index.js +5 -1
  79. package/build-module/components/inserter/block-patterns-tab/index.js.map +1 -1
  80. package/build-module/components/inserter/hooks/use-insertion-point.js +16 -4
  81. package/build-module/components/inserter/hooks/use-insertion-point.js.map +1 -1
  82. package/build-module/components/inserter/media-tab/media-tab.js +5 -1
  83. package/build-module/components/inserter/media-tab/media-tab.js.map +1 -1
  84. package/build-module/components/inserter/menu.js +8 -2
  85. package/build-module/components/inserter/menu.js.map +1 -1
  86. package/build-module/components/tool-selector/index.js +5 -1
  87. package/build-module/components/tool-selector/index.js.map +1 -1
  88. package/build-module/components/use-resize-canvas/index.js +1 -2
  89. package/build-module/components/use-resize-canvas/index.js.map +1 -1
  90. package/build-module/hooks/block-bindings.js +13 -2
  91. package/build-module/hooks/block-bindings.js.map +1 -1
  92. package/build-module/hooks/grid-visualizer.js +13 -11
  93. package/build-module/hooks/grid-visualizer.js.map +1 -1
  94. package/build-module/hooks/layout-child.js +41 -3
  95. package/build-module/hooks/layout-child.js.map +1 -1
  96. package/build-module/hooks/use-zoom-out.js +24 -17
  97. package/build-module/hooks/use-zoom-out.js.map +1 -1
  98. package/build-module/private-apis.js +2 -0
  99. package/build-module/private-apis.js.map +1 -1
  100. package/build-module/store/private-selectors.js +35 -2
  101. package/build-module/store/private-selectors.js.map +1 -1
  102. package/build-module/store/selectors.js +15 -8
  103. package/build-module/store/selectors.js.map +1 -1
  104. package/build-module/utils/block-bindings.js +9 -6
  105. package/build-module/utils/block-bindings.js.map +1 -1
  106. package/build-style/content-rtl.css +19 -26
  107. package/build-style/content.css +19 -26
  108. package/build-style/style-rtl.css +36 -21
  109. package/build-style/style.css +36 -21
  110. package/package.json +6 -6
  111. package/src/components/block-canvas/style.scss +1 -0
  112. package/src/components/block-list/block.js +0 -3
  113. package/src/components/block-list/content.scss +3 -2
  114. package/src/components/block-list/use-block-props/index.js +1 -2
  115. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +25 -4
  116. package/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +19 -11
  117. package/src/components/block-list/zoom-out-separator.js +8 -6
  118. package/src/components/block-popover/index.js +2 -2
  119. package/src/components/block-toolbar/index.js +37 -24
  120. package/src/components/block-toolbar/style.scss +10 -1
  121. package/src/components/block-toolbar/use-has-block-toolbar.js +19 -28
  122. package/src/components/block-tools/index.js +0 -9
  123. package/src/components/block-tools/style.scss +2 -26
  124. package/src/components/block-tools/use-show-block-tools.js +2 -10
  125. package/src/components/block-tools/zoom-out-mode-inserters.js +26 -50
  126. package/src/components/iframe/content.scss +23 -32
  127. package/src/components/iframe/index.js +60 -13
  128. package/src/components/iframe/style.scss +18 -0
  129. package/src/components/inserter/block-patterns-tab/index.js +6 -1
  130. package/src/components/inserter/hooks/use-insertion-point.js +23 -5
  131. package/src/components/inserter/media-tab/media-tab.js +6 -1
  132. package/src/components/inserter/menu.js +12 -1
  133. package/src/components/inserter/style.scss +6 -0
  134. package/src/components/list-view/style.scss +9 -0
  135. package/src/components/rich-text/style.scss +5 -0
  136. package/src/components/tool-selector/index.js +5 -2
  137. package/src/components/use-resize-canvas/index.js +1 -3
  138. package/src/hooks/block-bindings.js +40 -23
  139. package/src/hooks/grid-visualizer.js +23 -9
  140. package/src/hooks/layout-child.js +48 -3
  141. package/src/hooks/use-zoom-out.js +36 -20
  142. package/src/private-apis.js +2 -0
  143. package/src/store/private-selectors.js +40 -1
  144. package/src/store/selectors.js +16 -8
  145. package/src/style.scss +1 -0
  146. package/src/utils/block-bindings.js +9 -6
  147. package/src/utils/test/use-block-bindings-utils.js +174 -0
  148. package/build/components/block-tools/zoom-out-popover.js +0 -57
  149. package/build/components/block-tools/zoom-out-popover.js.map +0 -1
  150. package/build/components/block-tools/zoom-out-toolbar.js +0 -159
  151. package/build/components/block-tools/zoom-out-toolbar.js.map +0 -1
  152. package/build-module/components/block-tools/zoom-out-popover.js +0 -48
  153. package/build-module/components/block-tools/zoom-out-popover.js.map +0 -1
  154. package/build-module/components/block-tools/zoom-out-toolbar.js +0 -152
  155. package/build-module/components/block-tools/zoom-out-toolbar.js.map +0 -1
  156. package/src/components/block-tools/zoom-out-popover.js +0 -46
  157. package/src/components/block-tools/zoom-out-toolbar.js +0 -167
@@ -122,7 +122,7 @@ function Iframe( {
122
122
  }, [] );
123
123
  const { styles = '', scripts = '' } = resolvedAssets;
124
124
  const [ iframeDocument, setIframeDocument ] = useState();
125
- const prevContainerWidthRef = useRef();
125
+ const initialContainerWidth = useRef( 0 );
126
126
  const [ bodyClasses, setBodyClasses ] = useState( [] );
127
127
  const clearerRef = useBlockSelectionClearer();
128
128
  const [ before, writingFlowRef, after ] = useWritingFlow();
@@ -243,10 +243,15 @@ function Iframe( {
243
243
 
244
244
  useEffect( () => {
245
245
  if ( ! isZoomedOut ) {
246
- prevContainerWidthRef.current = containerWidth;
246
+ initialContainerWidth.current = containerWidth;
247
247
  }
248
248
  }, [ containerWidth, isZoomedOut ] );
249
249
 
250
+ const scaleContainerWidth = Math.max(
251
+ initialContainerWidth.current,
252
+ containerWidth
253
+ );
254
+
250
255
  const disabledRef = useDisabled( { isDisabled: ! readonly } );
251
256
  const bodyRef = useMergeRefs( [
252
257
  useBubbleEvents( iframeDocument ),
@@ -298,21 +303,65 @@ function Iframe( {
298
303
 
299
304
  useEffect( () => cleanup, [ cleanup ] );
300
305
 
306
+ const zoomOutAnimationClassnameRef = useRef( null );
307
+
308
+ // Toggle zoom out CSS Classes only when zoom out mode changes. We could add these into the useEffect
309
+ // that controls settings the CSS variables, but then we would need to do more work to ensure we're
310
+ // only toggling these when the zoom out mode changes, as that useEffect is also triggered by a large
311
+ // number of dependencies.
301
312
  useEffect( () => {
302
313
  if ( ! iframeDocument || ! isZoomedOut ) {
303
314
  return;
304
315
  }
305
316
 
317
+ const handleZoomOutAnimationClassname = () => {
318
+ clearTimeout( zoomOutAnimationClassnameRef.current );
319
+
320
+ iframeDocument.documentElement.classList.add(
321
+ 'zoom-out-animation'
322
+ );
323
+
324
+ zoomOutAnimationClassnameRef.current = setTimeout( () => {
325
+ iframeDocument.documentElement.classList.remove(
326
+ 'zoom-out-animation'
327
+ );
328
+ }, 400 ); // 400ms should match the animation speed used in components/iframe/content.scss
329
+ };
330
+
331
+ handleZoomOutAnimationClassname();
306
332
  iframeDocument.documentElement.classList.add( 'is-zoomed-out' );
307
333
 
334
+ return () => {
335
+ handleZoomOutAnimationClassname();
336
+ iframeDocument.documentElement.classList.remove( 'is-zoomed-out' );
337
+ };
338
+ }, [ iframeDocument, isZoomedOut ] );
339
+
340
+ // Calculate the scaling and CSS variables for the zoom out canvas
341
+ useEffect( () => {
342
+ if ( ! iframeDocument || ! isZoomedOut ) {
343
+ return;
344
+ }
345
+
308
346
  const maxWidth = 750;
347
+ // Note: When we initialize the zoom out when the canvas is smaller (sidebars open),
348
+ // initialContainerWidth will be smaller than the full page, and reflow will happen
349
+ // when the canvas area becomes larger due to sidebars closing. This is a known but
350
+ // minor divergence for now.
351
+
352
+ // This scaling calculation has to happen within the JS because CSS calc() can
353
+ // only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid
354
+ // but calc( 100px / 2px ) is not.
309
355
  iframeDocument.documentElement.style.setProperty(
310
356
  '--wp-block-editor-iframe-zoom-out-scale',
311
357
  scale === 'default'
312
- ? Math.min( containerWidth, maxWidth ) /
313
- prevContainerWidthRef.current
358
+ ? ( Math.min( containerWidth, maxWidth ) -
359
+ parseInt( frameSize ) * 2 ) /
360
+ scaleContainerWidth
314
361
  : scale
315
362
  );
363
+
364
+ // frameSize has to be a px value for the scaling and frame size to be computed correctly.
316
365
  iframeDocument.documentElement.style.setProperty(
317
366
  '--wp-block-editor-iframe-zoom-out-frame-size',
318
367
  typeof frameSize === 'number' ? `${ frameSize }px` : frameSize
@@ -330,13 +379,11 @@ function Iframe( {
330
379
  `${ containerWidth }px`
331
380
  );
332
381
  iframeDocument.documentElement.style.setProperty(
333
- '--wp-block-editor-iframe-zoom-out-prev-container-width',
334
- `${ prevContainerWidthRef.current }px`
382
+ '--wp-block-editor-iframe-zoom-out-scale-container-width',
383
+ `${ scaleContainerWidth }px`
335
384
  );
336
385
 
337
386
  return () => {
338
- iframeDocument.documentElement.classList.remove( 'is-zoomed-out' );
339
-
340
387
  iframeDocument.documentElement.style.removeProperty(
341
388
  '--wp-block-editor-iframe-zoom-out-scale'
342
389
  );
@@ -353,7 +400,7 @@ function Iframe( {
353
400
  '--wp-block-editor-iframe-zoom-out-container-width'
354
401
  );
355
402
  iframeDocument.documentElement.style.removeProperty(
356
- '--wp-block-editor-iframe-zoom-out-prev-container-width'
403
+ '--wp-block-editor-iframe-zoom-out-scale-container-width'
357
404
  );
358
405
  };
359
406
  }, [
@@ -365,6 +412,7 @@ function Iframe( {
365
412
  containerWidth,
366
413
  windowInnerWidth,
367
414
  isZoomedOut,
415
+ scaleContainerWidth,
368
416
  ] );
369
417
 
370
418
  // Make sure to not render the before and after focusable div elements in view
@@ -380,6 +428,7 @@ function Iframe( {
380
428
  style={ {
381
429
  ...props.style,
382
430
  height: props.style?.height,
431
+ border: 0,
383
432
  } }
384
433
  ref={ useMergeRefs( [ ref, setRef ] ) }
385
434
  tabIndex={ tabIndex }
@@ -453,10 +502,8 @@ function Iframe( {
453
502
  isZoomedOut && 'is-zoomed-out'
454
503
  ) }
455
504
  style={ {
456
- '--wp-block-editor-iframe-zoom-out-container-width':
457
- isZoomedOut && `${ containerWidth }px`,
458
- '--wp-block-editor-iframe-zoom-out-prev-container-width':
459
- isZoomedOut && `${ prevContainerWidthRef.current }px`,
505
+ '--wp-block-editor-iframe-zoom-out-scale-container-width':
506
+ isZoomedOut && `${ scaleContainerWidth }px`,
460
507
  } }
461
508
  >
462
509
  { iframe }
@@ -0,0 +1,18 @@
1
+ .block-editor-iframe__container {
2
+ width: 100%;
3
+ height: 100%;
4
+ overflow-x: hidden;
5
+ }
6
+
7
+ .block-editor-iframe__scale-container {
8
+ height: 100%;
9
+ }
10
+
11
+ .block-editor-iframe__scale-container.is-zoomed-out {
12
+ $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width, 100vw);
13
+ width: $scale-container-width;
14
+ // Position the iframe so that it is always aligned with the right side so that
15
+ // the scrollbar is always visible on the right side
16
+ position: absolute;
17
+ right: 0;
18
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useState } from '@wordpress/element';
4
+ import { useState, useEffect } from '@wordpress/element';
5
5
  import { useViewportMatch } from '@wordpress/compose';
6
6
  import { Button, Spinner } from '@wordpress/components';
7
7
  import { __ } from '@wordpress/i18n';
@@ -24,6 +24,7 @@ function BlockPatternsTab( {
24
24
  selectedCategory,
25
25
  onInsert,
26
26
  rootClientId,
27
+ setHasCategories,
27
28
  children,
28
29
  } ) {
29
30
  const [ showPatternsExplorer, setShowPatternsExplorer ] = useState( false );
@@ -37,6 +38,10 @@ function BlockPatternsTab( {
37
38
  []
38
39
  );
39
40
 
41
+ useEffect( () => {
42
+ setHasCategories( !! categories.length );
43
+ }, [ categories, setHasCategories ] );
44
+
40
45
  if ( isResolvingPatterns ) {
41
46
  return (
42
47
  <div className="block-editor-inserter__patterns-loading">
@@ -79,7 +79,9 @@ function useInsertionPoint( {
79
79
  getBlockRootClientId,
80
80
  getBlockIndex,
81
81
  getBlockOrder,
82
- } = select( blockEditorStore );
82
+ getSectionRootClientId,
83
+ __unstableGetEditorMode,
84
+ } = unlock( select( blockEditorStore ) );
83
85
  const selectedBlockClientId = getSelectedBlockClientId();
84
86
 
85
87
  let _destinationRootClientId = rootClientId;
@@ -92,10 +94,26 @@ function useInsertionPoint( {
92
94
  // Insert after a specific client ID.
93
95
  _destinationIndex = getBlockIndex( clientId );
94
96
  } else if ( ! isAppender && selectedBlockClientId ) {
95
- _destinationRootClientId = getBlockRootClientId(
96
- selectedBlockClientId
97
- );
98
- _destinationIndex = getBlockIndex( selectedBlockClientId ) + 1;
97
+ const sectionRootClientId = getSectionRootClientId();
98
+
99
+ // Avoids empty inserter when the selected block is acting
100
+ // as the "root".
101
+ // See https://github.com/WordPress/gutenberg/pull/66214.
102
+ if (
103
+ __unstableGetEditorMode() === 'zoom-out' &&
104
+ sectionRootClientId === selectedBlockClientId
105
+ ) {
106
+ _destinationRootClientId = sectionRootClientId;
107
+ _destinationIndex = getBlockOrder(
108
+ _destinationRootClientId
109
+ ).length;
110
+ } else {
111
+ _destinationRootClientId = getBlockRootClientId(
112
+ selectedBlockClientId
113
+ );
114
+ _destinationIndex =
115
+ getBlockIndex( selectedBlockClientId ) + 1;
116
+ }
99
117
  } else {
100
118
  // Insert at the end of the list.
101
119
  _destinationIndex = getBlockOrder(
@@ -4,7 +4,7 @@
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { useViewportMatch } from '@wordpress/compose';
6
6
  import { Button } from '@wordpress/components';
7
- import { useCallback, useMemo } from '@wordpress/element';
7
+ import { useCallback, useEffect, useMemo } from '@wordpress/element';
8
8
 
9
9
  /**
10
10
  * Internal dependencies
@@ -24,6 +24,7 @@ function MediaTab( {
24
24
  rootClientId,
25
25
  selectedCategory,
26
26
  onSelectCategory,
27
+ setHasCategories,
27
28
  onInsert,
28
29
  children,
29
30
  } ) {
@@ -49,6 +50,10 @@ function MediaTab( {
49
50
  [ mediaCategories ]
50
51
  );
51
52
 
53
+ useEffect( () => {
54
+ setHasCategories( !! categories.length );
55
+ }, [ categories, setHasCategories ] );
56
+
52
57
  if ( ! categories.length ) {
53
58
  return <InserterNoResults />;
54
59
  }
@@ -32,6 +32,7 @@ import InserterSearchResults from './search-results';
32
32
  import useInsertionPoint from './hooks/use-insertion-point';
33
33
  import { store as blockEditorStore } from '../../store';
34
34
  import TabbedSidebar from '../tabbed-sidebar';
35
+ import { useZoomOut } from '../../hooks/use-zoom-out';
35
36
 
36
37
  const NOOP = () => {};
37
38
  function InserterMenu(
@@ -66,6 +67,8 @@ function InserterMenu(
66
67
  const [ patternFilter, setPatternFilter ] = useState( 'all' );
67
68
  const [ selectedMediaCategory, setSelectedMediaCategory ] =
68
69
  useState( null );
70
+
71
+ const [ hasCategories, setHasCategories ] = useState( true );
69
72
  function getInitialTab() {
70
73
  if ( __experimentalInitialTab ) {
71
74
  return __experimentalInitialTab;
@@ -77,6 +80,10 @@ function InserterMenu(
77
80
  }
78
81
  const [ selectedTab, setSelectedTab ] = useState( getInitialTab() );
79
82
 
83
+ const shouldUseZoomOut =
84
+ selectedTab === 'patterns' || selectedTab === 'media';
85
+ useZoomOut( shouldUseZoomOut );
86
+
80
87
  const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] =
81
88
  useInsertionPoint( {
82
89
  rootClientId,
@@ -141,10 +148,12 @@ function InserterMenu(
141
148
 
142
149
  const showPatternPanel =
143
150
  selectedTab === 'patterns' &&
151
+ hasCategories &&
144
152
  ! delayedFilterValue &&
145
153
  !! selectedPatternCategory;
146
154
 
147
- const showMediaPanel = selectedTab === 'media' && !! selectedMediaCategory;
155
+ const showMediaPanel =
156
+ selectedTab === 'media' && !! selectedMediaCategory && hasCategories;
148
157
 
149
158
  const inserterSearch = useMemo( () => {
150
159
  if ( selectedTab === 'media' ) {
@@ -237,6 +246,7 @@ function InserterMenu(
237
246
  onInsert={ onInsertPattern }
238
247
  onSelectCategory={ onClickPatternCategory }
239
248
  selectedCategory={ selectedPatternCategory }
249
+ setHasCategories={ setHasCategories }
240
250
  >
241
251
  { showPatternPanel && (
242
252
  <PatternCategoryPreviews
@@ -265,6 +275,7 @@ function InserterMenu(
265
275
  selectedCategory={ selectedMediaCategory }
266
276
  onSelectCategory={ setSelectedMediaCategory }
267
277
  onInsert={ onInsert }
278
+ setHasCategories={ setHasCategories }
268
279
  >
269
280
  { showMediaPanel && (
270
281
  <MediaCategoryPanel
@@ -123,6 +123,12 @@ $block-inserter-tabs-height: 44px;
123
123
  }
124
124
 
125
125
  .block-editor-inserter__panel-header {
126
+ // Use `position: relative` to ensure any absolute positioned child elements are
127
+ // positioned relative to the panel header.
128
+ // This makes the overflow rule of the panel work correctly, particularly when the
129
+ // `VisuallyHidden` component is used within the inserter UI.
130
+ position: relative;
131
+
126
132
  display: inline-flex;
127
133
  align-items: center;
128
134
  padding: $grid-unit-20 $grid-unit-20 0;
@@ -41,6 +41,15 @@
41
41
  &:hover {
42
42
  color: var(--wp-admin-theme-color);
43
43
  }
44
+
45
+ svg {
46
+ fill: currentColor;
47
+ // Optimizate for high contrast modes.
48
+ // See also https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/.
49
+ @media (forced-colors: active) {
50
+ fill: CanvasText;
51
+ }
52
+ }
44
53
  }
45
54
 
46
55
  &:not(.is-selected) .block-editor-list-view-block-select-button {
@@ -9,12 +9,17 @@
9
9
  margin-bottom: $grid-unit-10;
10
10
  box-shadow: none;
11
11
  outline: none;
12
+ border-radius: $radius-small;
12
13
  }
13
14
 
14
15
  .components-toolbar {
15
16
  border-radius: $radius-small;
16
17
  }
17
18
 
19
+ .components-toolbar-group {
20
+ background: none;
21
+ }
22
+
18
23
  .components-toolbar__control,
19
24
  .components-dropdown-menu__toggle {
20
25
  min-width: $block-toolbar-height;
@@ -36,7 +36,7 @@ function ToolSelector( props, ref ) {
36
36
  ( select ) => select( blockEditorStore ).__unstableGetEditorMode(),
37
37
  []
38
38
  );
39
- const { __unstableSetEditorMode } = unlock(
39
+ const { resetZoomLevel, __unstableSetEditorMode } = unlock(
40
40
  useDispatch( blockEditorStore )
41
41
  );
42
42
 
@@ -63,7 +63,10 @@ function ToolSelector( props, ref ) {
63
63
  value={
64
64
  mode === 'navigation' ? 'navigation' : 'edit'
65
65
  }
66
- onSelect={ __unstableSetEditorMode }
66
+ onSelect={ ( newMode ) => {
67
+ resetZoomLevel();
68
+ __unstableSetEditorMode( newMode );
69
+ } }
67
70
  choices={ [
68
71
  {
69
72
  value: 'edit',
@@ -43,11 +43,9 @@ export default function useResizeCanvas( deviceType ) {
43
43
  return deviceWidth < actualWidth ? deviceWidth : actualWidth;
44
44
  };
45
45
 
46
- const marginValue = () => ( window.innerHeight < 800 ? 36 : 64 );
47
-
48
46
  const contentInlineStyles = ( device ) => {
49
47
  const height = device === 'Mobile' ? '768px' : '1024px';
50
- const marginVertical = marginValue() + 'px';
48
+ const marginVertical = '40px';
51
49
  const marginHorizontal = 'auto';
52
50
 
53
51
  switch ( device ) {
@@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n';
5
5
  import {
6
6
  getBlockBindingsSource,
7
7
  getBlockBindingsSources,
8
+ getBlockType,
8
9
  } from '@wordpress/blocks';
9
10
  import {
10
11
  __experimentalItemGroup as ItemGroup,
@@ -29,6 +30,7 @@ import {
29
30
  import { unlock } from '../lock-unlock';
30
31
  import InspectorControls from '../components/inspector-controls';
31
32
  import BlockContext from '../components/block-context';
33
+ import { useBlockEditContext } from '../components/block-edit';
32
34
  import { useBlockBindingsUtils } from '../utils/block-bindings';
33
35
  import { store as blockEditorStore } from '../store';
34
36
 
@@ -50,9 +52,20 @@ const useToolsPanelDropdownMenuProps = () => {
50
52
  };
51
53
 
52
54
  function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
55
+ const { clientId } = useBlockEditContext();
53
56
  const registeredSources = getBlockBindingsSources();
54
57
  const { updateBlockBindings } = useBlockBindingsUtils();
55
58
  const currentKey = binding?.args?.key;
59
+ const attributeType = useSelect(
60
+ ( select ) => {
61
+ const { name: blockName } =
62
+ select( blockEditorStore ).getBlock( clientId );
63
+ const _attributeType =
64
+ getBlockType( blockName ).attributes?.[ attribute ]?.type;
65
+ return _attributeType === 'rich-text' ? 'string' : _attributeType;
66
+ },
67
+ [ clientId, attribute ]
68
+ );
56
69
  return (
57
70
  <>
58
71
  { Object.entries( fieldsList ).map( ( [ name, fields ], i ) => (
@@ -63,29 +76,33 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
63
76
  { registeredSources[ name ].label }
64
77
  </DropdownMenuV2.GroupLabel>
65
78
  ) }
66
- { Object.entries( fields ).map( ( [ key, args ] ) => (
67
- <DropdownMenuV2.RadioItem
68
- key={ key }
69
- onChange={ () =>
70
- updateBlockBindings( {
71
- [ attribute ]: {
72
- source: name,
73
- args: { key },
74
- },
75
- } )
76
- }
77
- name={ attribute + '-binding' }
78
- value={ key }
79
- checked={ key === currentKey }
80
- >
81
- <DropdownMenuV2.ItemLabel>
82
- { args?.label }
83
- </DropdownMenuV2.ItemLabel>
84
- <DropdownMenuV2.ItemHelpText>
85
- { args?.value }
86
- </DropdownMenuV2.ItemHelpText>
87
- </DropdownMenuV2.RadioItem>
88
- ) ) }
79
+ { Object.entries( fields )
80
+ .filter(
81
+ ( [ , args ] ) => args?.type === attributeType
82
+ )
83
+ .map( ( [ key, args ] ) => (
84
+ <DropdownMenuV2.RadioItem
85
+ key={ key }
86
+ onChange={ () =>
87
+ updateBlockBindings( {
88
+ [ attribute ]: {
89
+ source: name,
90
+ args: { key },
91
+ },
92
+ } )
93
+ }
94
+ name={ attribute + '-binding' }
95
+ value={ key }
96
+ checked={ key === currentKey }
97
+ >
98
+ <DropdownMenuV2.ItemLabel>
99
+ { args?.label }
100
+ </DropdownMenuV2.ItemLabel>
101
+ <DropdownMenuV2.ItemHelpText>
102
+ { args?.value }
103
+ </DropdownMenuV2.ItemHelpText>
104
+ </DropdownMenuV2.RadioItem>
105
+ ) ) }
89
106
  </DropdownMenuV2.Group>
90
107
  { i !== Object.keys( fieldsList ).length - 1 && (
91
108
  <DropdownMenuV2.Separator />
@@ -16,20 +16,34 @@ function GridLayoutSync( props ) {
16
16
  }
17
17
 
18
18
  function GridTools( { clientId, layout } ) {
19
- const { isSelected, isDragging } = useSelect( ( select ) => {
20
- const { isBlockSelected, isDraggingBlocks } =
21
- select( blockEditorStore );
19
+ const isVisible = useSelect(
20
+ ( select ) => {
21
+ const {
22
+ isBlockSelected,
23
+ isDraggingBlocks,
24
+ getTemplateLock,
25
+ getBlockEditingMode,
26
+ } = select( blockEditorStore );
22
27
 
23
- return {
24
- isSelected: isBlockSelected( clientId ),
25
- isDragging: isDraggingBlocks(),
26
- };
27
- } );
28
+ // These calls are purposely ordered from least expensive to most expensive.
29
+ // Hides the visualizer in cases where the user is not or cannot interact with it.
30
+ if (
31
+ ( ! isDraggingBlocks() && ! isBlockSelected( clientId ) ) ||
32
+ getTemplateLock( clientId ) ||
33
+ getBlockEditingMode( clientId ) !== 'default'
34
+ ) {
35
+ return false;
36
+ }
37
+
38
+ return true;
39
+ },
40
+ [ clientId ]
41
+ );
28
42
 
29
43
  return (
30
44
  <>
31
45
  <GridLayoutSync clientId={ clientId } />
32
- { ( isSelected || isDragging ) && (
46
+ { isVisible && (
33
47
  <GridVisualizer clientId={ clientId } parentLayout={ layout } />
34
48
  ) }
35
49
  </>
@@ -172,9 +172,54 @@ function ChildLayoutControlsPure( { clientId, style, setAttributes } ) {
172
172
  isManualPlacement,
173
173
  } = parentLayout;
174
174
 
175
- const rootClientId = useSelect(
175
+ if ( parentLayoutType !== 'grid' ) {
176
+ return null;
177
+ }
178
+
179
+ return (
180
+ <GridTools
181
+ clientId={ clientId }
182
+ style={ style }
183
+ setAttributes={ setAttributes }
184
+ allowSizingOnChildren={ allowSizingOnChildren }
185
+ isManualPlacement={ isManualPlacement }
186
+ parentLayout={ parentLayout }
187
+ />
188
+ );
189
+ }
190
+
191
+ function GridTools( {
192
+ clientId,
193
+ style,
194
+ setAttributes,
195
+ allowSizingOnChildren,
196
+ isManualPlacement,
197
+ parentLayout,
198
+ } ) {
199
+ const { rootClientId, isVisible } = useSelect(
176
200
  ( select ) => {
177
- return select( blockEditorStore ).getBlockRootClientId( clientId );
201
+ const {
202
+ getBlockRootClientId,
203
+ getBlockEditingMode,
204
+ getTemplateLock,
205
+ } = select( blockEditorStore );
206
+
207
+ const _rootClientId = getBlockRootClientId( clientId );
208
+
209
+ if (
210
+ getTemplateLock( _rootClientId ) ||
211
+ getBlockEditingMode( _rootClientId ) !== 'default'
212
+ ) {
213
+ return {
214
+ rootClientId: _rootClientId,
215
+ isVisible: false,
216
+ };
217
+ }
218
+
219
+ return {
220
+ rootClientId: _rootClientId,
221
+ isVisible: true,
222
+ };
178
223
  },
179
224
  [ clientId ]
180
225
  );
@@ -182,7 +227,7 @@ function ChildLayoutControlsPure( { clientId, style, setAttributes } ) {
182
227
  // Use useState() instead of useRef() so that GridItemResizer updates when ref is set.
183
228
  const [ resizerBounds, setResizerBounds ] = useState();
184
229
 
185
- if ( parentLayoutType !== 'grid' ) {
230
+ if ( ! isVisible ) {
186
231
  return null;
187
232
  }
188
233