@wordpress/block-editor 15.3.1-next.6f42e1382.0 → 15.3.1-next.a730c9c8c.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 (65) hide show
  1. package/build/components/block-card/index.js +4 -2
  2. package/build/components/block-card/index.js.map +1 -1
  3. package/build/components/block-inspector/edit-contents-button.js +54 -0
  4. package/build/components/block-inspector/edit-contents-button.js.map +1 -0
  5. package/build/components/block-inspector/index.js +5 -1
  6. package/build/components/block-inspector/index.js.map +1 -1
  7. package/build/components/block-switcher/index.js +3 -3
  8. package/build/components/block-switcher/index.js.map +1 -1
  9. package/build/components/block-variation-transforms/index.js +1 -1
  10. package/build/components/block-variation-transforms/index.js.map +1 -1
  11. package/build/components/border-radius-control/utils.js.map +1 -1
  12. package/build/components/global-styles/border-panel.js +6 -6
  13. package/build/components/global-styles/border-panel.js.map +1 -1
  14. package/build/components/url-popover/image-url-input-ui.js +7 -2
  15. package/build/components/url-popover/image-url-input-ui.js.map +1 -1
  16. package/build/components/writing-flow/use-clipboard-handler.js +6 -1
  17. package/build/components/writing-flow/use-clipboard-handler.js.map +1 -1
  18. package/build/store/private-selectors.js +3 -2
  19. package/build/store/private-selectors.js.map +1 -1
  20. package/build/store/reducer.js +55 -1
  21. package/build/store/reducer.js.map +1 -1
  22. package/build/utils/block-bindings.js +1 -1
  23. package/build/utils/block-bindings.js.map +1 -1
  24. package/build-module/components/block-card/index.js +4 -2
  25. package/build-module/components/block-card/index.js.map +1 -1
  26. package/build-module/components/block-inspector/edit-contents-button.js +47 -0
  27. package/build-module/components/block-inspector/edit-contents-button.js.map +1 -0
  28. package/build-module/components/block-inspector/index.js +5 -1
  29. package/build-module/components/block-inspector/index.js.map +1 -1
  30. package/build-module/components/block-switcher/index.js +3 -3
  31. package/build-module/components/block-switcher/index.js.map +1 -1
  32. package/build-module/components/block-variation-transforms/index.js +1 -1
  33. package/build-module/components/block-variation-transforms/index.js.map +1 -1
  34. package/build-module/components/border-radius-control/utils.js.map +1 -1
  35. package/build-module/components/global-styles/border-panel.js +6 -6
  36. package/build-module/components/global-styles/border-panel.js.map +1 -1
  37. package/build-module/components/url-popover/image-url-input-ui.js +9 -4
  38. package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
  39. package/build-module/components/writing-flow/use-clipboard-handler.js +6 -1
  40. package/build-module/components/writing-flow/use-clipboard-handler.js.map +1 -1
  41. package/build-module/store/private-selectors.js +3 -2
  42. package/build-module/store/private-selectors.js.map +1 -1
  43. package/build-module/store/reducer.js +55 -1
  44. package/build-module/store/reducer.js.map +1 -1
  45. package/build-module/utils/block-bindings.js +1 -1
  46. package/build-module/utils/block-bindings.js.map +1 -1
  47. package/build-style/style-rtl.css +9 -4
  48. package/build-style/style.css +9 -4
  49. package/package.json +34 -34
  50. package/src/components/block-card/index.js +11 -1
  51. package/src/components/block-inspector/edit-contents-button.js +46 -0
  52. package/src/components/block-inspector/index.js +6 -1
  53. package/src/components/block-inspector/style.scss +5 -0
  54. package/src/components/block-switcher/index.js +5 -3
  55. package/src/components/block-toolbar/style.scss +3 -5
  56. package/src/components/block-variation-transforms/index.js +2 -1
  57. package/src/components/border-radius-control/test/utils.js +71 -0
  58. package/src/components/border-radius-control/utils.js +1 -0
  59. package/src/components/global-styles/border-panel.js +7 -6
  60. package/src/components/url-popover/image-url-input-ui.js +18 -2
  61. package/src/components/writing-flow/use-clipboard-handler.js +6 -0
  62. package/src/store/private-selectors.js +3 -2
  63. package/src/store/reducer.js +83 -0
  64. package/src/store/test/reducer.js +291 -0
  65. package/src/utils/block-bindings.js +1 -1
@@ -2286,6 +2286,9 @@ function getDerivedBlockEditingModesForTree(
2286
2286
  const contentOnlyParents = [
2287
2287
  ...contentOnlyTemplateLockedClientIds,
2288
2288
  ...unsyncedPatternClientIds,
2289
+ ...( window?.__experimentalContentOnlyPatternInsertion
2290
+ ? templatePartClientIds
2291
+ : [] ),
2289
2292
  ];
2290
2293
 
2291
2294
  traverseBlockTree( state, treeClientId, ( block ) => {
@@ -2664,6 +2667,86 @@ export function withDerivedBlockEditingModes( reducer ) {
2664
2667
  }
2665
2668
  break;
2666
2669
  }
2670
+ case 'UPDATE_BLOCK_ATTRIBUTES': {
2671
+ // Handle unsynced patterns which indicate their contentOnly-ness via
2672
+ // the `attributes.metadata.patternName` property.
2673
+ // Check when this is added or removed and update blockEditingModes.
2674
+ const addedBlocks = [];
2675
+ const removedClientIds = [];
2676
+
2677
+ for ( const clientId of action?.clientIds ) {
2678
+ const attributes = action.options?.uniqueByBlock
2679
+ ? action.attributes[ clientId ]
2680
+ : action.attributes;
2681
+
2682
+ if ( ! attributes ) {
2683
+ break;
2684
+ }
2685
+
2686
+ if (
2687
+ // patternName is switching from falsy to truthy, indicating
2688
+ // this block is becoming an unsynced pattern.
2689
+ attributes.metadata?.patternName &&
2690
+ ! state.blocks.attributes.get( clientId )?.metadata
2691
+ ?.patternName
2692
+ ) {
2693
+ addedBlocks.push(
2694
+ nextState.blocks.tree.get( clientId )
2695
+ );
2696
+ } else if (
2697
+ // patternName is switching from truthy to falsy, this block is becoming
2698
+ // a regular block but was an unsynced pattern.
2699
+ // Check that `metadata` is part of the included attributes, as
2700
+ // `updateBlockAttributes` merges attributes, if it isn't present
2701
+ // the previous `metadata` would be retained.
2702
+ attributes.metadata &&
2703
+ ! attributes.metadata?.patternName &&
2704
+ state.blocks.attributes.get( clientId )?.metadata
2705
+ ?.patternName
2706
+ ) {
2707
+ // Include it in 'removedClientIds'.
2708
+ removedClientIds.push( clientId );
2709
+ }
2710
+ }
2711
+
2712
+ if ( ! addedBlocks?.length && ! removedClientIds?.length ) {
2713
+ break;
2714
+ }
2715
+
2716
+ const nextDerivedBlockEditingModes =
2717
+ getDerivedBlockEditingModesUpdates( {
2718
+ prevState: state,
2719
+ nextState,
2720
+ addedBlocks,
2721
+ removedClientIds,
2722
+ isNavMode: false,
2723
+ } );
2724
+ const nextDerivedNavModeBlockEditingModes =
2725
+ getDerivedBlockEditingModesUpdates( {
2726
+ prevState: state,
2727
+ nextState,
2728
+ addedBlocks,
2729
+ removedClientIds,
2730
+ isNavMode: true,
2731
+ } );
2732
+
2733
+ if (
2734
+ nextDerivedBlockEditingModes ||
2735
+ nextDerivedNavModeBlockEditingModes
2736
+ ) {
2737
+ return {
2738
+ ...nextState,
2739
+ derivedBlockEditingModes:
2740
+ nextDerivedBlockEditingModes ??
2741
+ state.derivedBlockEditingModes,
2742
+ derivedNavModeBlockEditingModes:
2743
+ nextDerivedNavModeBlockEditingModes ??
2744
+ state.derivedNavModeBlockEditingModes,
2745
+ };
2746
+ }
2747
+
2748
+ break;
2749
+ }
2667
2750
  case 'UPDATE_BLOCK_LIST_SETTINGS': {
2668
2751
  // Handle the addition and removal of contentOnly template locked blocks.
2669
2752
  const addedBlocks = [];
@@ -4505,5 +4505,296 @@ describe( 'state', () => {
4505
4505
  );
4506
4506
  } );
4507
4507
  } );
4508
+
4509
+ // Tests for the contentOnly experiments pattern.
4510
+ // If/when the experiment is stabilized, this wrapping `describe` and
4511
+ // `beforeAll`/`afterAll` can be removed, un-nesting the tests within.
4512
+ describe( 'contentOnly patterns experiment', () => {
4513
+ beforeAll( () => {
4514
+ globalThis.window.__experimentalContentOnlyPatternInsertion = true;
4515
+ } );
4516
+
4517
+ afterAll( () => {
4518
+ delete globalThis.window
4519
+ .__experimentalContentOnlyPatternInsertion;
4520
+ } );
4521
+
4522
+ describe( 'unsynced patterns', () => {
4523
+ let initialState;
4524
+ beforeAll( () => {
4525
+ initialState = dispatchActions(
4526
+ [
4527
+ {
4528
+ type: 'RESET_BLOCKS',
4529
+ blocks: [
4530
+ {
4531
+ name: 'core/group',
4532
+ clientId: 'group-1',
4533
+ attributes: {
4534
+ metadata: {
4535
+ patternName: 'test-pattern',
4536
+ },
4537
+ },
4538
+ innerBlocks: [
4539
+ {
4540
+ name: 'core/paragraph',
4541
+ clientId: 'paragraph-1',
4542
+ attributes: {},
4543
+ innerBlocks: [],
4544
+ },
4545
+ {
4546
+ name: 'core/group',
4547
+ clientId: 'group-2',
4548
+ attributes: {},
4549
+ innerBlocks: [
4550
+ {
4551
+ name: 'core/paragraph',
4552
+ clientId: 'paragraph-2',
4553
+ attributes: {},
4554
+ innerBlocks: [],
4555
+ },
4556
+ ],
4557
+ },
4558
+ ],
4559
+ },
4560
+ ],
4561
+ },
4562
+ ],
4563
+ testReducer,
4564
+ initialState
4565
+ );
4566
+ } );
4567
+
4568
+ it( 'returns the expected block editing modes for an unsynced pattern', () => {
4569
+ expect( initialState.derivedBlockEditingModes ).toEqual(
4570
+ new Map(
4571
+ Object.entries( {
4572
+ 'paragraph-1': 'contentOnly',
4573
+ 'group-2': 'disabled',
4574
+ 'paragraph-2': 'contentOnly',
4575
+ } )
4576
+ )
4577
+ );
4578
+ } );
4579
+
4580
+ it( 'removes block editing modes when an unsynced pattern is removed', () => {
4581
+ const { derivedBlockEditingModes } = dispatchActions(
4582
+ [
4583
+ {
4584
+ type: 'REMOVE_BLOCKS',
4585
+ clientIds: [ 'group-1' ],
4586
+ },
4587
+ ],
4588
+ testReducer,
4589
+ initialState
4590
+ );
4591
+
4592
+ expect( derivedBlockEditingModes ).toEqual( new Map() );
4593
+ } );
4594
+
4595
+ it( 'removes block editing modes when the `patternName` attribute is removed from the unsynced pattern', () => {
4596
+ const { derivedBlockEditingModes } = dispatchActions(
4597
+ [
4598
+ {
4599
+ type: 'UPDATE_BLOCK_ATTRIBUTES',
4600
+ clientIds: [ 'group-1' ],
4601
+ attributes: {
4602
+ metadata: {
4603
+ patternName: undefined,
4604
+ },
4605
+ },
4606
+ },
4607
+ ],
4608
+ testReducer,
4609
+ initialState
4610
+ );
4611
+
4612
+ expect( derivedBlockEditingModes ).toEqual( new Map() );
4613
+ } );
4614
+
4615
+ it( 'allows explicitly set blockEditingModes to override the unsynced pattern editing modes', () => {
4616
+ const { derivedBlockEditingModes } = dispatchActions(
4617
+ [
4618
+ {
4619
+ type: 'SET_BLOCK_EDITING_MODE',
4620
+ clientId: 'paragraph-2',
4621
+ mode: 'disabled',
4622
+ },
4623
+ ],
4624
+ testReducer,
4625
+ initialState
4626
+ );
4627
+
4628
+ expect( derivedBlockEditingModes ).toEqual(
4629
+ new Map(
4630
+ Object.entries( {
4631
+ 'paragraph-1': 'contentOnly',
4632
+ 'group-2': 'disabled',
4633
+ // Paragraph 2 already has an explicit mode, so isn't set as a derived mode.
4634
+ } )
4635
+ )
4636
+ );
4637
+ } );
4638
+
4639
+ it( 'sets the correct block editing modes when a new unsynced pattern is inserted', () => {
4640
+ const { derivedBlockEditingModes } = dispatchActions(
4641
+ [
4642
+ {
4643
+ type: 'INSERT_BLOCKS',
4644
+ rootClientId: '',
4645
+ index: 1,
4646
+ blocks: [
4647
+ {
4648
+ name: 'core/group',
4649
+ clientId: 'group-3',
4650
+ attributes: {
4651
+ metadata: {
4652
+ patternName: 'test-pattern-2',
4653
+ },
4654
+ },
4655
+ innerBlocks: [
4656
+ {
4657
+ name: 'core/paragraph',
4658
+ clientId: 'paragraph-3',
4659
+ attributes: {},
4660
+ innerBlocks: [],
4661
+ },
4662
+ ],
4663
+ },
4664
+ ],
4665
+ },
4666
+ ],
4667
+ testReducer,
4668
+ initialState
4669
+ );
4670
+
4671
+ expect( derivedBlockEditingModes ).toEqual(
4672
+ new Map(
4673
+ Object.entries( {
4674
+ 'paragraph-1': 'contentOnly',
4675
+ 'group-2': 'disabled',
4676
+ 'paragraph-2': 'contentOnly',
4677
+ 'paragraph-3': 'contentOnly',
4678
+ } )
4679
+ )
4680
+ );
4681
+ } );
4682
+ } );
4683
+
4684
+ describe( 'template parts', () => {
4685
+ let initialState;
4686
+ beforeAll( () => {
4687
+ // Simulates how the editor typically inserts controlled blocks,
4688
+ // - first the template part is inserted with no inner blocks.
4689
+ // - next the template part is marked as a controlled block.
4690
+ // - finally, once the inner blocks of the template part are received, they're inserted.
4691
+ initialState = dispatchActions(
4692
+ [
4693
+ {
4694
+ type: 'RESET_BLOCKS',
4695
+ blocks: [
4696
+ {
4697
+ name: 'core/template-part',
4698
+ clientId: 'template-part',
4699
+ attributes: {},
4700
+ innerBlocks: [],
4701
+ },
4702
+ ],
4703
+ },
4704
+ {
4705
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
4706
+ clientId: 'template-part',
4707
+ hasControlledInnerBlocks: true,
4708
+ },
4709
+ {
4710
+ type: 'REPLACE_INNER_BLOCKS',
4711
+ rootClientId: 'template-part',
4712
+ blocks: [
4713
+ {
4714
+ name: 'core/paragraph',
4715
+ clientId: 'template-part-paragraph',
4716
+ attributes: {},
4717
+ innerBlocks: [],
4718
+ },
4719
+ {
4720
+ name: 'core/group',
4721
+ clientId: 'template-part-group',
4722
+ attributes: {},
4723
+ innerBlocks: [
4724
+ {
4725
+ name: 'core/paragraph',
4726
+ clientId:
4727
+ 'template-part-grouped-paragraph',
4728
+ attributes: {},
4729
+ innerBlocks: [],
4730
+ },
4731
+ ],
4732
+ },
4733
+ ],
4734
+ },
4735
+ ],
4736
+ testReducer,
4737
+ initialState
4738
+ );
4739
+ } );
4740
+
4741
+ it( 'returns the expected block editing modes for synced patterns', () => {
4742
+ expect( initialState.derivedBlockEditingModes ).toEqual(
4743
+ new Map(
4744
+ Object.entries( {
4745
+ 'template-part-paragraph': 'contentOnly',
4746
+ 'template-part-group': 'disabled',
4747
+ 'template-part-grouped-paragraph':
4748
+ 'contentOnly',
4749
+ } )
4750
+ )
4751
+ );
4752
+ } );
4753
+
4754
+ it( 'removes the block editing modes when the template part is removed', () => {
4755
+ const { derivedBlockEditingModes } = dispatchActions(
4756
+ [
4757
+ {
4758
+ type: 'REMOVE_BLOCKS',
4759
+ clientIds: [ 'template-part' ],
4760
+ },
4761
+ {
4762
+ type: 'SET_HAS_CONTROLLED_INNER_BLOCKS',
4763
+ clientId: 'template-part',
4764
+ hasControlledInnerBlocks: false,
4765
+ },
4766
+ ],
4767
+ testReducer,
4768
+ initialState
4769
+ );
4770
+
4771
+ expect( derivedBlockEditingModes ).toEqual( new Map() );
4772
+ } );
4773
+
4774
+ it( 'allows explicitly set blockEditingModes to override the template part editing modes', () => {
4775
+ const { derivedBlockEditingModes } = dispatchActions(
4776
+ [
4777
+ {
4778
+ type: 'SET_BLOCK_EDITING_MODE',
4779
+ clientId: 'template-part-grouped-paragraph',
4780
+ mode: 'disabled',
4781
+ },
4782
+ ],
4783
+ testReducer,
4784
+ initialState
4785
+ );
4786
+
4787
+ expect( derivedBlockEditingModes ).toEqual(
4788
+ new Map(
4789
+ Object.entries( {
4790
+ 'template-part-paragraph': 'contentOnly',
4791
+ 'template-part-group': 'disabled',
4792
+ // template-part-grouped-paragraph already has an explicit mode, so isn't set as a derived mode.
4793
+ } )
4794
+ )
4795
+ );
4796
+ } );
4797
+ } );
4798
+ } );
4508
4799
  } );
4509
4800
  } );
@@ -14,7 +14,7 @@ const PATTERN_OVERRIDES_SOURCE = 'core/pattern-overrides';
14
14
  const BLOCK_BINDINGS_ALLOWED_BLOCKS = {
15
15
  'core/paragraph': [ 'content' ],
16
16
  'core/heading': [ 'content' ],
17
- 'core/image': [ 'id', 'url', 'title', 'alt' ],
17
+ 'core/image': [ 'id', 'url', 'title', 'alt', 'caption' ],
18
18
  'core/button': [ 'url', 'text', 'linkTarget', 'rel' ],
19
19
  'core/post-date': [ 'datetime' ],
20
20
  };