@wordpress/block-editor 14.16.0 → 14.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/components/background-image-control/index.js +18 -10
  3. package/build/components/background-image-control/index.js.map +1 -1
  4. package/build/components/block-canvas/index.js +6 -3
  5. package/build/components/block-canvas/index.js.map +1 -1
  6. package/build/components/block-list/block.js +4 -2
  7. package/build/components/block-list/block.js.map +1 -1
  8. package/build/components/block-list/use-block-props/use-firefox-draggable-compatibility.js +14 -11
  9. package/build/components/block-list/use-block-props/use-firefox-draggable-compatibility.js.map +1 -1
  10. package/build/components/block-settings-menu/block-mode-toggle.js +3 -3
  11. package/build/components/block-settings-menu/block-mode-toggle.js.map +1 -1
  12. package/build/components/block-toolbar/use-has-block-toolbar.js +3 -12
  13. package/build/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  14. package/build/components/block-tools/use-show-block-tools.js +3 -2
  15. package/build/components/block-tools/use-show-block-tools.js.map +1 -1
  16. package/build/components/child-layout-control/index.js +1 -0
  17. package/build/components/child-layout-control/index.js.map +1 -1
  18. package/build/components/html-element-control/index.js +107 -0
  19. package/build/components/html-element-control/index.js.map +1 -0
  20. package/build/components/html-element-control/messages.js +25 -0
  21. package/build/components/html-element-control/messages.js.map +1 -0
  22. package/build/components/inserter/media-tab/media-preview.js +1 -7
  23. package/build/components/inserter/media-tab/media-preview.js.map +1 -1
  24. package/build/components/keyboard-shortcuts/index.js +2 -2
  25. package/build/components/keyboard-shortcuts/index.js.map +1 -1
  26. package/build/components/link-control/index.js +2 -0
  27. package/build/components/link-control/index.js.map +1 -1
  28. package/build/components/media-placeholder/index.js +2 -1
  29. package/build/components/media-placeholder/index.js.map +1 -1
  30. package/build/components/rich-text/event-listeners/delete.js +1 -9
  31. package/build/components/rich-text/event-listeners/delete.js.map +1 -1
  32. package/build/components/use-resize-canvas/index.js +1 -1
  33. package/build/components/use-resize-canvas/index.js.map +1 -1
  34. package/build/hooks/duotone.js +1 -1
  35. package/build/hooks/duotone.js.map +1 -1
  36. package/build/hooks/spacing-visualizer.js +14 -8
  37. package/build/hooks/spacing-visualizer.js.map +1 -1
  38. package/build/hooks/typography.js +1 -1
  39. package/build/hooks/typography.js.map +1 -1
  40. package/build/private-apis.js +2 -0
  41. package/build/private-apis.js.map +1 -1
  42. package/build/private-apis.native.js +4 -1
  43. package/build/private-apis.native.js.map +1 -1
  44. package/build/store/actions.js +1 -1
  45. package/build/store/actions.js.map +1 -1
  46. package/build-module/components/background-image-control/index.js +19 -11
  47. package/build-module/components/background-image-control/index.js.map +1 -1
  48. package/build-module/components/block-canvas/index.js +6 -3
  49. package/build-module/components/block-canvas/index.js.map +1 -1
  50. package/build-module/components/block-list/block.js +4 -2
  51. package/build-module/components/block-list/block.js.map +1 -1
  52. package/build-module/components/block-list/use-block-props/use-firefox-draggable-compatibility.js +14 -11
  53. package/build-module/components/block-list/use-block-props/use-firefox-draggable-compatibility.js.map +1 -1
  54. package/build-module/components/block-settings-menu/block-mode-toggle.js +3 -3
  55. package/build-module/components/block-settings-menu/block-mode-toggle.js.map +1 -1
  56. package/build-module/components/block-toolbar/use-has-block-toolbar.js +3 -12
  57. package/build-module/components/block-toolbar/use-has-block-toolbar.js.map +1 -1
  58. package/build-module/components/block-tools/use-show-block-tools.js +3 -2
  59. package/build-module/components/block-tools/use-show-block-tools.js.map +1 -1
  60. package/build-module/components/child-layout-control/index.js +1 -0
  61. package/build-module/components/child-layout-control/index.js.map +1 -1
  62. package/build-module/components/html-element-control/index.js +102 -0
  63. package/build-module/components/html-element-control/index.js.map +1 -0
  64. package/build-module/components/html-element-control/messages.js +19 -0
  65. package/build-module/components/html-element-control/messages.js.map +1 -0
  66. package/build-module/components/inserter/media-tab/media-preview.js +1 -7
  67. package/build-module/components/inserter/media-tab/media-preview.js.map +1 -1
  68. package/build-module/components/keyboard-shortcuts/index.js +2 -2
  69. package/build-module/components/keyboard-shortcuts/index.js.map +1 -1
  70. package/build-module/components/link-control/index.js +4 -1
  71. package/build-module/components/link-control/index.js.map +1 -1
  72. package/build-module/components/media-placeholder/index.js +2 -1
  73. package/build-module/components/media-placeholder/index.js.map +1 -1
  74. package/build-module/components/rich-text/event-listeners/delete.js +1 -9
  75. package/build-module/components/rich-text/event-listeners/delete.js.map +1 -1
  76. package/build-module/components/use-resize-canvas/index.js +1 -1
  77. package/build-module/components/use-resize-canvas/index.js.map +1 -1
  78. package/build-module/hooks/duotone.js +1 -1
  79. package/build-module/hooks/duotone.js.map +1 -1
  80. package/build-module/hooks/spacing-visualizer.js +15 -9
  81. package/build-module/hooks/spacing-visualizer.js.map +1 -1
  82. package/build-module/hooks/typography.js +1 -1
  83. package/build-module/hooks/typography.js.map +1 -1
  84. package/build-module/private-apis.js +2 -0
  85. package/build-module/private-apis.js.map +1 -1
  86. package/build-module/private-apis.native.js +3 -1
  87. package/build-module/private-apis.native.js.map +1 -1
  88. package/build-module/store/actions.js +1 -1
  89. package/build-module/store/actions.js.map +1 -1
  90. package/build-style/content-rtl.css +1 -0
  91. package/build-style/content.css +1 -0
  92. package/build-style/style-rtl.css +7 -2
  93. package/build-style/style.css +8 -2
  94. package/package.json +34 -34
  95. package/src/components/background-image-control/index.js +22 -7
  96. package/src/components/block-canvas/index.js +5 -3
  97. package/src/components/block-inspector/style.scss +4 -2
  98. package/src/components/block-list/block.js +6 -2
  99. package/src/components/block-list/content.scss +1 -0
  100. package/src/components/block-list/use-block-props/use-firefox-draggable-compatibility.js +14 -11
  101. package/src/components/block-settings-menu/block-mode-toggle.js +3 -3
  102. package/src/components/block-settings-menu/test/block-mode-toggle.js +1 -1
  103. package/src/components/block-toolbar/use-has-block-toolbar.js +7 -13
  104. package/src/components/block-tools/use-show-block-tools.js +2 -0
  105. package/src/components/child-layout-control/index.js +1 -0
  106. package/src/components/html-element-control/index.js +109 -0
  107. package/src/components/html-element-control/messages.js +34 -0
  108. package/src/components/inserter/media-tab/media-preview.js +1 -8
  109. package/src/components/keyboard-shortcuts/index.js +2 -2
  110. package/src/components/link-control/index.js +6 -1
  111. package/src/components/media-placeholder/index.js +1 -1
  112. package/src/components/media-placeholder/style.scss +6 -0
  113. package/src/components/rich-text/event-listeners/delete.js +1 -6
  114. package/src/components/use-resize-canvas/index.js +1 -1
  115. package/src/hooks/duotone.js +4 -3
  116. package/src/hooks/spacing-visualizer.js +14 -17
  117. package/src/hooks/typography.js +5 -3
  118. package/src/private-apis.js +2 -0
  119. package/src/private-apis.native.js +2 -0
  120. package/src/store/actions.js +5 -1
  121. package/src/store/test/actions.js +122 -0
@@ -124,9 +124,10 @@ function DuotonePanelPure( { style, setAttributes, name } ) {
124
124
  return null;
125
125
  }
126
126
 
127
- const duotonePresetOrColors = ! Array.isArray( duotoneStyle )
128
- ? getColorsFromDuotonePreset( duotoneStyle, duotonePalette )
129
- : duotoneStyle;
127
+ const duotonePresetOrColors =
128
+ duotoneStyle === 'unset' || Array.isArray( duotoneStyle )
129
+ ? duotoneStyle
130
+ : getColorsFromDuotonePreset( duotoneStyle, duotonePalette );
130
131
 
131
132
  return (
132
133
  <>
@@ -1,13 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import {
5
- useState,
6
- useRef,
7
- useLayoutEffect,
8
- useEffect,
9
- useReducer,
10
- } from '@wordpress/element';
4
+ import { useState, useRef, useEffect, useReducer } from '@wordpress/element';
11
5
  import isShallowEqual from '@wordpress/is-shallow-equal';
12
6
 
13
7
  /**
@@ -22,19 +16,22 @@ function SpacingVisualizer( { clientId, value, computeStyle, forceShow } ) {
22
16
  computeStyle( blockElement )
23
17
  );
24
18
 
25
- useLayoutEffect( () => {
19
+ // It's not sufficient to read the block’s computed style when `value` changes because
20
+ // the effect would run before the block’s style has updated. Thus observing mutations
21
+ // to the block’s attributes is used to trigger updates to the visualizer’s styles.
22
+ useEffect( () => {
26
23
  if ( ! blockElement ) {
27
24
  return;
28
25
  }
29
- // It's not sufficient to read the computed spacing value when value.spacing changes as
30
- // useEffect may run before the browser recomputes CSS. We therefore combine
31
- // useLayoutEffect and two rAF calls to ensure that we read the spacing after the current
32
- // paint but before the next paint.
33
- // See https://github.com/WordPress/gutenberg/pull/59227.
34
- window.requestAnimationFrame( () =>
35
- window.requestAnimationFrame( updateStyle )
36
- );
37
- }, [ blockElement, value ] );
26
+ const observer = new window.MutationObserver( updateStyle );
27
+ observer.observe( blockElement, {
28
+ attributes: true,
29
+ attributeFilter: [ 'style', 'class' ],
30
+ } );
31
+ return () => {
32
+ observer.disconnect();
33
+ };
34
+ }, [ blockElement ] );
38
35
 
39
36
  const previousValueRef = useRef( value );
40
37
  const [ isActive, setIsActive ] = useState( false );
@@ -53,9 +53,11 @@ function styleToAttributes( style ) {
53
53
  const updatedStyle = { ...omit( style, [ 'fontFamily' ] ) };
54
54
  const fontSizeValue = style?.typography?.fontSize;
55
55
  const fontFamilyValue = style?.typography?.fontFamily;
56
- const fontSizeSlug = fontSizeValue?.startsWith( 'var:preset|font-size|' )
57
- ? fontSizeValue.substring( 'var:preset|font-size|'.length )
58
- : undefined;
56
+ const fontSizeSlug =
57
+ typeof fontSizeValue === 'string' &&
58
+ fontSizeValue?.startsWith( 'var:preset|font-size|' )
59
+ ? fontSizeValue.substring( 'var:preset|font-size|'.length )
60
+ : undefined;
59
61
  const fontFamilySlug = fontFamilyValue?.startsWith(
60
62
  'var:preset|font-family|'
61
63
  )
@@ -50,6 +50,7 @@ import useBlockDisplayTitle from './components/block-title/use-block-display-tit
50
50
  import TabbedSidebar from './components/tabbed-sidebar';
51
51
  import CommentIconSlotFill from './components/collab/block-comment-icon-slot';
52
52
  import CommentIconToolbarSlotFill from './components/collab/block-comment-icon-toolbar-slot';
53
+ import HTMLElementControl from './components/html-element-control';
53
54
  /**
54
55
  * Private @wordpress/block-editor APIs.
55
56
  */
@@ -80,6 +81,7 @@ lock( privateApis, {
80
81
  TextAlignmentControl,
81
82
  usesContextKey,
82
83
  useFlashEditableBlocks,
84
+ HTMLElementControl,
83
85
  useZoomOut,
84
86
  globalStylesDataKey,
85
87
  globalStylesLinksDataKey,
@@ -6,6 +6,7 @@ import { ExperimentalBlockEditorProvider } from './components/provider';
6
6
  import { getRichTextValues } from './components/rich-text/get-rich-text-values';
7
7
  import { lock } from './lock-unlock';
8
8
  import { PrivateRichText } from './components/rich-text/';
9
+ import HTMLElementControl from './components/html-element-control';
9
10
 
10
11
  /**
11
12
  * Private @wordpress/block-editor APIs.
@@ -16,4 +17,5 @@ lock( privateApis, {
16
17
  ExperimentalBlockEditorProvider,
17
18
  getRichTextValues,
18
19
  PrivateRichText,
20
+ HTMLElementControl,
19
21
  } );
@@ -1157,7 +1157,11 @@ export const mergeBlocks =
1157
1157
  const blockA = select.getBlock( clientIdA );
1158
1158
  const blockAType = getBlockType( blockA.name );
1159
1159
 
1160
- if ( ! blockAType ) {
1160
+ if (
1161
+ ! blockAType ||
1162
+ select.getBlockEditingMode( clientIdA ) === 'disabled' ||
1163
+ select.getBlockEditingMode( clientIdB ) === 'disabled'
1164
+ ) {
1161
1165
  return;
1162
1166
  }
1163
1167
 
@@ -822,6 +822,7 @@ describe( 'actions', () => {
822
822
  const select = {
823
823
  getBlock: ( clientId ) =>
824
824
  [ blockA, blockB ].find( ( b ) => b.clientId === clientId ),
825
+ getBlockEditingMode: () => 'default',
825
826
  };
826
827
  const dispatch = Object.assign( jest.fn(), {
827
828
  selectBlock: jest.fn(),
@@ -873,6 +874,7 @@ describe( 'actions', () => {
873
874
  attributeKey: 'content',
874
875
  offset: 0,
875
876
  } ),
877
+ getBlockEditingMode: () => 'default',
876
878
  };
877
879
  const dispatch = Object.assign( jest.fn(), {
878
880
  replaceBlocks: jest.fn(),
@@ -943,6 +945,7 @@ describe( 'actions', () => {
943
945
  attributeKey: 'content',
944
946
  offset: 0,
945
947
  } ),
948
+ getBlockEditingMode: () => 'default',
946
949
  };
947
950
  const dispatch = Object.assign( jest.fn(), {
948
951
  replaceBlocks: jest.fn(),
@@ -1019,6 +1022,7 @@ describe( 'actions', () => {
1019
1022
  attributeKey: 'content2',
1020
1023
  offset: 0,
1021
1024
  } ),
1025
+ getBlockEditingMode: () => 'default',
1022
1026
  };
1023
1027
  const dispatch = Object.assign( jest.fn(), {
1024
1028
  replaceBlocks: jest.fn(),
@@ -1049,6 +1053,124 @@ describe( 'actions', () => {
1049
1053
  0
1050
1054
  );
1051
1055
  } );
1056
+
1057
+ it( 'should not merge the blocks if blockB editing mode is `disabled`', () => {
1058
+ registerBlockType( 'core/test-block', {
1059
+ attributes: {
1060
+ content: {},
1061
+ },
1062
+ merge( attributes, attributesToMerge ) {
1063
+ return {
1064
+ content:
1065
+ attributes.content +
1066
+ ' ' +
1067
+ attributesToMerge.content,
1068
+ };
1069
+ },
1070
+ save: noop,
1071
+ category: 'text',
1072
+ title: 'test block',
1073
+ } );
1074
+ const blockA = deepFreeze( {
1075
+ clientId: 'chicken',
1076
+ name: 'core/test-block',
1077
+ attributes: { content: 'chicken' },
1078
+ innerBlocks: [],
1079
+ } );
1080
+ const blockB = deepFreeze( {
1081
+ clientId: 'ribs',
1082
+ name: 'core/test-block',
1083
+ attributes: { content: 'ribs' },
1084
+ innerBlocks: [],
1085
+ } );
1086
+
1087
+ const modes = {
1088
+ chicken: 'default',
1089
+ ribs: 'disabled',
1090
+ };
1091
+
1092
+ const select = {
1093
+ getBlock: ( clientId ) =>
1094
+ [ blockA, blockB ].find( ( b ) => b.clientId === clientId ),
1095
+ getSelectionStart: () => ( {
1096
+ clientId: blockB.clientId,
1097
+ attributeKey: 'content',
1098
+ offset: 0,
1099
+ } ),
1100
+ getBlockEditingMode: ( clientId ) => modes[ clientId ],
1101
+ };
1102
+ const dispatch = Object.assign( jest.fn(), {
1103
+ replaceBlocks: jest.fn(),
1104
+ selectionChange: jest.fn(),
1105
+ } );
1106
+
1107
+ mergeBlocks(
1108
+ blockA.clientId,
1109
+ blockB.clientId
1110
+ )( { select, dispatch } );
1111
+
1112
+ expect( dispatch.selectionChange ).not.toHaveBeenCalled();
1113
+ expect( dispatch.replaceBlocks ).not.toHaveBeenCalled();
1114
+ } );
1115
+
1116
+ it( 'should not merge the blocks if blockA editing mode is `disabled`', () => {
1117
+ registerBlockType( 'core/test-block', {
1118
+ attributes: {
1119
+ content: {},
1120
+ },
1121
+ merge( attributes, attributesToMerge ) {
1122
+ return {
1123
+ content:
1124
+ attributes.content +
1125
+ ' ' +
1126
+ attributesToMerge.content,
1127
+ };
1128
+ },
1129
+ save: noop,
1130
+ category: 'text',
1131
+ title: 'test block',
1132
+ } );
1133
+ const blockA = deepFreeze( {
1134
+ clientId: 'chicken',
1135
+ name: 'core/test-block',
1136
+ attributes: { content: 'chicken' },
1137
+ innerBlocks: [],
1138
+ } );
1139
+ const blockB = deepFreeze( {
1140
+ clientId: 'ribs',
1141
+ name: 'core/test-block',
1142
+ attributes: { content: 'ribs' },
1143
+ innerBlocks: [],
1144
+ } );
1145
+
1146
+ const modes = {
1147
+ chicken: 'disabled',
1148
+ ribs: 'default',
1149
+ };
1150
+
1151
+ const select = {
1152
+ getBlock: ( clientId ) =>
1153
+ [ blockA, blockB ].find( ( b ) => b.clientId === clientId ),
1154
+ getSelectionStart: () => ( {
1155
+ clientId: blockB.clientId,
1156
+ attributeKey: 'content',
1157
+ offset: 0,
1158
+ } ),
1159
+ getBlockEditingMode: ( clientId ) => modes[ clientId ],
1160
+ };
1161
+ const dispatch = Object.assign( jest.fn(), {
1162
+ replaceBlocks: jest.fn(),
1163
+ selectionChange: jest.fn(),
1164
+ } );
1165
+
1166
+ mergeBlocks(
1167
+ blockA.clientId,
1168
+ blockB.clientId
1169
+ )( { select, dispatch } );
1170
+
1171
+ expect( dispatch.selectionChange ).not.toHaveBeenCalled();
1172
+ expect( dispatch.replaceBlocks ).not.toHaveBeenCalled();
1173
+ } );
1052
1174
  } );
1053
1175
 
1054
1176
  describe( 'validateBlocksToTemplate', () => {