@wordpress/block-editor 15.15.0 → 15.16.1-next.v.202604091042.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 (197) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/autocomplete/index.cjs +1 -2
  3. package/build/components/autocomplete/index.cjs.map +3 -3
  4. package/build/components/block-inspector/index.cjs +2 -1
  5. package/build/components/block-inspector/index.cjs.map +2 -2
  6. package/build/components/block-list/block-crash-warning.cjs +4 -2
  7. package/build/components/block-list/block-crash-warning.cjs.map +2 -2
  8. package/build/components/block-list/block-html.cjs +6 -2
  9. package/build/components/block-list/block-html.cjs.map +2 -2
  10. package/build/components/block-mover/button.cjs +4 -3
  11. package/build/components/block-mover/button.cjs.map +2 -2
  12. package/build/components/block-mover/index.cjs +1 -8
  13. package/build/components/block-mover/index.cjs.map +2 -2
  14. package/build/components/block-visibility/modal.cjs +2 -2
  15. package/build/components/block-visibility/modal.cjs.map +1 -1
  16. package/build/components/block-visibility/viewport-visibility-info.cjs +6 -1
  17. package/build/components/block-visibility/viewport-visibility-info.cjs.map +2 -2
  18. package/build/components/global-styles/background-panel.cjs +142 -33
  19. package/build/components/global-styles/background-panel.cjs.map +2 -2
  20. package/build/components/global-styles/color-panel.cjs +18 -7
  21. package/build/components/global-styles/color-panel.cjs.map +2 -2
  22. package/build/components/global-styles/hooks.cjs +8 -4
  23. package/build/components/global-styles/hooks.cjs.map +2 -2
  24. package/build/components/iframe/get-compatibility-styles.cjs +1 -1
  25. package/build/components/iframe/get-compatibility-styles.cjs.map +2 -2
  26. package/build/components/inserter/media-tab/hooks.cjs +1 -1
  27. package/build/components/inserter/media-tab/hooks.cjs.map +2 -2
  28. package/build/components/inspector-controls-tabs/styles-tab.cjs +2 -1
  29. package/build/components/inspector-controls-tabs/styles-tab.cjs.map +2 -2
  30. package/build/components/link-control/search-input.cjs +1 -1
  31. package/build/components/link-control/search-input.cjs.map +2 -2
  32. package/build/components/link-picker/link-preview.cjs +2 -1
  33. package/build/components/link-picker/link-preview.cjs.map +3 -3
  34. package/build/components/rich-text/index.cjs +1 -1
  35. package/build/components/rich-text/index.cjs.map +2 -2
  36. package/build/components/rich-text/input-event.cjs +3 -3
  37. package/build/components/rich-text/input-event.cjs.map +2 -2
  38. package/build/components/use-on-block-drop/index.cjs +1 -1
  39. package/build/components/use-on-block-drop/index.cjs.map +2 -2
  40. package/build/components/use-paste-styles/index.cjs +2 -2
  41. package/build/components/use-paste-styles/index.cjs.map +2 -2
  42. package/build/hooks/background.cjs +74 -21
  43. package/build/hooks/background.cjs.map +3 -3
  44. package/build/hooks/block-style-variation.cjs +5 -6
  45. package/build/hooks/block-style-variation.cjs.map +3 -3
  46. package/build/hooks/cross-origin-isolation.cjs +6 -6
  47. package/build/hooks/cross-origin-isolation.cjs.map +2 -2
  48. package/build/hooks/custom-css.cjs +5 -0
  49. package/build/hooks/custom-css.cjs.map +2 -2
  50. package/build/hooks/fit-text.cjs +46 -58
  51. package/build/hooks/fit-text.cjs.map +3 -3
  52. package/build/hooks/index.cjs +2 -2
  53. package/build/hooks/index.cjs.map +2 -2
  54. package/build/hooks/utils.cjs +5 -1
  55. package/build/hooks/utils.cjs.map +2 -2
  56. package/build/private-apis.cjs +1 -1
  57. package/build/private-apis.cjs.map +1 -1
  58. package/build/store/actions.cjs +8 -12
  59. package/build/store/actions.cjs.map +2 -2
  60. package/build/store/private-selectors.cjs +2 -2
  61. package/build/store/private-selectors.cjs.map +2 -2
  62. package/build/store/reducer.cjs +112 -146
  63. package/build/store/reducer.cjs.map +2 -2
  64. package/build/store/selectors.cjs +14 -15
  65. package/build/store/selectors.cjs.map +2 -2
  66. package/build/store/utils.cjs +1 -1
  67. package/build/store/utils.cjs.map +2 -2
  68. package/build/utils/pasting.cjs +1 -1
  69. package/build/utils/pasting.cjs.map +2 -2
  70. package/build-module/components/autocomplete/index.mjs +1 -2
  71. package/build-module/components/autocomplete/index.mjs.map +2 -2
  72. package/build-module/components/block-inspector/index.mjs +2 -1
  73. package/build-module/components/block-inspector/index.mjs.map +2 -2
  74. package/build-module/components/block-list/block-crash-warning.mjs +4 -2
  75. package/build-module/components/block-list/block-crash-warning.mjs.map +2 -2
  76. package/build-module/components/block-list/block-html.mjs +7 -3
  77. package/build-module/components/block-list/block-html.mjs.map +2 -2
  78. package/build-module/components/block-mover/button.mjs +4 -3
  79. package/build-module/components/block-mover/button.mjs.map +2 -2
  80. package/build-module/components/block-mover/index.mjs +1 -8
  81. package/build-module/components/block-mover/index.mjs.map +2 -2
  82. package/build-module/components/block-visibility/modal.mjs +2 -2
  83. package/build-module/components/block-visibility/modal.mjs.map +1 -1
  84. package/build-module/components/block-visibility/viewport-visibility-info.mjs +6 -1
  85. package/build-module/components/block-visibility/viewport-visibility-info.mjs.map +2 -2
  86. package/build-module/components/global-styles/background-panel.mjs +141 -34
  87. package/build-module/components/global-styles/background-panel.mjs.map +2 -2
  88. package/build-module/components/global-styles/color-panel.mjs +17 -7
  89. package/build-module/components/global-styles/color-panel.mjs.map +2 -2
  90. package/build-module/components/global-styles/hooks.mjs +8 -4
  91. package/build-module/components/global-styles/hooks.mjs.map +2 -2
  92. package/build-module/components/iframe/get-compatibility-styles.mjs +1 -1
  93. package/build-module/components/iframe/get-compatibility-styles.mjs.map +2 -2
  94. package/build-module/components/inserter/media-tab/hooks.mjs +1 -1
  95. package/build-module/components/inserter/media-tab/hooks.mjs.map +2 -2
  96. package/build-module/components/inspector-controls-tabs/styles-tab.mjs +2 -1
  97. package/build-module/components/inspector-controls-tabs/styles-tab.mjs.map +2 -2
  98. package/build-module/components/link-control/search-input.mjs +1 -1
  99. package/build-module/components/link-control/search-input.mjs.map +2 -2
  100. package/build-module/components/link-picker/link-preview.mjs +2 -1
  101. package/build-module/components/link-picker/link-preview.mjs.map +2 -2
  102. package/build-module/components/rich-text/index.mjs +2 -2
  103. package/build-module/components/rich-text/index.mjs.map +2 -2
  104. package/build-module/components/rich-text/input-event.mjs +2 -2
  105. package/build-module/components/rich-text/input-event.mjs.map +2 -2
  106. package/build-module/components/use-on-block-drop/index.mjs +1 -1
  107. package/build-module/components/use-on-block-drop/index.mjs.map +2 -2
  108. package/build-module/components/use-paste-styles/index.mjs +2 -2
  109. package/build-module/components/use-paste-styles/index.mjs.map +2 -2
  110. package/build-module/hooks/background.mjs +76 -22
  111. package/build-module/hooks/background.mjs.map +2 -2
  112. package/build-module/hooks/block-style-variation.mjs +4 -5
  113. package/build-module/hooks/block-style-variation.mjs.map +2 -2
  114. package/build-module/hooks/cross-origin-isolation.mjs +6 -6
  115. package/build-module/hooks/cross-origin-isolation.mjs.map +2 -2
  116. package/build-module/hooks/custom-css.mjs +5 -0
  117. package/build-module/hooks/custom-css.mjs.map +2 -2
  118. package/build-module/hooks/fit-text.mjs +46 -58
  119. package/build-module/hooks/fit-text.mjs.map +2 -2
  120. package/build-module/hooks/index.mjs +2 -2
  121. package/build-module/hooks/index.mjs.map +2 -2
  122. package/build-module/hooks/utils.mjs +5 -1
  123. package/build-module/hooks/utils.mjs.map +2 -2
  124. package/build-module/private-apis.mjs +2 -2
  125. package/build-module/private-apis.mjs.map +1 -1
  126. package/build-module/store/actions.mjs +8 -12
  127. package/build-module/store/actions.mjs.map +2 -2
  128. package/build-module/store/private-selectors.mjs +2 -2
  129. package/build-module/store/private-selectors.mjs.map +2 -2
  130. package/build-module/store/reducer.mjs +112 -145
  131. package/build-module/store/reducer.mjs.map +2 -2
  132. package/build-module/store/selectors.mjs +14 -15
  133. package/build-module/store/selectors.mjs.map +2 -2
  134. package/build-module/store/utils.mjs +1 -1
  135. package/build-module/store/utils.mjs.map +2 -2
  136. package/build-module/utils/pasting.mjs +1 -1
  137. package/build-module/utils/pasting.mjs.map +2 -2
  138. package/build-style/content-rtl.css +2 -2
  139. package/build-style/content.css +2 -2
  140. package/build-style/style-rtl.css +35 -14
  141. package/build-style/style.css +35 -14
  142. package/package.json +38 -39
  143. package/src/autocompleters/style.scss +0 -8
  144. package/src/components/autocomplete/index.js +1 -2
  145. package/src/components/background-image-control/style.scss +0 -4
  146. package/src/components/block-draggable/test/helpers.native.js +1 -1
  147. package/src/components/block-inspector/index.js +1 -0
  148. package/src/components/block-list/block-crash-warning.js +3 -1
  149. package/src/components/block-list/block-crash-warning.native.js +3 -1
  150. package/src/components/block-list/block-html.js +13 -3
  151. package/src/components/block-mover/button.js +7 -4
  152. package/src/components/block-mover/index.js +1 -8
  153. package/src/components/block-visibility/viewport-visibility-info.js +8 -1
  154. package/src/components/fit-text-size-warning/style.scss +1 -5
  155. package/src/components/global-styles/background-panel.js +157 -11
  156. package/src/components/global-styles/color-panel.js +23 -7
  157. package/src/components/global-styles/hooks.js +12 -4
  158. package/src/components/global-styles/test/background-panel.js +44 -1
  159. package/src/components/iframe/get-compatibility-styles.js +1 -1
  160. package/src/components/inserter/media-tab/hooks.js +1 -1
  161. package/src/components/inspector-controls-tabs/styles-tab.js +1 -0
  162. package/src/components/link-control/README.md +2 -2
  163. package/src/components/link-control/search-input.js +1 -1
  164. package/src/components/link-picker/link-preview.js +2 -1
  165. package/src/components/rich-text/index.js +1 -1
  166. package/src/components/rich-text/index.native.js +1 -1
  167. package/src/components/rich-text/input-event.js +1 -1
  168. package/src/components/rich-text/input-event.native.js +1 -1
  169. package/src/components/rich-text/native/index.native.js +18 -17
  170. package/src/components/use-on-block-drop/index.js +1 -1
  171. package/src/components/use-paste-styles/index.js +2 -2
  172. package/src/hooks/background.js +122 -21
  173. package/src/hooks/background.scss +45 -0
  174. package/src/hooks/block-style-variation.js +3 -4
  175. package/src/hooks/cross-origin-isolation.js +6 -6
  176. package/src/hooks/custom-css.js +6 -0
  177. package/src/hooks/fit-text.js +73 -83
  178. package/src/hooks/index.js +1 -1
  179. package/src/hooks/test/cross-origin-isolation.js +7 -3
  180. package/src/hooks/utils.js +4 -0
  181. package/src/private-apis.js +2 -2
  182. package/src/store/actions.js +9 -16
  183. package/src/store/private-selectors.js +2 -2
  184. package/src/store/reducer.js +144 -193
  185. package/src/store/selectors.js +33 -23
  186. package/src/store/test/private-selectors.js +107 -71
  187. package/src/store/test/reducer.js +593 -152
  188. package/src/store/test/registry-selectors.js +1 -1
  189. package/src/store/test/selectors.js +345 -262
  190. package/src/store/utils.js +1 -1
  191. package/src/style.scss +1 -0
  192. package/src/utils/pasting.js +1 -1
  193. package/build/autocompleters/link.cjs +0 -81
  194. package/build/autocompleters/link.cjs.map +0 -7
  195. package/build-module/autocompleters/link.mjs +0 -50
  196. package/build-module/autocompleters/link.mjs.map +0 -7
  197. package/src/autocompleters/link.js +0 -63
@@ -37,14 +37,13 @@ import {
37
37
  settings,
38
38
  lastBlockAttributesChange,
39
39
  lastBlockInserted,
40
- blockEditingModes,
41
40
  expandedBlock,
42
41
  zoomLevel,
43
42
  editedContentOnlySection,
44
43
  withDerivedBlockEditingModes,
45
44
  viewportModalClientIds,
46
45
  } from '../reducer';
47
-
46
+ import { getBlockOrder, getBlocks } from '../selectors';
48
47
  import { unlock } from '../../lock-unlock';
49
48
  import { sectionRootClientIdKey, isIsolatedEditorKey } from '.././private-keys';
50
49
 
@@ -286,7 +285,8 @@ describe( 'state', () => {
286
285
  'chicken-child': {},
287
286
  } )
288
287
  ),
289
- controlledInnerBlocks: {},
288
+ controlledInnerBlocks: new Set(),
289
+ blockEditingModes: new Map(),
290
290
  } );
291
291
 
292
292
  const newChildBlock = createBlock( 'core/test-child-block', {
@@ -344,7 +344,8 @@ describe( 'state', () => {
344
344
  chicken: '',
345
345
  } )
346
346
  ),
347
- controlledInnerBlocks: {},
347
+ controlledInnerBlocks: new Set(),
348
+ blockEditingModes: new Map(),
348
349
  } );
349
350
  expect( state.tree.get( 'chicken' ) ).not.toBe(
350
351
  existingState.tree.get( 'chicken' )
@@ -386,7 +387,8 @@ describe( 'state', () => {
386
387
  chicken: {},
387
388
  } )
388
389
  ),
389
- controlledInnerBlocks: {},
390
+ controlledInnerBlocks: new Set(),
391
+ blockEditingModes: new Map(),
390
392
  } );
391
393
 
392
394
  const newChildBlock = createBlock( 'core/test-child-block', {
@@ -444,7 +446,8 @@ describe( 'state', () => {
444
446
  chicken: '',
445
447
  } )
446
448
  ),
447
- controlledInnerBlocks: {},
449
+ controlledInnerBlocks: new Set(),
450
+ blockEditingModes: new Map(),
448
451
  } );
449
452
  expect( state.tree.get( 'chicken' ) ).not.toBe(
450
453
  existingState.tree.get( 'chicken' )
@@ -515,7 +518,8 @@ describe( 'state', () => {
515
518
  } )
516
519
  ),
517
520
  tree: new Map(),
518
- controlledInnerBlocks: {},
521
+ controlledInnerBlocks: new Set(),
522
+ blockEditingModes: new Map(),
519
523
  } );
520
524
 
521
525
  const newChildBlock1 = createBlock( 'core/test-child-block', {
@@ -609,7 +613,8 @@ describe( 'state', () => {
609
613
  [ newChildBlockId3 ]: 'chicken',
610
614
  } )
611
615
  ),
612
- controlledInnerBlocks: {},
616
+ controlledInnerBlocks: new Set(),
617
+ blockEditingModes: new Map(),
613
618
  } );
614
619
 
615
620
  expect( state.tree.get( '' ).innerBlocks[ 0 ] ).toBe(
@@ -684,7 +689,8 @@ describe( 'state', () => {
684
689
  chicken: {},
685
690
  } )
686
691
  ),
687
- controlledInnerBlocks: {},
692
+ controlledInnerBlocks: new Set(),
693
+ blockEditingModes: new Map(),
688
694
  } );
689
695
 
690
696
  const newChildBlock = createBlock( 'core/test-block' );
@@ -736,7 +742,8 @@ describe( 'state', () => {
736
742
  [ newChildBlockId ]: 'chicken',
737
743
  } )
738
744
  ),
739
- controlledInnerBlocks: {},
745
+ controlledInnerBlocks: new Set(),
746
+ blockEditingModes: new Map(),
740
747
  } );
741
748
 
742
749
  // The block object of the parent should be updated.
@@ -757,7 +764,8 @@ describe( 'state', () => {
757
764
  isPersistentChange: true,
758
765
  isIgnoredChange: false,
759
766
  tree: new Map(),
760
- controlledInnerBlocks: {},
767
+ controlledInnerBlocks: new Set(),
768
+ blockEditingModes: new Map(),
761
769
  } );
762
770
  } );
763
771
 
@@ -1138,52 +1146,6 @@ describe( 'state', () => {
1138
1146
  } );
1139
1147
  } );
1140
1148
 
1141
- it( 'should update the reusable block reference if the temporary id is swapped', () => {
1142
- const original = blocks( undefined, {
1143
- type: 'RESET_BLOCKS',
1144
- blocks: [
1145
- {
1146
- clientId: 'chicken',
1147
- name: 'core/block',
1148
- attributes: {
1149
- ref: 'random-clientId',
1150
- },
1151
- isValid: false,
1152
- innerBlocks: [],
1153
- },
1154
- ],
1155
- } );
1156
-
1157
- const state = blocks( deepFreeze( original ), {
1158
- type: 'SAVE_REUSABLE_BLOCK_SUCCESS',
1159
- id: 'random-clientId',
1160
- updatedId: 3,
1161
- } );
1162
-
1163
- expect( state.byClientId.get( 'chicken' ) ).toEqual( {
1164
- clientId: 'chicken',
1165
- name: 'core/block',
1166
- isValid: false,
1167
- } );
1168
-
1169
- expect( state.attributes.get( 'chicken' ) ).toEqual( {
1170
- ref: 3,
1171
- } );
1172
-
1173
- expect( state.tree.get( '' ).innerBlocks[ 0 ] ).toBe(
1174
- state.tree.get( 'chicken' )
1175
- );
1176
- expect( state.tree.get( 'chicken' ) ).toEqual( {
1177
- clientId: 'chicken',
1178
- name: 'core/block',
1179
- isValid: false,
1180
- innerBlocks: [],
1181
- attributes: {
1182
- ref: 3,
1183
- },
1184
- } );
1185
- } );
1186
-
1187
1149
  it( 'should move the block up', () => {
1188
1150
  const original = blocks( undefined, {
1189
1151
  type: 'RESET_BLOCKS',
@@ -2297,7 +2259,9 @@ describe( 'state', () => {
2297
2259
  hasControlledInnerBlocks: true,
2298
2260
  } );
2299
2261
 
2300
- expect( state.controlledInnerBlocks.chicken ).toBe( true );
2262
+ expect( state.controlledInnerBlocks.has( 'chicken' ) ).toBe(
2263
+ true
2264
+ );
2301
2265
  // The previous content of the block should be removed
2302
2266
  expect( state.byClientId.child ).toBeUndefined();
2303
2267
  expect( state.tree.get( 'child' ) ).toBeUndefined();
@@ -2334,9 +2298,7 @@ describe( 'state', () => {
2334
2298
  'paragraph-id': [],
2335
2299
  } )
2336
2300
  ),
2337
- controlledInnerBlocks: {
2338
- 'reusable-id': true,
2339
- },
2301
+ controlledInnerBlocks: new Set( [ 'reusable-id' ] ),
2340
2302
  parents: new Map(
2341
2303
  Object.entries( {
2342
2304
  'group-id': '',
@@ -2459,11 +2421,29 @@ describe( 'state', () => {
2459
2421
  clientId: 'chicken',
2460
2422
  hasControlledInnerBlocks: true,
2461
2423
  } );
2462
- expect( withControlled.controlledInnerBlocks.chicken ).toBe(
2424
+ expect(
2425
+ withControlled.controlledInnerBlocks.has( 'chicken' )
2426
+ ).toBe( true );
2427
+
2428
+ const state = blocks( withControlled, {
2429
+ type: 'RESET_BLOCKS',
2430
+ blocks: [
2431
+ {
2432
+ clientId: 'chicken',
2433
+ name: 'core/test-block',
2434
+ attributes: {},
2435
+ innerBlocks: [],
2436
+ },
2437
+ ],
2438
+ } );
2439
+
2440
+ expect( state.controlledInnerBlocks.has( 'chicken' ) ).toBe(
2463
2441
  true
2464
2442
  );
2443
+ } );
2465
2444
 
2466
- const state = blocks( withControlled, {
2445
+ it( 'should preserve controlledInnerBlocks blocks across RESET_BLOCKS', () => {
2446
+ const original = blocks( undefined, {
2467
2447
  type: 'RESET_BLOCKS',
2468
2448
  blocks: [
2469
2449
  {
@@ -2474,8 +2454,191 @@ describe( 'state', () => {
2474
2454
  },
2475
2455
  ],
2476
2456
  } );
2457
+ const withControlled = blocks( original, {
2458
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
2459
+ clientId: 'chicken',
2460
+ hasControlledInnerBlocks: true,
2461
+ } );
2462
+
2463
+ const withControlledContent = blocks( withControlled, {
2464
+ type: 'REPLACE_INNER_BLOCKS',
2465
+ rootClientId: 'chicken',
2466
+ blocks: [
2467
+ {
2468
+ clientId: 'content',
2469
+ innerBlocks: [
2470
+ {
2471
+ clientId: 'content-inner',
2472
+ innerBlocks: [],
2473
+ },
2474
+ ],
2475
+ },
2476
+ ],
2477
+ } );
2477
2478
 
2478
- expect( state.controlledInnerBlocks.chicken ).toBe( true );
2479
+ expect(
2480
+ getBlocks(
2481
+ { blocks: withControlledContent },
2482
+ 'chicken'
2483
+ ).map( ( b ) => b.clientId )
2484
+ ).toEqual( [ 'content' ] );
2485
+ expect(
2486
+ getBlocks(
2487
+ { blocks: withControlledContent },
2488
+ 'content'
2489
+ ).map( ( b ) => b.clientId )
2490
+ ).toEqual( [ 'content-inner' ] );
2491
+
2492
+ const state = blocks( withControlledContent, {
2493
+ type: 'RESET_BLOCKS',
2494
+ blocks: [
2495
+ {
2496
+ clientId: 'chicken',
2497
+ name: 'core/test-block',
2498
+ attributes: {},
2499
+ innerBlocks: [],
2500
+ },
2501
+ ],
2502
+ } );
2503
+
2504
+ expect( state.controlledInnerBlocks.has( 'chicken' ) ).toBe(
2505
+ true
2506
+ );
2507
+ expect(
2508
+ getBlocks( { blocks: state }, 'chicken' ).map(
2509
+ ( b ) => b.clientId
2510
+ )
2511
+ ).toEqual( [ 'content' ] );
2512
+ expect(
2513
+ getBlocks( { blocks: state }, 'content' ).map(
2514
+ ( b ) => b.clientId
2515
+ )
2516
+ ).toEqual( [ 'content-inner' ] );
2517
+ } );
2518
+
2519
+ it( 'should forget controlledInnerBlocks during full RESET_BLOCKS', () => {
2520
+ const templateBlock = {
2521
+ clientId: 'template',
2522
+ name: 'core/post-content',
2523
+ attributes: {},
2524
+ innerBlocks: [],
2525
+ };
2526
+ const contentBlock = {
2527
+ clientId: 'content',
2528
+ name: 'core/paragraph',
2529
+ attributes: {},
2530
+ innerBlocks: [],
2531
+ };
2532
+
2533
+ let state = blocks( undefined, {
2534
+ type: 'RESET_BLOCKS',
2535
+ blocks: [ templateBlock ],
2536
+ } );
2537
+
2538
+ state = blocks( state, {
2539
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
2540
+ clientId: 'template',
2541
+ hasControlledInnerBlocks: true,
2542
+ } );
2543
+
2544
+ state = blocks( state, {
2545
+ type: 'REPLACE_INNER_BLOCKS',
2546
+ rootClientId: 'template',
2547
+ blocks: [ contentBlock ],
2548
+ } );
2549
+
2550
+ // Reset blocks completely, we expect that the controlled blocks are forgotten.
2551
+ state = blocks( state, {
2552
+ type: 'RESET_BLOCKS',
2553
+ blocks: [],
2554
+ } );
2555
+
2556
+ // Reset back to the template.
2557
+ state = blocks( state, {
2558
+ type: 'RESET_BLOCKS',
2559
+ blocks: [ templateBlock ],
2560
+ } );
2561
+
2562
+ // Expect that the `template`/`content` blocks are reconstructed.
2563
+ const fullState = { blocks: state };
2564
+ expect( getBlocks( fullState, 'template' ) ).toEqual( [] );
2565
+ expect( getBlockOrder( fullState, 'template' ) ).toEqual(
2566
+ []
2567
+ );
2568
+ } );
2569
+
2570
+ it( 'should not leave stale controlled tree entries after root replacement and reset', () => {
2571
+ const templateBlock = {
2572
+ clientId: 'template',
2573
+ name: 'core/post-content',
2574
+ attributes: {},
2575
+ innerBlocks: [],
2576
+ };
2577
+ const contentBlock = {
2578
+ clientId: 'content',
2579
+ name: 'core/paragraph',
2580
+ attributes: {},
2581
+ innerBlocks: [],
2582
+ };
2583
+
2584
+ // Initialize template, simulates root `useBlockSync` initialization.
2585
+ let state = blocks( undefined, {
2586
+ type: 'RESET_BLOCKS',
2587
+ blocks: [ templateBlock ],
2588
+ } );
2589
+
2590
+ // Add a controlled child to the template using two actions, simulates inner `useBlockSync` initialization.
2591
+ state = blocks( state, {
2592
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
2593
+ clientId: 'template',
2594
+ hasControlledInnerBlocks: true,
2595
+ } );
2596
+
2597
+ state = blocks( state, {
2598
+ type: 'REPLACE_INNER_BLOCKS',
2599
+ rootClientId: 'template',
2600
+ blocks: [ contentBlock ],
2601
+ } );
2602
+
2603
+ // Reset blocks completely, simulates root `useBlockSync` cleanup.
2604
+ state = blocks( state, {
2605
+ type: 'RESET_BLOCKS',
2606
+ blocks: [],
2607
+ } );
2608
+
2609
+ // Unset controlled inner blocks, simulates inner `useBlockSync` cleanup.
2610
+ state = blocks( state, {
2611
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
2612
+ clientId: 'template',
2613
+ hasControlledInnerBlocks: false,
2614
+ } );
2615
+
2616
+ // Initialize template again, simulates `useBlockSync` after navigation.
2617
+ state = blocks( state, {
2618
+ type: 'RESET_BLOCKS',
2619
+ blocks: [ templateBlock ],
2620
+ } );
2621
+
2622
+ // Set controlled inner blocks again, this time to empty.
2623
+ state = blocks( state, {
2624
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
2625
+ clientId: 'template',
2626
+ hasControlledInnerBlocks: true,
2627
+ } );
2628
+
2629
+ state = blocks( state, {
2630
+ type: 'REPLACE_INNER_BLOCKS',
2631
+ rootClientId: 'template',
2632
+ blocks: [],
2633
+ } );
2634
+
2635
+ // At this point the template has empty content, and `useInnerBlockTemplateSync` should apply
2636
+ // its template content. It will check if `getBlocks` is empty before applying the template.
2637
+ const fullState = { blocks: state };
2638
+ expect( getBlockOrder( fullState, 'template' ) ).toEqual(
2639
+ []
2640
+ );
2641
+ expect( getBlocks( fullState, 'template' ) ).toEqual( [] );
2479
2642
  } );
2480
2643
 
2481
2644
  it( 'should not create new state references when setting controlled inner blocks on a block with no inner blocks', () => {
@@ -2497,7 +2660,9 @@ describe( 'state', () => {
2497
2660
  hasControlledInnerBlocks: true,
2498
2661
  } );
2499
2662
 
2500
- expect( state.controlledInnerBlocks.chicken ).toBe( true );
2663
+ expect( state.controlledInnerBlocks.has( 'chicken' ) ).toBe(
2664
+ true
2665
+ );
2501
2666
  // The order and byClientId Maps should be the same
2502
2667
  // reference because the block has no inner blocks to
2503
2668
  // remove, so REPLACE_INNER_BLOCKS should be skipped.
@@ -3226,7 +3391,7 @@ describe( 'state', () => {
3226
3391
 
3227
3392
  describe( 'blockListSettings', () => {
3228
3393
  it( 'should add new settings', () => {
3229
- const original = deepFreeze( {} );
3394
+ const original = deepFreeze( new Map() );
3230
3395
 
3231
3396
  const state = blockListSettings( original, {
3232
3397
  type: 'UPDATE_BLOCK_LIST_SETTINGS',
@@ -3236,19 +3401,29 @@ describe( 'state', () => {
3236
3401
  },
3237
3402
  } );
3238
3403
 
3239
- expect( state ).toEqual( {
3240
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3241
- allowedBlocks: [ 'core/paragraph' ],
3242
- },
3243
- } );
3404
+ expect( state ).toEqual(
3405
+ new Map( [
3406
+ [
3407
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3408
+ {
3409
+ allowedBlocks: [ 'core/paragraph' ],
3410
+ },
3411
+ ],
3412
+ ] )
3413
+ );
3244
3414
  } );
3245
3415
 
3246
3416
  it( 'should return same reference if updated as the same', () => {
3247
- const original = deepFreeze( {
3248
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3249
- allowedBlocks: [ 'core/paragraph' ],
3250
- },
3251
- } );
3417
+ const original = deepFreeze(
3418
+ new Map( [
3419
+ [
3420
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3421
+ {
3422
+ allowedBlocks: [ 'core/paragraph' ],
3423
+ },
3424
+ ],
3425
+ ] )
3426
+ );
3252
3427
 
3253
3428
  const state = blockListSettings( original, {
3254
3429
  type: 'UPDATE_BLOCK_LIST_SETTINGS',
@@ -3262,7 +3437,7 @@ describe( 'state', () => {
3262
3437
  } );
3263
3438
 
3264
3439
  it( 'should return same reference if updated settings not assigned and id not exists', () => {
3265
- const original = deepFreeze( {} );
3440
+ const original = deepFreeze( new Map() );
3266
3441
 
3267
3442
  const state = blockListSettings( original, {
3268
3443
  type: 'UPDATE_BLOCK_LIST_SETTINGS',
@@ -3273,14 +3448,22 @@ describe( 'state', () => {
3273
3448
  } );
3274
3449
 
3275
3450
  it( 'should update the settings of a block', () => {
3276
- const original = deepFreeze( {
3277
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3278
- allowedBlocks: [ 'core/paragraph' ],
3279
- },
3280
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3281
- allowedBlocks: true,
3282
- },
3283
- } );
3451
+ const original = deepFreeze(
3452
+ new Map( [
3453
+ [
3454
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3455
+ {
3456
+ allowedBlocks: [ 'core/paragraph' ],
3457
+ },
3458
+ ],
3459
+ [
3460
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3461
+ {
3462
+ allowedBlocks: true,
3463
+ },
3464
+ ],
3465
+ ] )
3466
+ );
3284
3467
 
3285
3468
  const state = blockListSettings( original, {
3286
3469
  type: 'UPDATE_BLOCK_LIST_SETTINGS',
@@ -3290,40 +3473,61 @@ describe( 'state', () => {
3290
3473
  },
3291
3474
  } );
3292
3475
 
3293
- expect( state ).toEqual( {
3294
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3295
- allowedBlocks: [ 'core/list' ],
3296
- },
3297
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3298
- allowedBlocks: true,
3299
- },
3300
- } );
3476
+ expect( state ).toEqual(
3477
+ new Map( [
3478
+ [
3479
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3480
+ {
3481
+ allowedBlocks: [ 'core/list' ],
3482
+ },
3483
+ ],
3484
+ [
3485
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3486
+ {
3487
+ allowedBlocks: true,
3488
+ },
3489
+ ],
3490
+ ] )
3491
+ );
3301
3492
  } );
3302
3493
 
3303
3494
  it( 'should remove existing settings if updated settings not assigned', () => {
3304
- const original = deepFreeze( {
3305
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3306
- allowedBlocks: [ 'core/paragraph' ],
3307
- },
3308
- } );
3495
+ const original = deepFreeze(
3496
+ new Map( [
3497
+ [
3498
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3499
+ {
3500
+ allowedBlocks: [ 'core/paragraph' ],
3501
+ },
3502
+ ],
3503
+ ] )
3504
+ );
3309
3505
 
3310
3506
  const state = blockListSettings( original, {
3311
3507
  type: 'UPDATE_BLOCK_LIST_SETTINGS',
3312
3508
  clientId: '9db792c6-a25a-495d-adbd-97d56a4c4189',
3313
3509
  } );
3314
3510
 
3315
- expect( state ).toEqual( {} );
3511
+ expect( state ).toEqual( new Map() );
3316
3512
  } );
3317
3513
 
3318
3514
  it( 'should remove the settings of a block when it is replaced', () => {
3319
- const original = deepFreeze( {
3320
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3321
- allowedBlocks: [ 'core/paragraph' ],
3322
- },
3323
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3324
- allowedBlocks: true,
3325
- },
3326
- } );
3515
+ const original = deepFreeze(
3516
+ new Map( [
3517
+ [
3518
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3519
+ {
3520
+ allowedBlocks: [ 'core/paragraph' ],
3521
+ },
3522
+ ],
3523
+ [
3524
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3525
+ {
3526
+ allowedBlocks: true,
3527
+ },
3528
+ ],
3529
+ ] )
3530
+ );
3327
3531
 
3328
3532
  const state = blockListSettings( original, {
3329
3533
  type: 'REPLACE_BLOCKS',
@@ -3331,22 +3535,35 @@ describe( 'state', () => {
3331
3535
  blocks: [],
3332
3536
  } );
3333
3537
 
3334
- expect( state ).toEqual( {
3335
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3336
- allowedBlocks: [ 'core/paragraph' ],
3337
- },
3338
- } );
3538
+ expect( state ).toEqual(
3539
+ new Map( [
3540
+ [
3541
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3542
+ {
3543
+ allowedBlocks: [ 'core/paragraph' ],
3544
+ },
3545
+ ],
3546
+ ] )
3547
+ );
3339
3548
  } );
3340
3549
 
3341
3550
  it( 'should preserve the settings of a block when its clientId is reused in replacement', () => {
3342
- const original = deepFreeze( {
3343
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3344
- allowedBlocks: [ 'core/paragraph' ],
3345
- },
3346
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3347
- allowedBlocks: true,
3348
- },
3349
- } );
3551
+ const original = deepFreeze(
3552
+ new Map( [
3553
+ [
3554
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3555
+ {
3556
+ allowedBlocks: [ 'core/paragraph' ],
3557
+ },
3558
+ ],
3559
+ [
3560
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3561
+ {
3562
+ allowedBlocks: true,
3563
+ },
3564
+ ],
3565
+ ] )
3566
+ );
3350
3567
 
3351
3568
  const state = blockListSettings( original, {
3352
3569
  type: 'REPLACE_BLOCKS',
@@ -3359,29 +3576,42 @@ describe( 'state', () => {
3359
3576
  ],
3360
3577
  } );
3361
3578
 
3362
- expect( state ).toEqual( {
3363
- '9db792c6-a25a-495d-adbd-97d56a4c4189': {
3364
- allowedBlocks: [ 'core/paragraph' ],
3365
- },
3366
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3367
- allowedBlocks: true,
3368
- },
3369
- } );
3579
+ expect( state ).toEqual(
3580
+ new Map( [
3581
+ [
3582
+ '9db792c6-a25a-495d-adbd-97d56a4c4189',
3583
+ {
3584
+ allowedBlocks: [ 'core/paragraph' ],
3585
+ },
3586
+ ],
3587
+ [
3588
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3589
+ {
3590
+ allowedBlocks: true,
3591
+ },
3592
+ ],
3593
+ ] )
3594
+ );
3370
3595
  } );
3371
3596
 
3372
3597
  it( 'should remove the settings of a block when it is removed', () => {
3373
- const original = deepFreeze( {
3374
- 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1': {
3375
- allowedBlocks: true,
3376
- },
3377
- } );
3598
+ const original = deepFreeze(
3599
+ new Map( [
3600
+ [
3601
+ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1',
3602
+ {
3603
+ allowedBlocks: true,
3604
+ },
3605
+ ],
3606
+ ] )
3607
+ );
3378
3608
 
3379
3609
  const state = blockListSettings( original, {
3380
3610
  type: 'REMOVE_BLOCKS',
3381
3611
  clientIds: [ 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' ],
3382
3612
  } );
3383
3613
 
3384
- expect( state ).toEqual( {} );
3614
+ expect( state ).toEqual( new Map() );
3385
3615
  } );
3386
3616
  } );
3387
3617
 
@@ -3579,17 +3809,18 @@ describe( 'state', () => {
3579
3809
 
3580
3810
  describe( 'blockEditingModes', () => {
3581
3811
  it( 'should return an empty map by default', () => {
3582
- expect( blockEditingModes( undefined, {} ) ).toEqual( new Map() );
3812
+ const state = blocks( undefined, {} );
3813
+ expect( state.blockEditingModes ).toEqual( new Map() );
3583
3814
  } );
3584
3815
 
3585
3816
  it( 'should set the editing mode for a block', () => {
3586
- const state = new Map();
3587
- const newState = blockEditingModes( state, {
3817
+ const state = blocks( undefined, {} );
3818
+ const newState = blocks( state, {
3588
3819
  type: 'SET_BLOCK_EDITING_MODE',
3589
3820
  clientId: '14501cc2-90a6-4f52-aa36-ab6e896135d1',
3590
3821
  mode: 'default',
3591
3822
  } );
3592
- expect( newState ).toEqual(
3823
+ expect( newState.blockEditingModes ).toEqual(
3593
3824
  new Map( [
3594
3825
  [ '14501cc2-90a6-4f52-aa36-ab6e896135d1', 'default' ],
3595
3826
  ] )
@@ -3597,28 +3828,126 @@ describe( 'state', () => {
3597
3828
  } );
3598
3829
 
3599
3830
  it( 'should clear the editing mode for a block', () => {
3600
- const state = new Map( [
3601
- [ '14501cc2-90a6-4f52-aa36-ab6e896135d1', 'default' ],
3602
- ] );
3603
- const newState = blockEditingModes( state, {
3831
+ let state = blocks( undefined, {} );
3832
+ state = blocks( state, {
3833
+ type: 'SET_BLOCK_EDITING_MODE',
3834
+ clientId: '14501cc2-90a6-4f52-aa36-ab6e896135d1',
3835
+ mode: 'default',
3836
+ } );
3837
+ const newState = blocks( state, {
3604
3838
  type: 'UNSET_BLOCK_EDITING_MODE',
3605
3839
  clientId: '14501cc2-90a6-4f52-aa36-ab6e896135d1',
3606
3840
  } );
3607
- expect( newState ).toEqual( new Map() );
3841
+ expect( newState.blockEditingModes ).toEqual( new Map() );
3608
3842
  } );
3609
3843
 
3610
- it( 'should clear editing modes when blocks are reset', () => {
3611
- const state = new Map( [
3612
- [ '', 'disabled' ],
3613
- [ '14501cc2-90a6-4f52-aa36-ab6e896135d1', 'default' ],
3614
- ] );
3615
- const newState = blockEditingModes( state, {
3844
+ it( 'should preserve editing modes when blocks are reset', () => {
3845
+ // Add a template with two template parts.
3846
+ let state = blocks( undefined, {} );
3847
+ state = blocks( state, {
3616
3848
  type: 'RESET_BLOCKS',
3849
+ blocks: [
3850
+ {
3851
+ name: 'core/template-part',
3852
+ clientId: 'template-part-1',
3853
+ attributes: {},
3854
+ innerBlocks: [],
3855
+ },
3856
+ {
3857
+ name: 'core/template-part',
3858
+ clientId: 'template-part-2',
3859
+ attributes: {},
3860
+ innerBlocks: [],
3861
+ },
3862
+ ],
3863
+ } );
3864
+
3865
+ // In each of the template parts add a controlled content (a paragraph block).
3866
+ state = blocks( state, {
3867
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
3868
+ clientId: 'template-part-1',
3869
+ hasControlledInnerBlocks: true,
3870
+ } );
3871
+ state = blocks( state, {
3872
+ type: 'REPLACE_INNER_BLOCKS',
3873
+ rootClientId: 'template-part-1',
3874
+ blocks: [
3875
+ {
3876
+ name: 'core/paragraph',
3877
+ clientId: 'paragraph-1',
3878
+ attributes: {},
3879
+ innerBlocks: [],
3880
+ },
3881
+ ],
3617
3882
  } );
3618
- expect( newState ).toEqual(
3883
+ state = blocks( state, {
3884
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
3885
+ clientId: 'template-part-2',
3886
+ hasControlledInnerBlocks: true,
3887
+ } );
3888
+ state = blocks( state, {
3889
+ type: 'REPLACE_INNER_BLOCKS',
3890
+ rootClientId: 'template-part-2',
3891
+ blocks: [
3892
+ {
3893
+ name: 'core/paragraph',
3894
+ clientId: 'paragraph-2',
3895
+ attributes: {},
3896
+ innerBlocks: [],
3897
+ },
3898
+ ],
3899
+ } );
3900
+
3901
+ // Set block editing modes, just like `DisableNonPageContentBlocks` would do:
3902
+ // - the root block to 'disabled'
3903
+ // - the template parts to 'contentOnly'
3904
+ // - the template part children to 'disabled'
3905
+ state = blocks( state, {
3906
+ type: 'SET_BLOCK_EDITING_MODE',
3907
+ clientId: '',
3908
+ mode: 'disabled',
3909
+ } );
3910
+ state = blocks( state, {
3911
+ type: 'SET_BLOCK_EDITING_MODE',
3912
+ clientId: 'template-part-1',
3913
+ mode: 'contentOnly',
3914
+ } );
3915
+ state = blocks( state, {
3916
+ type: 'SET_BLOCK_EDITING_MODE',
3917
+ clientId: 'template-part-2',
3918
+ mode: 'contentOnly',
3919
+ } );
3920
+ state = blocks( state, {
3921
+ type: 'SET_BLOCK_EDITING_MODE',
3922
+ clientId: 'paragraph-1',
3923
+ mode: 'disabled',
3924
+ } );
3925
+ state = blocks( state, {
3926
+ type: 'SET_BLOCK_EDITING_MODE',
3927
+ clientId: 'paragraph-2',
3928
+ mode: 'disabled',
3929
+ } );
3930
+
3931
+ // Reset the template, keeping only one of the template parts.
3932
+ state = blocks( state, {
3933
+ type: 'RESET_BLOCKS',
3934
+ blocks: [
3935
+ {
3936
+ name: 'core/template-part',
3937
+ clientId: 'template-part-1',
3938
+ attributes: {},
3939
+ innerBlocks: [],
3940
+ },
3941
+ ],
3942
+ } );
3943
+
3944
+ // Check that the editing modes for valid blocks are preserved, and the
3945
+ // editing modes for removed blocks are cleared.
3946
+ expect( state.blockEditingModes ).toEqual(
3619
3947
  new Map( [
3620
- // Root mode should be maintained.
3621
3948
  [ '', 'disabled' ],
3949
+ [ 'template-part-1', 'contentOnly' ],
3950
+ [ 'paragraph-1', 'disabled' ],
3622
3951
  ] )
3623
3952
  );
3624
3953
  } );
@@ -3649,6 +3978,119 @@ describe( 'state', () => {
3649
3978
  } );
3650
3979
  } );
3651
3980
 
3981
+ describe( 'editedContentOnlySection', () => {
3982
+ it( 'returns undefined by default', () => {
3983
+ expect(
3984
+ editedContentOnlySection( undefined, { type: 'UNKNOWN' } )
3985
+ ).toBeUndefined();
3986
+ } );
3987
+
3988
+ it( 'sets the clientId on EDIT_CONTENT_ONLY_SECTION', () => {
3989
+ const state = editedContentOnlySection( undefined, {
3990
+ type: 'EDIT_CONTENT_ONLY_SECTION',
3991
+ clientId: 'block-1',
3992
+ } );
3993
+ expect( state ).toBe( 'block-1' );
3994
+ } );
3995
+
3996
+ it( 'clears the clientId when EDIT_CONTENT_ONLY_SECTION has no clientId', () => {
3997
+ const state = editedContentOnlySection( 'block-1', {
3998
+ type: 'EDIT_CONTENT_ONLY_SECTION',
3999
+ } );
4000
+ expect( state ).toBeUndefined();
4001
+ } );
4002
+
4003
+ it( 'clears when the edited section is directly removed via REMOVE_BLOCKS', () => {
4004
+ const state = editedContentOnlySection( 'block-1', {
4005
+ type: 'REMOVE_BLOCKS',
4006
+ clientIds: [ 'block-1' ],
4007
+ } );
4008
+ expect( state ).toBeUndefined();
4009
+ } );
4010
+
4011
+ it( 'keeps state when REMOVE_BLOCKS targets other blocks', () => {
4012
+ const state = editedContentOnlySection( 'block-1', {
4013
+ type: 'REMOVE_BLOCKS',
4014
+ clientIds: [ 'block-2', 'block-3' ],
4015
+ } );
4016
+ expect( state ).toBe( 'block-1' );
4017
+ } );
4018
+
4019
+ it( 'clears when the edited section is directly replaced via REPLACE_BLOCKS', () => {
4020
+ const state = editedContentOnlySection( 'block-1', {
4021
+ type: 'REPLACE_BLOCKS',
4022
+ clientIds: [ 'block-1' ],
4023
+ blocks: [ { clientId: 'block-new', innerBlocks: [] } ],
4024
+ } );
4025
+ expect( state ).toBeUndefined();
4026
+ } );
4027
+
4028
+ it( 'keeps state when REPLACE_BLOCKS targets other blocks', () => {
4029
+ const state = editedContentOnlySection( 'block-1', {
4030
+ type: 'REPLACE_BLOCKS',
4031
+ clientIds: [ 'block-2' ],
4032
+ blocks: [ { clientId: 'block-new', innerBlocks: [] } ],
4033
+ } );
4034
+ expect( state ).toBe( 'block-1' );
4035
+ } );
4036
+
4037
+ it( 'clears when RESET_BLOCKS does not include the edited section', () => {
4038
+ const state = editedContentOnlySection( 'block-1', {
4039
+ type: 'RESET_BLOCKS',
4040
+ blocks: [
4041
+ { clientId: 'block-2', innerBlocks: [] },
4042
+ { clientId: 'block-3', innerBlocks: [] },
4043
+ ],
4044
+ } );
4045
+ expect( state ).toBeUndefined();
4046
+ } );
4047
+
4048
+ it( 'keeps state when RESET_BLOCKS includes the edited section at the top level', () => {
4049
+ const state = editedContentOnlySection( 'block-1', {
4050
+ type: 'RESET_BLOCKS',
4051
+ blocks: [
4052
+ { clientId: 'block-1', innerBlocks: [] },
4053
+ { clientId: 'block-2', innerBlocks: [] },
4054
+ ],
4055
+ } );
4056
+ expect( state ).toBe( 'block-1' );
4057
+ } );
4058
+
4059
+ it( 'keeps state when RESET_BLOCKS includes the edited section nested in innerBlocks', () => {
4060
+ const state = editedContentOnlySection( 'block-1', {
4061
+ type: 'RESET_BLOCKS',
4062
+ blocks: [
4063
+ {
4064
+ clientId: 'block-parent',
4065
+ innerBlocks: [
4066
+ {
4067
+ clientId: 'block-1',
4068
+ innerBlocks: [],
4069
+ },
4070
+ ],
4071
+ },
4072
+ ],
4073
+ } );
4074
+ expect( state ).toBe( 'block-1' );
4075
+ } );
4076
+
4077
+ it( 'does not clear on unrelated actions when state is set', () => {
4078
+ const state = editedContentOnlySection( 'block-1', {
4079
+ type: 'SELECT_BLOCK',
4080
+ clientId: 'block-2',
4081
+ } );
4082
+ expect( state ).toBe( 'block-1' );
4083
+ } );
4084
+
4085
+ it( 'does not run cleanup logic when state is already empty', () => {
4086
+ const state = editedContentOnlySection( undefined, {
4087
+ type: 'REMOVE_BLOCKS',
4088
+ clientIds: [ 'block-1' ],
4089
+ } );
4090
+ expect( state ).toBeUndefined();
4091
+ } );
4092
+ } );
4093
+
3652
4094
  describe( 'insertionPoint', () => {
3653
4095
  it( 'should default to null', () => {
3654
4096
  const state = insertionPoint( undefined, {} );
@@ -3691,7 +4133,6 @@ describe( 'state', () => {
3691
4133
  settings,
3692
4134
  zoomLevel,
3693
4135
  blockListSettings,
3694
- blockEditingModes,
3695
4136
  editedContentOnlySection,
3696
4137
  } )
3697
4138
  );