@wordpress/block-editor 14.3.1 → 14.3.3

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 (137) hide show
  1. package/README.md +2 -2
  2. package/build/components/block-heading-level-dropdown/index.js +3 -1
  3. package/build/components/block-heading-level-dropdown/index.js.map +1 -1
  4. package/build/components/block-list/block.js +27 -4
  5. package/build/components/block-list/block.js.map +1 -1
  6. package/build/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  7. package/build/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  8. package/build/components/block-list/use-block-props/use-zoom-out-mode-exit.js +9 -4
  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 +18 -1
  11. package/build/components/block-list/zoom-out-separator.js.map +1 -1
  12. package/build/components/block-switcher/utils.js +1 -1
  13. package/build/components/block-switcher/utils.js.map +1 -1
  14. package/build/components/block-tools/zoom-out-toolbar.js +5 -2
  15. package/build/components/block-tools/zoom-out-toolbar.js.map +1 -1
  16. package/build/components/block-variation-transforms/index.js +12 -6
  17. package/build/components/block-variation-transforms/index.js.map +1 -1
  18. package/build/components/rich-text/event-listeners/paste-handler.js +2 -13
  19. package/build/components/rich-text/event-listeners/paste-handler.js.map +1 -1
  20. package/build/components/rich-text/index.js +34 -20
  21. package/build/components/rich-text/index.js.map +1 -1
  22. package/build/components/tool-selector/index.js +2 -1
  23. package/build/components/tool-selector/index.js.map +1 -1
  24. package/build/components/writing-flow/index.js +1 -2
  25. package/build/components/writing-flow/index.js.map +1 -1
  26. package/build/components/writing-flow/use-arrow-nav.js +1 -4
  27. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  28. package/build/components/writing-flow/use-input.js +1 -31
  29. package/build/components/writing-flow/use-input.js.map +1 -1
  30. package/build/components/writing-flow/use-select-all.js +1 -14
  31. package/build/components/writing-flow/use-select-all.js.map +1 -1
  32. package/build/components/writing-flow/use-selection-observer.js +2 -6
  33. package/build/components/writing-flow/use-selection-observer.js.map +1 -1
  34. package/build/components/writing-flow/utils.js +0 -27
  35. package/build/components/writing-flow/utils.js.map +1 -1
  36. package/build/hooks/layout.js +12 -8
  37. package/build/hooks/layout.js.map +1 -1
  38. package/build/hooks/use-bindings-attributes.js +22 -28
  39. package/build/hooks/use-bindings-attributes.js.map +1 -1
  40. package/build/hooks/use-zoom-out.js +20 -23
  41. package/build/hooks/use-zoom-out.js.map +1 -1
  42. package/build/store/private-actions.js +25 -0
  43. package/build/store/private-actions.js.map +1 -1
  44. package/build/store/private-selectors.js +22 -0
  45. package/build/store/private-selectors.js.map +1 -1
  46. package/build/store/reducer.js +21 -1
  47. package/build/store/reducer.js.map +1 -1
  48. package/build/store/selectors.js +12 -5
  49. package/build/store/selectors.js.map +1 -1
  50. package/build-module/components/block-heading-level-dropdown/index.js +3 -1
  51. package/build-module/components/block-heading-level-dropdown/index.js.map +1 -1
  52. package/build-module/components/block-list/block.js +28 -7
  53. package/build-module/components/block-list/block.js.map +1 -1
  54. package/build-module/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  55. package/build-module/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  56. package/build-module/components/block-list/use-block-props/use-zoom-out-mode-exit.js +9 -4
  57. package/build-module/components/block-list/use-block-props/use-zoom-out-mode-exit.js.map +1 -1
  58. package/build-module/components/block-list/zoom-out-separator.js +18 -1
  59. package/build-module/components/block-list/zoom-out-separator.js.map +1 -1
  60. package/build-module/components/block-switcher/utils.js +1 -1
  61. package/build-module/components/block-switcher/utils.js.map +1 -1
  62. package/build-module/components/block-tools/zoom-out-toolbar.js +5 -2
  63. package/build-module/components/block-tools/zoom-out-toolbar.js.map +1 -1
  64. package/build-module/components/block-variation-transforms/index.js +12 -6
  65. package/build-module/components/block-variation-transforms/index.js.map +1 -1
  66. package/build-module/components/rich-text/event-listeners/paste-handler.js +2 -13
  67. package/build-module/components/rich-text/event-listeners/paste-handler.js.map +1 -1
  68. package/build-module/components/rich-text/index.js +34 -20
  69. package/build-module/components/rich-text/index.js.map +1 -1
  70. package/build-module/components/tool-selector/index.js +2 -1
  71. package/build-module/components/tool-selector/index.js.map +1 -1
  72. package/build-module/components/writing-flow/index.js +1 -2
  73. package/build-module/components/writing-flow/index.js.map +1 -1
  74. package/build-module/components/writing-flow/use-arrow-nav.js +1 -4
  75. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  76. package/build-module/components/writing-flow/use-input.js +1 -31
  77. package/build-module/components/writing-flow/use-input.js.map +1 -1
  78. package/build-module/components/writing-flow/use-select-all.js +1 -14
  79. package/build-module/components/writing-flow/use-select-all.js.map +1 -1
  80. package/build-module/components/writing-flow/use-selection-observer.js +2 -6
  81. package/build-module/components/writing-flow/use-selection-observer.js.map +1 -1
  82. package/build-module/components/writing-flow/utils.js +0 -26
  83. package/build-module/components/writing-flow/utils.js.map +1 -1
  84. package/build-module/hooks/layout.js +13 -9
  85. package/build-module/hooks/layout.js.map +1 -1
  86. package/build-module/hooks/use-bindings-attributes.js +22 -28
  87. package/build-module/hooks/use-bindings-attributes.js.map +1 -1
  88. package/build-module/hooks/use-zoom-out.js +20 -23
  89. package/build-module/hooks/use-zoom-out.js.map +1 -1
  90. package/build-module/store/private-actions.js +23 -0
  91. package/build-module/store/private-actions.js.map +1 -1
  92. package/build-module/store/private-selectors.js +20 -0
  93. package/build-module/store/private-selectors.js.map +1 -1
  94. package/build-module/store/reducer.js +20 -1
  95. package/build-module/store/reducer.js.map +1 -1
  96. package/build-module/store/selectors.js +12 -5
  97. package/build-module/store/selectors.js.map +1 -1
  98. package/build-style/content-rtl.css +10 -0
  99. package/build-style/content.css +10 -0
  100. package/build-style/style-rtl.css +4 -0
  101. package/build-style/style.css +4 -0
  102. package/package.json +20 -20
  103. package/src/components/block-heading-level-dropdown/index.js +7 -1
  104. package/src/components/block-list/block.js +47 -11
  105. package/src/components/block-list/content.scss +12 -0
  106. package/src/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  107. package/src/components/block-list/use-block-props/use-zoom-out-mode-exit.js +7 -3
  108. package/src/components/block-list/zoom-out-separator.js +14 -1
  109. package/src/components/block-switcher/test/use-transformed.patterns.js +3 -3
  110. package/src/components/block-switcher/test/utils.js +3 -3
  111. package/src/components/block-switcher/utils.js +1 -1
  112. package/src/components/block-toolbar/style.scss +7 -0
  113. package/src/components/block-tools/zoom-out-toolbar.js +5 -2
  114. package/src/components/block-variation-transforms/index.js +13 -4
  115. package/src/components/rich-text/event-listeners/paste-handler.js +2 -7
  116. package/src/components/rich-text/index.js +36 -23
  117. package/src/components/tool-selector/index.js +4 -1
  118. package/src/components/writing-flow/index.js +0 -2
  119. package/src/components/writing-flow/use-arrow-nav.js +2 -9
  120. package/src/components/writing-flow/use-input.js +1 -36
  121. package/src/components/writing-flow/use-select-all.js +1 -18
  122. package/src/components/writing-flow/use-selection-observer.js +3 -14
  123. package/src/components/writing-flow/utils.js +0 -30
  124. package/src/hooks/layout.js +17 -12
  125. package/src/hooks/use-bindings-attributes.js +26 -32
  126. package/src/hooks/use-zoom-out.js +21 -27
  127. package/src/store/private-actions.js +23 -0
  128. package/src/store/private-selectors.js +20 -0
  129. package/src/store/reducer.js +20 -0
  130. package/src/store/selectors.js +13 -8
  131. package/src/store/test/private-selectors.js +2 -2
  132. package/src/store/test/selectors.js +10 -6
  133. package/build/components/writing-flow/use-event-redirect.js +0 -66
  134. package/build/components/writing-flow/use-event-redirect.js.map +0 -1
  135. package/build-module/components/writing-flow/use-event-redirect.js +0 -60
  136. package/build-module/components/writing-flow/use-event-redirect.js.map +0 -1
  137. package/src/components/writing-flow/use-event-redirect.js +0 -72
@@ -497,6 +497,16 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
497
497
  margin-right: -1px;
498
498
  margin-left: -1px;
499
499
  transition: background-color 0.3s ease;
500
+ display: flex;
501
+ align-items: center;
502
+ justify-content: center;
503
+ font-size: 13px;
504
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
505
+ color: #000;
506
+ font-weight: normal;
507
+ }
508
+ .is-zoomed-out .block-editor-block-list__zoom-out-separator {
509
+ font-size: calc(13px * ( 2 - var(--wp-block-editor-iframe-zoom-out-scale) ));
500
510
  }
501
511
  .block-editor-block-list__zoom-out-separator.is-dragged-over {
502
512
  background: #ccc;
@@ -497,6 +497,16 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
497
497
  margin-left: -1px;
498
498
  margin-right: -1px;
499
499
  transition: background-color 0.3s ease;
500
+ display: flex;
501
+ align-items: center;
502
+ justify-content: center;
503
+ font-size: 13px;
504
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
505
+ color: #000;
506
+ font-weight: normal;
507
+ }
508
+ .is-zoomed-out .block-editor-block-list__zoom-out-separator {
509
+ font-size: calc(13px * ( 2 - var(--wp-block-editor-iframe-zoom-out-scale) ));
500
510
  }
501
511
  .block-editor-block-list__zoom-out-separator.is-dragged-over {
502
512
  background: #ccc;
@@ -3465,6 +3465,10 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3465
3465
  border: 0;
3466
3466
  border-left: 1px solid #ddd;
3467
3467
  }
3468
+ .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button::before {
3469
+ background: color-mix(in srgb, var(--wp-block-synced-color) 10%, transparent);
3470
+ border-radius: 2px;
3471
+ }
3468
3472
  .block-editor-block-toolbar.is-synced .block-editor-block-switcher .components-button .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button .block-editor-block-icon {
3469
3473
  color: var(--wp-block-synced-color);
3470
3474
  }
@@ -3466,6 +3466,10 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3466
3466
  border: 0;
3467
3467
  border-right: 1px solid #ddd;
3468
3468
  }
3469
+ .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button::before {
3470
+ background: color-mix(in srgb, var(--wp-block-synced-color) 10%, transparent);
3471
+ border-radius: 2px;
3472
+ }
3469
3473
  .block-editor-block-toolbar.is-synced .block-editor-block-switcher .components-button .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button .block-editor-block-icon {
3470
3474
  color: var(--wp-block-synced-color);
3471
3475
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "14.3.1",
3
+ "version": "14.3.3",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -36,31 +36,31 @@
36
36
  "@emotion/react": "^11.7.1",
37
37
  "@emotion/styled": "^11.6.0",
38
38
  "@react-spring/web": "^9.4.5",
39
- "@wordpress/a11y": "^4.8.1",
40
- "@wordpress/api-fetch": "^7.8.1",
39
+ "@wordpress/a11y": "^4.8.2",
40
+ "@wordpress/api-fetch": "^7.8.2",
41
41
  "@wordpress/blob": "^4.8.1",
42
42
  "@wordpress/block-serialization-default-parser": "^5.8.1",
43
- "@wordpress/blocks": "^13.8.1",
44
- "@wordpress/commands": "^1.8.1",
45
- "@wordpress/components": "^28.8.1",
46
- "@wordpress/compose": "^7.8.1",
47
- "@wordpress/data": "^10.8.1",
48
- "@wordpress/date": "^5.8.1",
49
- "@wordpress/deprecated": "^4.8.1",
50
- "@wordpress/dom": "^4.8.1",
43
+ "@wordpress/blocks": "^13.8.3",
44
+ "@wordpress/commands": "^1.8.3",
45
+ "@wordpress/components": "^28.8.3",
46
+ "@wordpress/compose": "^7.8.3",
47
+ "@wordpress/data": "^10.8.3",
48
+ "@wordpress/date": "^5.8.2",
49
+ "@wordpress/deprecated": "^4.8.2",
50
+ "@wordpress/dom": "^4.8.2",
51
51
  "@wordpress/element": "^6.8.1",
52
52
  "@wordpress/escape-html": "^3.8.1",
53
- "@wordpress/hooks": "^4.8.1",
53
+ "@wordpress/hooks": "^4.8.2",
54
54
  "@wordpress/html-entities": "^4.8.1",
55
- "@wordpress/i18n": "^5.8.1",
56
- "@wordpress/icons": "^10.8.1",
55
+ "@wordpress/i18n": "^5.8.2",
56
+ "@wordpress/icons": "^10.8.2",
57
57
  "@wordpress/is-shallow-equal": "^5.8.1",
58
- "@wordpress/keyboard-shortcuts": "^5.8.1",
59
- "@wordpress/keycodes": "^4.8.1",
60
- "@wordpress/notices": "^5.8.1",
61
- "@wordpress/preferences": "^4.8.1",
58
+ "@wordpress/keyboard-shortcuts": "^5.8.3",
59
+ "@wordpress/keycodes": "^4.8.2",
60
+ "@wordpress/notices": "^5.8.3",
61
+ "@wordpress/preferences": "^4.8.3",
62
62
  "@wordpress/private-apis": "^1.8.1",
63
- "@wordpress/rich-text": "^7.8.1",
63
+ "@wordpress/rich-text": "^7.8.3",
64
64
  "@wordpress/style-engine": "^2.8.1",
65
65
  "@wordpress/token-list": "^3.8.1",
66
66
  "@wordpress/url": "^4.8.1",
@@ -88,5 +88,5 @@
88
88
  "publishConfig": {
89
89
  "access": "public"
90
90
  },
91
- "gitHead": "cf707c1f25a2716e310cc8f9afcc8554405c79ac"
91
+ "gitHead": "6187079697e13c3292eb098d6338523a6676c6e8"
92
92
  }
@@ -40,12 +40,18 @@ export default function HeadingLevelDropdown( {
40
40
  value,
41
41
  onChange,
42
42
  } ) {
43
+ const validOptions = options
44
+ .filter(
45
+ ( option ) => option === 0 || HEADING_LEVELS.includes( option )
46
+ )
47
+ .sort( ( a, b ) => a - b ); // Sorts numerically in ascending order;
48
+
43
49
  return (
44
50
  <ToolbarDropdownMenu
45
51
  popoverProps={ POPOVER_PROPS }
46
52
  icon={ <HeadingLevelIcon level={ value } /> }
47
53
  label={ __( 'Change level' ) }
48
- controls={ options.map( ( targetLevel ) => {
54
+ controls={ validOptions.map( ( targetLevel ) => {
49
55
  const isActive = targetLevel === value;
50
56
  return {
51
57
  icon: <HeadingLevelIcon level={ targetLevel } />,
@@ -25,6 +25,7 @@ import {
25
25
  getBlockDefaultClassName,
26
26
  hasBlockSupport,
27
27
  store as blocksStore,
28
+ privateApis as blocksPrivateApis,
28
29
  } from '@wordpress/blocks';
29
30
  import { withFilters } from '@wordpress/components';
30
31
  import { withDispatch, useDispatch, useSelect } from '@wordpress/data';
@@ -46,6 +47,8 @@ import { PrivateBlockContext } from './private-block-context';
46
47
 
47
48
  import { unlock } from '../../lock-unlock';
48
49
 
50
+ const { isUnmodifiedBlockContent } = unlock( blocksPrivateApis );
51
+
49
52
  /**
50
53
  * Merges wrapper props with special handling for classNames and styles.
51
54
  *
@@ -350,12 +353,48 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
350
353
  removeBlock( _clientId );
351
354
  } else {
352
355
  registry.batch( () => {
356
+ const firstBlock = getBlock( firstClientId );
357
+ const isFirstBlockContentUnmodified =
358
+ isUnmodifiedBlockContent( firstBlock );
359
+ const defaultBlockName = getDefaultBlockName();
360
+ const replacement = switchToBlockType(
361
+ firstBlock,
362
+ defaultBlockName
363
+ );
364
+ const canTransformToDefaultBlock =
365
+ !! replacement?.length &&
366
+ replacement.every( ( block ) =>
367
+ canInsertBlockType( block.name, _clientId )
368
+ );
369
+
353
370
  if (
371
+ isFirstBlockContentUnmodified &&
372
+ canTransformToDefaultBlock
373
+ ) {
374
+ // Step 1: If the block is empty and can be transformed to the default block type.
375
+ replaceBlocks(
376
+ firstClientId,
377
+ replacement,
378
+ changeSelection
379
+ );
380
+ } else if (
381
+ isFirstBlockContentUnmodified &&
382
+ firstBlock.name === defaultBlockName
383
+ ) {
384
+ // Step 2: If the block is empty and is already the default block type.
385
+ removeBlock( firstClientId );
386
+ const nextBlockClientId =
387
+ getNextBlockClientId( clientId );
388
+ if ( nextBlockClientId ) {
389
+ selectBlock( nextBlockClientId );
390
+ }
391
+ } else if (
354
392
  canInsertBlockType(
355
- getBlockName( firstClientId ),
393
+ firstBlock.name,
356
394
  targetRootClientId
357
395
  )
358
396
  ) {
397
+ // Step 3: If the block can be moved up.
359
398
  moveBlocksToPosition(
360
399
  [ firstClientId ],
361
400
  _clientId,
@@ -363,21 +402,17 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
363
402
  getBlockIndex( _clientId )
364
403
  );
365
404
  } else {
366
- const replacement = switchToBlockType(
367
- getBlock( firstClientId ),
368
- getDefaultBlockName()
369
- );
370
-
371
- if (
372
- replacement &&
373
- replacement.length &&
405
+ const canLiftAndTransformToDefaultBlock =
406
+ !! replacement?.length &&
374
407
  replacement.every( ( block ) =>
375
408
  canInsertBlockType(
376
409
  block.name,
377
410
  targetRootClientId
378
411
  )
379
- )
380
- ) {
412
+ );
413
+
414
+ if ( canLiftAndTransformToDefaultBlock ) {
415
+ // Step 4: If the block can be transformed to the default block type and moved up.
381
416
  insertBlocks(
382
417
  replacement,
383
418
  getBlockIndex( _clientId ),
@@ -386,6 +421,7 @@ const applyWithDispatch = withDispatch( ( dispatch, ownProps, registry ) => {
386
421
  );
387
422
  removeBlock( firstClientId, false );
388
423
  } else {
424
+ // Step 5: Continue the default behavior.
389
425
  switchToDefaultOrRemove();
390
426
  }
391
427
  }
@@ -461,6 +461,18 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
461
461
  margin-left: -1px;
462
462
  margin-right: -1px;
463
463
  transition: background-color 0.3s ease;
464
+ display: flex;
465
+ align-items: center;
466
+ justify-content: center;
467
+ font-size: $default-font-size;
468
+ font-family: $default-font;
469
+ color: $black;
470
+ font-weight: normal;
471
+
472
+ .is-zoomed-out & {
473
+ // Scale the font size based on the zoom level.
474
+ font-size: calc(#{$default-font-size} * ( 2 - var(--wp-block-editor-iframe-zoom-out-scale) ));
475
+ }
464
476
 
465
477
  &.is-dragged-over {
466
478
  background: $gray-400;
@@ -68,7 +68,6 @@ export function useFocusFirstElement( { clientId, initialPosition } ) {
68
68
  textInputs[ isReverse ? textInputs.length - 1 : 0 ] || ref.current;
69
69
 
70
70
  if ( ! isInsideRootBlock( ref.current, target ) ) {
71
- ownerDocument.defaultView.getSelection().removeAllRanges();
72
71
  ref.current.focus();
73
72
  return;
74
73
  }
@@ -16,14 +16,17 @@ import { unlock } from '../../../lock-unlock';
16
16
  * @param {string} clientId Block client ID.
17
17
  */
18
18
  export function useZoomOutModeExit( { editorMode } ) {
19
- const { getSettings } = useSelect( blockEditorStore );
20
- const { __unstableSetEditorMode } = unlock(
19
+ const { getSettings, isZoomOut } = unlock( useSelect( blockEditorStore ) );
20
+ const { __unstableSetEditorMode, resetZoomLevel } = unlock(
21
21
  useDispatch( blockEditorStore )
22
22
  );
23
23
 
24
24
  return useRefEffect(
25
25
  ( node ) => {
26
- if ( editorMode !== 'zoom-out' ) {
26
+ // In "compose" mode.
27
+ const composeMode = editorMode === 'zoom-out' && isZoomOut();
28
+
29
+ if ( ! composeMode ) {
27
30
  return;
28
31
  }
29
32
 
@@ -39,6 +42,7 @@ export function useZoomOutModeExit( { editorMode } ) {
39
42
  __experimentalSetIsInserterOpened( false );
40
43
  }
41
44
  __unstableSetEditorMode( 'edit' );
45
+ resetZoomLevel();
42
46
  }
43
47
  }
44
48
 
@@ -13,6 +13,7 @@ import {
13
13
  import { useReducedMotion } from '@wordpress/compose';
14
14
  import { useSelect } from '@wordpress/data';
15
15
  import { useState } from '@wordpress/element';
16
+ import { __ } from '@wordpress/i18n';
16
17
 
17
18
  /**
18
19
  * Internal dependencies
@@ -103,7 +104,19 @@ export function ZoomOutSeparator( {
103
104
  data-is-insertion-point="true"
104
105
  onDragOver={ () => setIsDraggedOver( true ) }
105
106
  onDragLeave={ () => setIsDraggedOver( false ) }
106
- ></motion.div>
107
+ >
108
+ <motion.div
109
+ initial={ { opacity: 0 } }
110
+ animate={ { opacity: 1 } }
111
+ exit={ { opacity: 0 } }
112
+ transition={ {
113
+ type: 'tween',
114
+ duration: 0.1,
115
+ } }
116
+ >
117
+ { __( 'Drop pattern.' ) }
118
+ </motion.div>
119
+ </motion.div>
107
120
  ) }
108
121
  </AnimatePresence>
109
122
  );
@@ -20,15 +20,15 @@ describe( 'use-transformed-patterns', () => {
20
20
  },
21
21
  content: {
22
22
  type: 'boolean',
23
- __experimentalRole: 'content',
23
+ role: 'content',
24
24
  },
25
25
  level: {
26
26
  type: 'number',
27
- __experimentalRole: 'content',
27
+ role: 'content',
28
28
  },
29
29
  color: {
30
30
  type: 'string',
31
- __experimentalRole: 'other',
31
+ role: 'other',
32
32
  },
33
33
  },
34
34
  save() {},
@@ -18,15 +18,15 @@ describe( 'BlockSwitcher - utils', () => {
18
18
  },
19
19
  content: {
20
20
  type: 'boolean',
21
- __experimentalRole: 'content',
21
+ role: 'content',
22
22
  },
23
23
  level: {
24
24
  type: 'number',
25
- __experimentalRole: 'content',
25
+ role: 'content',
26
26
  },
27
27
  color: {
28
28
  type: 'string',
29
- __experimentalRole: 'other',
29
+ role: 'other',
30
30
  },
31
31
  },
32
32
  save() {},
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { __experimentalGetBlockAttributesNamesByRole as getBlockAttributesNamesByRole } from '@wordpress/blocks';
4
+ import { getBlockAttributesNamesByRole } from '@wordpress/blocks';
5
5
 
6
6
  /**
7
7
  * Try to find a matching block by a block's name in a provided
@@ -37,6 +37,13 @@
37
37
  border-right: $border-width solid $gray-300;
38
38
  }
39
39
 
40
+ &.is-connected {
41
+ .block-editor-block-switcher .components-button::before {
42
+ background: color-mix(in srgb, var(--wp-block-synced-color) 10%, transparent);
43
+ border-radius: $radius-small;
44
+ }
45
+ }
46
+
40
47
  &.is-synced,
41
48
  &.is-connected {
42
49
  .block-editor-block-switcher .components-button .block-editor-block-icon {
@@ -20,6 +20,7 @@ import BlockDraggable from '../block-draggable';
20
20
  import BlockMover from '../block-mover';
21
21
  import Shuffle from '../block-toolbar/shuffle';
22
22
  import NavigableToolbar from '../navigable-toolbar';
23
+ import { unlock } from '../../lock-unlock';
23
24
 
24
25
  export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
25
26
  const selected = useSelect(
@@ -84,8 +85,9 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
84
85
  setIsInserterOpened,
85
86
  } = selected;
86
87
 
87
- const { removeBlock, __unstableSetEditorMode } =
88
- useDispatch( blockEditorStore );
88
+ const { removeBlock, __unstableSetEditorMode, resetZoomLevel } = unlock(
89
+ useDispatch( blockEditorStore )
90
+ );
89
91
 
90
92
  const classNames = clsx( 'zoom-out-toolbar', {
91
93
  'is-block-moving-mode': !! blockMovingMode,
@@ -144,6 +146,7 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) {
144
146
  setIsInserterOpened( false );
145
147
  }
146
148
  __unstableSetEditorMode( 'edit' );
149
+ resetZoomLevel();
147
150
  __unstableContentRef.current?.focus();
148
151
  } }
149
152
  />
@@ -21,6 +21,7 @@ import { chevronDown } from '@wordpress/icons';
21
21
  */
22
22
  import BlockIcon from '../block-icon';
23
23
  import { store as blockEditorStore } from '../../store';
24
+ import { unlock } from '../../lock-unlock';
24
25
 
25
26
  function VariationsButtons( {
26
27
  className,
@@ -140,19 +141,28 @@ function VariationsToggleGroupControl( {
140
141
 
141
142
  function __experimentalBlockVariationTransforms( { blockClientId } ) {
142
143
  const { updateBlockAttributes } = useDispatch( blockEditorStore );
143
- const { activeBlockVariation, variations } = useSelect(
144
+ const { activeBlockVariation, variations, isContentOnly } = useSelect(
144
145
  ( select ) => {
145
146
  const { getActiveBlockVariation, getBlockVariations } =
146
147
  select( blocksStore );
147
- const { getBlockName, getBlockAttributes } =
148
+
149
+ const { getBlockName, getBlockAttributes, getBlockEditingMode } =
148
150
  select( blockEditorStore );
151
+
149
152
  const name = blockClientId && getBlockName( blockClientId );
153
+
154
+ const { hasContentRoleAttribute } = unlock( select( blocksStore ) );
155
+ const isContentBlock = hasContentRoleAttribute( name );
156
+
150
157
  return {
151
158
  activeBlockVariation: getActiveBlockVariation(
152
159
  name,
153
160
  getBlockAttributes( blockClientId )
154
161
  ),
155
162
  variations: name && getBlockVariations( name, 'transform' ),
163
+ isContentOnly:
164
+ getBlockEditingMode( blockClientId ) === 'contentOnly' &&
165
+ ! isContentBlock,
156
166
  };
157
167
  },
158
168
  [ blockClientId ]
@@ -181,8 +191,7 @@ function __experimentalBlockVariationTransforms( { blockClientId } ) {
181
191
  } );
182
192
  };
183
193
 
184
- // Skip rendering if there are no variations
185
- if ( ! variations?.length ) {
194
+ if ( ! variations?.length || isContentOnly ) {
186
195
  return null;
187
196
  }
188
197
 
@@ -26,15 +26,10 @@ export default ( props ) => ( element ) => {
26
26
  preserveWhiteSpace,
27
27
  pastePlainText,
28
28
  } = props.current;
29
- const { ownerDocument } = element;
30
- const { defaultView } = ownerDocument;
31
- const { anchorNode, focusNode } = defaultView.getSelection();
32
- const containsSelection =
33
- element.contains( anchorNode ) && element.contains( focusNode );
34
29
 
35
30
  // The event listener is attached to the window, so we need to check if
36
- // the target is the element.
37
- if ( ! containsSelection ) {
31
+ // the target is the element or inside the element.
32
+ if ( ! element.contains( event.target ) ) {
38
33
  return;
39
34
  }
40
35
 
@@ -165,7 +165,7 @@ export function RichTextWrapper(
165
165
  isBlockSelected,
166
166
  ] );
167
167
 
168
- const { disableBoundBlock, bindingsPlaceholder } = useSelect(
168
+ const { disableBoundBlock, bindingsPlaceholder, bindingsLabel } = useSelect(
169
169
  ( select ) => {
170
170
  if (
171
171
  ! blockBindings?.[ identifier ] ||
@@ -179,18 +179,36 @@ export function RichTextWrapper(
179
179
  const blockBindingsSource = getBlockBindingsSource(
180
180
  relatedBinding.source
181
181
  );
182
- const fieldsList = blockBindingsSource?.getFieldsList?.( {
183
- registry,
184
- context: blockContext,
185
- } );
182
+ const blockBindingsContext = {};
183
+ if ( blockBindingsSource?.usesContext?.length ) {
184
+ for ( const key of blockBindingsSource.usesContext ) {
185
+ blockBindingsContext[ key ] = blockContext[ key ];
186
+ }
187
+ }
186
188
 
187
189
  const _disableBoundBlock =
188
190
  ! blockBindingsSource?.canUserEditValue?.( {
189
- select,
190
- context: blockContext,
191
+ registry,
192
+ context: blockBindingsContext,
191
193
  args: relatedBinding.args,
192
194
  } );
193
195
 
196
+ // Don't modify placeholders if value is not empty.
197
+ if ( adjustedValue.length > 0 ) {
198
+ return {
199
+ disableBoundBlock: _disableBoundBlock,
200
+ // Null values will make them fall back to the default behavior.
201
+ bindingsPlaceholder: null,
202
+ bindingsLabel: null,
203
+ };
204
+ }
205
+
206
+ const { getBlockAttributes } = select( blockEditorStore );
207
+ const blockAttributes = getBlockAttributes( clientId );
208
+ const fieldsList = blockBindingsSource?.getFieldsList?.( {
209
+ registry,
210
+ context: blockBindingsContext,
211
+ } );
194
212
  const bindingKey =
195
213
  fieldsList?.[ relatedBinding?.args?.key ]?.label ??
196
214
  blockBindingsSource?.label;
@@ -202,12 +220,19 @@ export function RichTextWrapper(
202
220
  __( 'Add %s' ),
203
221
  bindingKey
204
222
  );
223
+ const _bindingsLabel = _disableBoundBlock
224
+ ? relatedBinding?.args?.key || blockBindingsSource?.label
225
+ : sprintf(
226
+ /* translators: %s: source label or key */
227
+ __( 'Empty %s; start writing to edit its value' ),
228
+ relatedBinding?.args?.key || blockBindingsSource?.label
229
+ );
205
230
 
206
231
  return {
207
232
  disableBoundBlock: _disableBoundBlock,
208
233
  bindingsPlaceholder:
209
- ( ! adjustedValue || adjustedValue.length === 0 ) &&
210
- _bindingsPlaceholder,
234
+ blockAttributes?.placeholder || _bindingsPlaceholder,
235
+ bindingsLabel: _bindingsLabel,
211
236
  };
212
237
  },
213
238
  [
@@ -372,19 +397,7 @@ export function RichTextWrapper(
372
397
  const inputEvents = useRef( new Set() );
373
398
 
374
399
  function onFocus() {
375
- let element = anchorRef.current;
376
-
377
- if ( ! element ) {
378
- return;
379
- }
380
-
381
- // Writing flow might be editable, so we should make sure focus goes to
382
- // the root editable element.
383
- while ( element.parentElement?.isContentEditable ) {
384
- element = element.parentElement;
385
- }
386
-
387
- element.focus();
400
+ anchorRef.current?.focus();
388
401
  }
389
402
 
390
403
  const TagName = tagName;
@@ -421,7 +434,7 @@ export function RichTextWrapper(
421
434
  aria-readonly={ shouldDisableEditing }
422
435
  { ...props }
423
436
  aria-label={
424
- bindingsPlaceholder || props[ 'aria-label' ] || placeholder
437
+ bindingsLabel || props[ 'aria-label' ] || placeholder
425
438
  }
426
439
  { ...autocompleteProps }
427
440
  ref={ useMergeRefs( [
@@ -18,6 +18,7 @@ import { Icon, edit as editIcon } from '@wordpress/icons';
18
18
  * Internal dependencies
19
19
  */
20
20
  import { store as blockEditorStore } from '../../store';
21
+ import { unlock } from '../../lock-unlock';
21
22
 
22
23
  const selectIcon = (
23
24
  <SVG
@@ -35,7 +36,9 @@ function ToolSelector( props, ref ) {
35
36
  ( select ) => select( blockEditorStore ).__unstableGetEditorMode(),
36
37
  []
37
38
  );
38
- const { __unstableSetEditorMode } = useDispatch( blockEditorStore );
39
+ const { __unstableSetEditorMode } = unlock(
40
+ useDispatch( blockEditorStore )
41
+ );
39
42
 
40
43
  return (
41
44
  <Dropdown
@@ -23,7 +23,6 @@ import useSelectionObserver from './use-selection-observer';
23
23
  import useClickSelection from './use-click-selection';
24
24
  import useInput from './use-input';
25
25
  import useClipboardHandler from './use-clipboard-handler';
26
- import useEventRedirect from './use-event-redirect';
27
26
  import { store as blockEditorStore } from '../../store';
28
27
 
29
28
  export function useWritingFlow() {
@@ -66,7 +65,6 @@ export function useWritingFlow() {
66
65
  },
67
66
  [ hasMultiSelection ]
68
67
  ),
69
- useEventRedirect(),
70
68
  ] ),
71
69
  after,
72
70
  ];