@wordpress/block-editor 14.3.6 → 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 (110) hide show
  1. package/README.md +2 -2
  2. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js +14 -6
  3. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  4. package/build/components/block-list/zoom-out-separator.js +10 -7
  5. package/build/components/block-list/zoom-out-separator.js.map +1 -1
  6. package/build/components/block-popover/index.js +1 -1
  7. package/build/components/block-popover/index.js.map +1 -1
  8. package/build/components/block-toolbar/index.js +28 -16
  9. package/build/components/block-toolbar/index.js.map +1 -1
  10. package/build/components/block-toolbar/use-has-block-toolbar.js +3 -3
  11. package/build/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  12. package/build/components/block-tools/index.js +1 -6
  13. package/build/components/block-tools/index.js.map +1 -1
  14. package/build/components/block-tools/use-show-block-tools.js +4 -6
  15. package/build/components/block-tools/use-show-block-tools.js.map +1 -1
  16. package/build/components/block-tools/zoom-out-mode-inserters.js +22 -36
  17. package/build/components/block-tools/zoom-out-mode-inserters.js.map +1 -1
  18. package/build/components/iframe/index.js +40 -10
  19. package/build/components/iframe/index.js.map +1 -1
  20. package/build/components/inserter/block-patterns-tab/index.js +4 -0
  21. package/build/components/inserter/block-patterns-tab/index.js.map +1 -1
  22. package/build/components/inserter/hooks/use-insertion-point.js +16 -4
  23. package/build/components/inserter/hooks/use-insertion-point.js.map +1 -1
  24. package/build/components/inserter/media-tab/media-tab.js +4 -0
  25. package/build/components/inserter/media-tab/media-tab.js.map +1 -1
  26. package/build/components/inserter/menu.js +5 -2
  27. package/build/components/inserter/menu.js.map +1 -1
  28. package/build/hooks/block-bindings.js +12 -1
  29. package/build/hooks/block-bindings.js.map +1 -1
  30. package/build/hooks/use-zoom-out.js +24 -16
  31. package/build/hooks/use-zoom-out.js.map +1 -1
  32. package/build/store/private-selectors.js +37 -2
  33. package/build/store/private-selectors.js.map +1 -1
  34. package/build/store/selectors.js +15 -8
  35. package/build/store/selectors.js.map +1 -1
  36. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js +14 -6
  37. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  38. package/build-module/components/block-list/zoom-out-separator.js +10 -7
  39. package/build-module/components/block-list/zoom-out-separator.js.map +1 -1
  40. package/build-module/components/block-popover/index.js +1 -1
  41. package/build-module/components/block-popover/index.js.map +1 -1
  42. package/build-module/components/block-toolbar/index.js +30 -18
  43. package/build-module/components/block-toolbar/index.js.map +1 -1
  44. package/build-module/components/block-toolbar/use-has-block-toolbar.js +3 -3
  45. package/build-module/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  46. package/build-module/components/block-tools/index.js +1 -6
  47. package/build-module/components/block-tools/index.js.map +1 -1
  48. package/build-module/components/block-tools/use-show-block-tools.js +4 -6
  49. package/build-module/components/block-tools/use-show-block-tools.js.map +1 -1
  50. package/build-module/components/block-tools/zoom-out-mode-inserters.js +22 -36
  51. package/build-module/components/block-tools/zoom-out-mode-inserters.js.map +1 -1
  52. package/build-module/components/iframe/index.js +40 -10
  53. package/build-module/components/iframe/index.js.map +1 -1
  54. package/build-module/components/inserter/block-patterns-tab/index.js +5 -1
  55. package/build-module/components/inserter/block-patterns-tab/index.js.map +1 -1
  56. package/build-module/components/inserter/hooks/use-insertion-point.js +16 -4
  57. package/build-module/components/inserter/hooks/use-insertion-point.js.map +1 -1
  58. package/build-module/components/inserter/media-tab/media-tab.js +5 -1
  59. package/build-module/components/inserter/media-tab/media-tab.js.map +1 -1
  60. package/build-module/components/inserter/menu.js +5 -2
  61. package/build-module/components/inserter/menu.js.map +1 -1
  62. package/build-module/hooks/block-bindings.js +13 -2
  63. package/build-module/hooks/block-bindings.js.map +1 -1
  64. package/build-module/hooks/use-zoom-out.js +24 -17
  65. package/build-module/hooks/use-zoom-out.js.map +1 -1
  66. package/build-module/store/private-selectors.js +35 -2
  67. package/build-module/store/private-selectors.js.map +1 -1
  68. package/build-module/store/selectors.js +15 -8
  69. package/build-module/store/selectors.js.map +1 -1
  70. package/build-style/content-rtl.css +14 -20
  71. package/build-style/content.css +14 -20
  72. package/build-style/style-rtl.css +28 -21
  73. package/build-style/style.css +28 -21
  74. package/package.json +6 -6
  75. package/src/components/block-canvas/style.scss +1 -0
  76. package/src/components/block-list/content.scss +3 -2
  77. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +25 -4
  78. package/src/components/block-list/zoom-out-separator.js +8 -6
  79. package/src/components/block-popover/index.js +2 -2
  80. package/src/components/block-toolbar/index.js +37 -24
  81. package/src/components/block-toolbar/style.scss +10 -1
  82. package/src/components/block-toolbar/use-has-block-toolbar.js +19 -28
  83. package/src/components/block-tools/index.js +0 -9
  84. package/src/components/block-tools/style.scss +2 -26
  85. package/src/components/block-tools/use-show-block-tools.js +2 -10
  86. package/src/components/block-tools/zoom-out-mode-inserters.js +26 -50
  87. package/src/components/iframe/content.scss +16 -24
  88. package/src/components/iframe/index.js +53 -12
  89. package/src/components/iframe/style.scss +6 -5
  90. package/src/components/inserter/block-patterns-tab/index.js +6 -1
  91. package/src/components/inserter/hooks/use-insertion-point.js +23 -5
  92. package/src/components/inserter/media-tab/media-tab.js +6 -1
  93. package/src/components/inserter/menu.js +7 -1
  94. package/src/components/inserter/style.scss +6 -0
  95. package/src/components/rich-text/style.scss +5 -0
  96. package/src/hooks/block-bindings.js +40 -23
  97. package/src/hooks/use-zoom-out.js +36 -20
  98. package/src/store/private-selectors.js +40 -1
  99. package/src/store/selectors.js +16 -8
  100. package/src/style.scss +1 -0
  101. package/build/components/block-tools/zoom-out-popover.js +0 -57
  102. package/build/components/block-tools/zoom-out-popover.js.map +0 -1
  103. package/build/components/block-tools/zoom-out-toolbar.js +0 -159
  104. package/build/components/block-tools/zoom-out-toolbar.js.map +0 -1
  105. package/build-module/components/block-tools/zoom-out-popover.js +0 -48
  106. package/build-module/components/block-tools/zoom-out-popover.js.map +0 -1
  107. package/build-module/components/block-tools/zoom-out-toolbar.js +0 -152
  108. package/build-module/components/block-tools/zoom-out-toolbar.js.map +0 -1
  109. package/src/components/block-tools/zoom-out-popover.js +0 -46
  110. package/src/components/block-tools/zoom-out-toolbar.js +0 -167
@@ -15,40 +15,31 @@ import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls
15
15
  * @return {boolean} Whether the block toolbar component will be rendered.
16
16
  */
17
17
  export function useHasBlockToolbar() {
18
- const { isToolbarEnabled, isDefaultEditingMode } = useSelect(
19
- ( select ) => {
20
- const {
21
- getBlockEditingMode,
22
- getBlockName,
23
- getBlockSelectionStart,
24
- } = select( blockEditorStore );
18
+ const { isToolbarEnabled, isBlockDisabled } = useSelect( ( select ) => {
19
+ const { getBlockEditingMode, getBlockName, getBlockSelectionStart } =
20
+ select( blockEditorStore );
25
21
 
26
- // we only care about the 1st selected block
27
- // for the toolbar, so we use getBlockSelectionStart
28
- // instead of getSelectedBlockClientIds
29
- const selectedBlockClientId = getBlockSelectionStart();
22
+ // we only care about the 1st selected block
23
+ // for the toolbar, so we use getBlockSelectionStart
24
+ // instead of getSelectedBlockClientIds
25
+ const selectedBlockClientId = getBlockSelectionStart();
30
26
 
31
- const blockType =
32
- selectedBlockClientId &&
33
- getBlockType( getBlockName( selectedBlockClientId ) );
27
+ const blockType =
28
+ selectedBlockClientId &&
29
+ getBlockType( getBlockName( selectedBlockClientId ) );
34
30
 
35
- return {
36
- isToolbarEnabled:
37
- blockType &&
38
- hasBlockSupport( blockType, '__experimentalToolbar', true ),
39
- isDefaultEditingMode:
40
- getBlockEditingMode( selectedBlockClientId ) === 'default',
41
- };
42
- },
43
- []
44
- );
31
+ return {
32
+ isToolbarEnabled:
33
+ blockType &&
34
+ hasBlockSupport( blockType, '__experimentalToolbar', true ),
35
+ isBlockDisabled:
36
+ getBlockEditingMode( selectedBlockClientId ) === 'disabled',
37
+ };
38
+ }, [] );
45
39
 
46
40
  const hasAnyBlockControls = useHasAnyBlockControls();
47
41
 
48
- if (
49
- ! isToolbarEnabled ||
50
- ( ! isDefaultEditingMode && ! hasAnyBlockControls )
51
- ) {
42
+ if ( ! isToolbarEnabled || ( isBlockDisabled && ! hasAnyBlockControls ) ) {
52
43
  return false;
53
44
  }
54
45
 
@@ -20,7 +20,6 @@ import {
20
20
  } from './insertion-point';
21
21
  import BlockToolbarPopover from './block-toolbar-popover';
22
22
  import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb';
23
- import ZoomOutPopover from './zoom-out-popover';
24
23
  import { store as blockEditorStore } from '../../store';
25
24
  import usePopoverScroll from '../block-popover/use-popover-scroll';
26
25
  import ZoomOutModeInserters from './zoom-out-mode-inserters';
@@ -80,7 +79,6 @@ export default function BlockTools( {
80
79
  showEmptyBlockSideInserter,
81
80
  showBreadcrumb,
82
81
  showBlockToolbarPopover,
83
- showZoomOutToolbar,
84
82
  } = useShowBlockTools();
85
83
 
86
84
  const {
@@ -231,13 +229,6 @@ export default function BlockTools( {
231
229
  />
232
230
  ) }
233
231
 
234
- { showZoomOutToolbar && (
235
- <ZoomOutPopover
236
- __unstableContentRef={ __unstableContentRef }
237
- clientId={ clientId }
238
- />
239
- ) }
240
-
241
232
  { /* Used for the inline rich text toolbar. Until this toolbar is combined into BlockToolbar, someone implementing their own BlockToolbar will also need to use this to see the image caption toolbar. */ }
242
233
  { ! isZoomOutMode && ! hasFixedToolbar && (
243
234
  <Popover.Slot
@@ -270,30 +270,6 @@
270
270
  left: 50%;
271
271
  }
272
272
 
273
- .zoom-out-toolbar {
274
-
275
- .block-editor-block-mover-button.block-editor-block-mover-button:focus-visible::before,
276
- .zoom-out-toolbar-button:focus::before,
277
- .block-editor-block-toolbar-shuffle:focus::before,
278
- .block-selection-button_drag-handle:focus::before {
279
- box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
280
- }
281
-
282
- .block-editor-block-mover {
283
- background: none;
284
- border: none;
285
- }
286
-
287
- // Make the spacing consistent between controls.
288
- .zoom-out-toolbar-button {
289
- height: $button-size-next-default-40px;
290
- }
291
- }
292
-
293
- .block-editor-block-tools__zoom-out-mode-inserter-button {
294
- visibility: hidden;
295
-
296
- &.is-visible {
297
- visibility: visible;
298
- }
273
+ .components-button.block-editor-button-pattern-inserter__button.block-editor-block-tools__zoom-out-mode-inserter-button {
274
+ top: -1px;
299
275
  }
@@ -8,6 +8,7 @@ import { isUnmodifiedDefaultBlock } from '@wordpress/blocks';
8
8
  * Internal dependencies
9
9
  */
10
10
  import { store as blockEditorStore } from '../../store';
11
+ import { unlock } from '../../lock-unlock';
11
12
 
12
13
  /**
13
14
  * Source of truth for which block tools are showing in the block editor.
@@ -25,7 +26,7 @@ export function useShowBlockTools() {
25
26
  hasMultiSelection,
26
27
  __unstableGetEditorMode,
27
28
  isTyping,
28
- } = select( blockEditorStore );
29
+ } = unlock( select( blockEditorStore ) );
29
30
 
30
31
  const clientId =
31
32
  getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId();
@@ -46,15 +47,7 @@ export function useShowBlockTools() {
46
47
  hasSelectedBlock &&
47
48
  ! hasMultiSelection() &&
48
49
  editorMode === 'navigation';
49
-
50
- const isZoomOut = editorMode === 'zoom-out';
51
- const _showZoomOutToolbar =
52
- isZoomOut &&
53
- block?.attributes?.align === 'full' &&
54
- ! _showEmptyBlockSideInserter &&
55
- ! maybeShowBreadcrumb;
56
50
  const _showBlockToolbarPopover =
57
- ! _showZoomOutToolbar &&
58
51
  ! getSettings().hasFixedToolbar &&
59
52
  ! _showEmptyBlockSideInserter &&
60
53
  hasSelectedBlock &&
@@ -66,7 +59,6 @@ export function useShowBlockTools() {
66
59
  showBreadcrumb:
67
60
  ! _showEmptyBlockSideInserter && maybeShowBreadcrumb,
68
61
  showBlockToolbarPopover: _showBlockToolbarPopover,
69
- showZoomOutToolbar: _showZoomOutToolbar,
70
62
  };
71
63
  }, [] );
72
64
  }
@@ -16,22 +16,16 @@ function ZoomOutModeInserters() {
16
16
  const [ isReady, setIsReady ] = useState( false );
17
17
  const {
18
18
  hasSelection,
19
- blockInsertionPoint,
20
19
  blockOrder,
21
- blockInsertionPointVisible,
22
20
  setInserterIsOpened,
23
21
  sectionRootClientId,
24
22
  selectedBlockClientId,
25
- hoveredBlockClientId,
26
23
  } = useSelect( ( select ) => {
27
24
  const {
28
25
  getSettings,
29
- getBlockInsertionPoint,
30
26
  getBlockOrder,
31
27
  getSelectionStart,
32
28
  getSelectedBlockClientId,
33
- getHoveredBlockClientId,
34
- isBlockInsertionPointVisible,
35
29
  getSectionRootClientId,
36
30
  } = unlock( select( blockEditorStore ) );
37
31
 
@@ -39,14 +33,11 @@ function ZoomOutModeInserters() {
39
33
 
40
34
  return {
41
35
  hasSelection: !! getSelectionStart().clientId,
42
- blockInsertionPoint: getBlockInsertionPoint(),
43
36
  blockOrder: getBlockOrder( root ),
44
- blockInsertionPointVisible: isBlockInsertionPointVisible(),
45
37
  sectionRootClientId: root,
46
38
  setInserterIsOpened:
47
39
  getSettings().__experimentalSetIsInserterOpened,
48
40
  selectedBlockClientId: getSelectedBlockClientId(),
49
- hoveredBlockClientId: getHoveredBlockClientId(),
50
41
  };
51
42
  }, [] );
52
43
 
@@ -62,51 +53,36 @@ function ZoomOutModeInserters() {
62
53
  };
63
54
  }, [] );
64
55
 
65
- if ( ! isReady ) {
56
+ if ( ! isReady || ! hasSelection ) {
66
57
  return null;
67
58
  }
68
59
 
69
- return [ undefined, ...blockOrder ].map( ( clientId, index ) => {
70
- const shouldRenderInsertionPoint =
71
- blockInsertionPointVisible && blockInsertionPoint.index === index;
60
+ const previousClientId = selectedBlockClientId;
61
+ const index = blockOrder.findIndex(
62
+ ( clientId ) => selectedBlockClientId === clientId
63
+ );
64
+ const nextClientId = blockOrder[ index + 1 ];
72
65
 
73
- const previousClientId = clientId;
74
- const nextClientId = blockOrder[ index ];
75
-
76
- const isSelected =
77
- hasSelection &&
78
- ( selectedBlockClientId === previousClientId ||
79
- selectedBlockClientId === nextClientId );
80
-
81
- const isHovered =
82
- hoveredBlockClientId === previousClientId ||
83
- hoveredBlockClientId === nextClientId;
84
-
85
- return (
86
- <BlockPopoverInbetween
87
- key={ index }
88
- previousClientId={ previousClientId }
89
- nextClientId={ nextClientId }
90
- >
91
- { ! shouldRenderInsertionPoint && (
92
- <ZoomOutModeInserterButton
93
- isVisible={ isSelected || isHovered }
94
- onClick={ () => {
95
- setInserterIsOpened( {
96
- rootClientId: sectionRootClientId,
97
- insertionIndex: index,
98
- tab: 'patterns',
99
- category: 'all',
100
- } );
101
- showInsertionPoint( sectionRootClientId, index, {
102
- operation: 'insert',
103
- } );
104
- } }
105
- />
106
- ) }
107
- </BlockPopoverInbetween>
108
- );
109
- } );
66
+ return (
67
+ <BlockPopoverInbetween
68
+ previousClientId={ previousClientId }
69
+ nextClientId={ nextClientId }
70
+ >
71
+ <ZoomOutModeInserterButton
72
+ onClick={ () => {
73
+ setInserterIsOpened( {
74
+ rootClientId: sectionRootClientId,
75
+ insertionIndex: index + 1,
76
+ tab: 'patterns',
77
+ category: 'all',
78
+ } );
79
+ showInsertionPoint( sectionRootClientId, index + 1, {
80
+ operation: 'insert',
81
+ } );
82
+ } }
83
+ />
84
+ </BlockPopoverInbetween>
85
+ );
110
86
  }
111
87
 
112
88
  export default ZoomOutModeInserters;
@@ -3,28 +3,19 @@
3
3
  border: 0.01px solid transparent;
4
4
  }
5
5
 
6
- .block-editor-iframe__container {
7
- width: 100%;
8
- height: 100%;
9
- overflow-x: hidden;
10
- }
11
-
12
- .block-editor-iframe__scale-container {
13
- width: 100%;
14
- height: 100%;
15
- display: flex;
16
- }
17
-
18
- .block-editor-iframe__scale-container.is-zoomed-out {
19
- $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
20
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw);
21
- width: $prev-container-width;
22
- margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2);
23
- }
24
-
25
6
  .block-editor-iframe__html {
26
7
  transform-origin: top center;
27
- @include editor-canvas-resize-animation;
8
+ // We don't want to animate the transform of the translateX because it is used
9
+ // to "center" the canvas. Leaving it on causes the canvas to slide around in
10
+ // odd ways.
11
+ @include editor-canvas-resize-animation(transform 0s, scale 0s, padding 0s);
12
+
13
+ &.zoom-out-animation {
14
+ // we only want to animate the scaling when entering zoom out. When sidebars
15
+ // are toggled, the resizing of the iframe handles scaling the canvas as well,
16
+ // and the doubled animations cause very odd animations.
17
+ @include editor-canvas-resize-animation(transform 0s);
18
+ }
28
19
  }
29
20
 
30
21
  .block-editor-iframe__html.is-zoomed-out {
@@ -32,10 +23,11 @@
32
23
  $frame-size: var(--wp-block-editor-iframe-zoom-out-frame-size);
33
24
  $inner-height: var(--wp-block-editor-iframe-zoom-out-inner-height);
34
25
  $content-height: var(--wp-block-editor-iframe-zoom-out-content-height);
35
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width);
36
-
37
- transform: scale(#{$scale});
38
-
26
+ $scale-container-width: var(--wp-block-editor-iframe-zoom-out-scale-container-width);
27
+ $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
28
+ // Apply an X translation to center the scaled content within the available space.
29
+ transform: translateX(calc((#{$scale-container-width} - #{$container-width}) / 2 / #{$scale}));
30
+ scale: #{$scale};
39
31
  background-color: $gray-300;
40
32
 
41
33
  // Chrome seems to respect that transform scale shouldn't affect the layout size of the element,
@@ -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,14 +303,52 @@ 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
+
309
352
  // This scaling calculation has to happen within the JS because CSS calc() can
310
353
  // only divide and multiply by a unitless value. I.e. calc( 100px / 2 ) is valid
311
354
  // but calc( 100px / 2px ) is not.
@@ -314,7 +357,7 @@ function Iframe( {
314
357
  scale === 'default'
315
358
  ? ( Math.min( containerWidth, maxWidth ) -
316
359
  parseInt( frameSize ) * 2 ) /
317
- prevContainerWidthRef.current
360
+ scaleContainerWidth
318
361
  : scale
319
362
  );
320
363
 
@@ -336,13 +379,11 @@ function Iframe( {
336
379
  `${ containerWidth }px`
337
380
  );
338
381
  iframeDocument.documentElement.style.setProperty(
339
- '--wp-block-editor-iframe-zoom-out-prev-container-width',
340
- `${ prevContainerWidthRef.current }px`
382
+ '--wp-block-editor-iframe-zoom-out-scale-container-width',
383
+ `${ scaleContainerWidth }px`
341
384
  );
342
385
 
343
386
  return () => {
344
- iframeDocument.documentElement.classList.remove( 'is-zoomed-out' );
345
-
346
387
  iframeDocument.documentElement.style.removeProperty(
347
388
  '--wp-block-editor-iframe-zoom-out-scale'
348
389
  );
@@ -359,7 +400,7 @@ function Iframe( {
359
400
  '--wp-block-editor-iframe-zoom-out-container-width'
360
401
  );
361
402
  iframeDocument.documentElement.style.removeProperty(
362
- '--wp-block-editor-iframe-zoom-out-prev-container-width'
403
+ '--wp-block-editor-iframe-zoom-out-scale-container-width'
363
404
  );
364
405
  };
365
406
  }, [
@@ -371,6 +412,7 @@ function Iframe( {
371
412
  containerWidth,
372
413
  windowInnerWidth,
373
414
  isZoomedOut,
415
+ scaleContainerWidth,
374
416
  ] );
375
417
 
376
418
  // Make sure to not render the before and after focusable div elements in view
@@ -386,6 +428,7 @@ function Iframe( {
386
428
  style={ {
387
429
  ...props.style,
388
430
  height: props.style?.height,
431
+ border: 0,
389
432
  } }
390
433
  ref={ useMergeRefs( [ ref, setRef ] ) }
391
434
  tabIndex={ tabIndex }
@@ -459,10 +502,8 @@ function Iframe( {
459
502
  isZoomedOut && 'is-zoomed-out'
460
503
  ) }
461
504
  style={ {
462
- '--wp-block-editor-iframe-zoom-out-container-width':
463
- isZoomedOut && `${ containerWidth }px`,
464
- '--wp-block-editor-iframe-zoom-out-prev-container-width':
465
- isZoomedOut && `${ prevContainerWidthRef.current }px`,
505
+ '--wp-block-editor-iframe-zoom-out-scale-container-width':
506
+ isZoomedOut && `${ scaleContainerWidth }px`,
466
507
  } }
467
508
  >
468
509
  { iframe }
@@ -9,9 +9,10 @@
9
9
  }
10
10
 
11
11
  .block-editor-iframe__scale-container.is-zoomed-out {
12
- $container-width: var(--wp-block-editor-iframe-zoom-out-container-width, 100vw);
13
- $prev-container-width: var(--wp-block-editor-iframe-zoom-out-prev-container-width, 100vw);
14
- width: $prev-container-width;
15
- // This is to offset the movement of the iframe when we open sidebars
16
- margin-left: calc(-1 * (#{$prev-container-width} - #{$container-width}) / 2);
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;
17
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
  }
@@ -67,6 +67,8 @@ function InserterMenu(
67
67
  const [ patternFilter, setPatternFilter ] = useState( 'all' );
68
68
  const [ selectedMediaCategory, setSelectedMediaCategory ] =
69
69
  useState( null );
70
+
71
+ const [ hasCategories, setHasCategories ] = useState( true );
70
72
  function getInitialTab() {
71
73
  if ( __experimentalInitialTab ) {
72
74
  return __experimentalInitialTab;
@@ -146,10 +148,12 @@ function InserterMenu(
146
148
 
147
149
  const showPatternPanel =
148
150
  selectedTab === 'patterns' &&
151
+ hasCategories &&
149
152
  ! delayedFilterValue &&
150
153
  !! selectedPatternCategory;
151
154
 
152
- const showMediaPanel = selectedTab === 'media' && !! selectedMediaCategory;
155
+ const showMediaPanel =
156
+ selectedTab === 'media' && !! selectedMediaCategory && hasCategories;
153
157
 
154
158
  const inserterSearch = useMemo( () => {
155
159
  if ( selectedTab === 'media' ) {
@@ -242,6 +246,7 @@ function InserterMenu(
242
246
  onInsert={ onInsertPattern }
243
247
  onSelectCategory={ onClickPatternCategory }
244
248
  selectedCategory={ selectedPatternCategory }
249
+ setHasCategories={ setHasCategories }
245
250
  >
246
251
  { showPatternPanel && (
247
252
  <PatternCategoryPreviews
@@ -270,6 +275,7 @@ function InserterMenu(
270
275
  selectedCategory={ selectedMediaCategory }
271
276
  onSelectCategory={ setSelectedMediaCategory }
272
277
  onInsert={ onInsert }
278
+ setHasCategories={ setHasCategories }
273
279
  >
274
280
  { showMediaPanel && (
275
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;
@@ -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;