@wordpress/block-editor 13.1.0 → 13.2.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 (142) hide show
  1. package/CHANGELOG.md +19 -17
  2. package/README.md +1 -1
  3. package/build/components/block-lock/modal.js +67 -67
  4. package/build/components/block-lock/modal.js.map +1 -1
  5. package/build/components/block-mover/index.js +12 -6
  6. package/build/components/block-mover/index.js.map +1 -1
  7. package/build/components/block-toolbar/shuffle.js +3 -1
  8. package/build/components/block-toolbar/shuffle.js.map +1 -1
  9. package/build/components/child-layout-control/index.js +185 -127
  10. package/build/components/child-layout-control/index.js.map +1 -1
  11. package/build/components/global-styles/use-global-styles-output.js +4 -3
  12. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  13. package/build/components/grid/grid-item-movers.js +97 -0
  14. package/build/components/grid/grid-item-movers.js.map +1 -0
  15. package/build/components/{grid-visualizer → grid}/grid-item-resizer.js +18 -56
  16. package/build/components/grid/grid-item-resizer.js.map +1 -0
  17. package/build/components/grid/grid-visualizer.js +225 -0
  18. package/build/components/grid/grid-visualizer.js.map +1 -0
  19. package/build/components/{grid-visualizer → grid}/index.js +14 -0
  20. package/build/components/grid/index.js.map +1 -0
  21. package/build/components/grid/use-get-number-of-blocks-before-cell.js +40 -0
  22. package/build/components/grid/use-get-number-of-blocks-before-cell.js.map +1 -0
  23. package/build/components/grid/use-grid-layout-sync.js +162 -0
  24. package/build/components/grid/use-grid-layout-sync.js.map +1 -0
  25. package/build/components/grid/utils.js +145 -0
  26. package/build/components/grid/utils.js.map +1 -0
  27. package/build/components/image-editor/aspect-ratio-dropdown.js +0 -1
  28. package/build/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  29. package/build/components/inner-blocks/index.js +1 -1
  30. package/build/components/inner-blocks/index.js.map +1 -1
  31. package/build/components/rich-text/event-listeners/input-rules.js +1 -0
  32. package/build/components/rich-text/event-listeners/input-rules.js.map +1 -1
  33. package/build/components/rich-text/index.native.js +10 -4
  34. package/build/components/rich-text/index.native.js.map +1 -1
  35. package/build/components/rich-text/native/index.native.js +14 -0
  36. package/build/components/rich-text/native/index.native.js.map +1 -1
  37. package/build/hooks/block-style-variation.js +26 -7
  38. package/build/hooks/block-style-variation.js.map +1 -1
  39. package/build/hooks/layout-child.js +29 -21
  40. package/build/hooks/layout-child.js.map +1 -1
  41. package/build/hooks/utils.js +3 -2
  42. package/build/hooks/utils.js.map +1 -1
  43. package/build/layouts/grid.js +24 -47
  44. package/build/layouts/grid.js.map +1 -1
  45. package/build/lock-unlock.js +1 -1
  46. package/build/lock-unlock.js.map +1 -1
  47. package/build/store/actions.js +17 -1
  48. package/build/store/actions.js.map +1 -1
  49. package/build-module/components/block-lock/modal.js +67 -67
  50. package/build-module/components/block-lock/modal.js.map +1 -1
  51. package/build-module/components/block-mover/index.js +12 -6
  52. package/build-module/components/block-mover/index.js.map +1 -1
  53. package/build-module/components/block-toolbar/shuffle.js +3 -1
  54. package/build-module/components/block-toolbar/shuffle.js.map +1 -1
  55. package/build-module/components/child-layout-control/index.js +185 -127
  56. package/build-module/components/child-layout-control/index.js.map +1 -1
  57. package/build-module/components/global-styles/use-global-styles-output.js +4 -3
  58. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  59. package/build-module/components/grid/grid-item-movers.js +90 -0
  60. package/build-module/components/grid/grid-item-movers.js.map +1 -0
  61. package/build-module/components/{grid-visualizer → grid}/grid-item-resizer.js +13 -51
  62. package/build-module/components/grid/grid-item-resizer.js.map +1 -0
  63. package/build-module/components/grid/grid-visualizer.js +217 -0
  64. package/build-module/components/grid/grid-visualizer.js.map +1 -0
  65. package/build-module/components/grid/index.js +5 -0
  66. package/build-module/components/grid/index.js.map +1 -0
  67. package/build-module/components/grid/use-get-number-of-blocks-before-cell.js +33 -0
  68. package/build-module/components/grid/use-get-number-of-blocks-before-cell.js.map +1 -0
  69. package/build-module/components/grid/use-grid-layout-sync.js +155 -0
  70. package/build-module/components/grid/use-grid-layout-sync.js.map +1 -0
  71. package/build-module/components/grid/utils.js +131 -0
  72. package/build-module/components/grid/utils.js.map +1 -0
  73. package/build-module/components/image-editor/aspect-ratio-dropdown.js +0 -1
  74. package/build-module/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  75. package/build-module/components/inner-blocks/index.js +1 -1
  76. package/build-module/components/inner-blocks/index.js.map +1 -1
  77. package/build-module/components/rich-text/event-listeners/input-rules.js +1 -1
  78. package/build-module/components/rich-text/event-listeners/input-rules.js.map +1 -1
  79. package/build-module/components/rich-text/index.native.js +11 -5
  80. package/build-module/components/rich-text/index.native.js.map +1 -1
  81. package/build-module/components/rich-text/native/index.native.js +14 -0
  82. package/build-module/components/rich-text/native/index.native.js.map +1 -1
  83. package/build-module/hooks/block-style-variation.js +25 -7
  84. package/build-module/hooks/block-style-variation.js.map +1 -1
  85. package/build-module/hooks/layout-child.js +27 -19
  86. package/build-module/hooks/layout-child.js.map +1 -1
  87. package/build-module/hooks/utils.js +3 -2
  88. package/build-module/hooks/utils.js.map +1 -1
  89. package/build-module/layouts/grid.js +24 -47
  90. package/build-module/layouts/grid.js.map +1 -1
  91. package/build-module/lock-unlock.js +1 -1
  92. package/build-module/lock-unlock.js.map +1 -1
  93. package/build-module/store/actions.js +17 -1
  94. package/build-module/store/actions.js.map +1 -1
  95. package/build-style/style-rtl.css +39 -18
  96. package/build-style/style.css +39 -18
  97. package/package.json +31 -31
  98. package/src/components/block-lock/modal.js +95 -82
  99. package/src/components/block-lock/style.scss +11 -1
  100. package/src/components/block-mover/index.js +37 -24
  101. package/src/components/block-toolbar/shuffle.js +3 -1
  102. package/src/components/child-layout-control/index.js +224 -159
  103. package/src/components/global-styles/test/use-global-styles-output.js +38 -3
  104. package/src/components/global-styles/use-global-styles-output.js +4 -3
  105. package/src/components/grid/grid-item-movers.js +128 -0
  106. package/src/components/{grid-visualizer → grid}/grid-item-resizer.js +14 -52
  107. package/src/components/grid/grid-visualizer.js +267 -0
  108. package/src/components/grid/index.js +4 -0
  109. package/src/components/grid/style.scss +63 -0
  110. package/src/components/grid/use-get-number-of-blocks-before-cell.js +30 -0
  111. package/src/components/grid/use-grid-layout-sync.js +167 -0
  112. package/src/components/grid/utils.js +178 -0
  113. package/src/components/image-editor/aspect-ratio-dropdown.js +0 -1
  114. package/src/components/inner-blocks/index.js +3 -1
  115. package/src/components/rich-text/event-listeners/input-rules.js +1 -1
  116. package/src/components/rich-text/index.native.js +10 -8
  117. package/src/components/rich-text/native/index.native.js +17 -0
  118. package/src/hooks/block-style-variation.js +24 -6
  119. package/src/hooks/layout-child.js +34 -14
  120. package/src/hooks/utils.js +3 -1
  121. package/src/layouts/grid.js +54 -62
  122. package/src/lock-unlock.js +1 -1
  123. package/src/store/actions.js +21 -1
  124. package/src/style.scss +1 -1
  125. package/build/components/grid-visualizer/grid-item-resizer.js.map +0 -1
  126. package/build/components/grid-visualizer/grid-visualizer.js +0 -92
  127. package/build/components/grid-visualizer/grid-visualizer.js.map +0 -1
  128. package/build/components/grid-visualizer/index.js.map +0 -1
  129. package/build/components/grid-visualizer/utils.js +0 -10
  130. package/build/components/grid-visualizer/utils.js.map +0 -1
  131. package/build-module/components/grid-visualizer/grid-item-resizer.js.map +0 -1
  132. package/build-module/components/grid-visualizer/grid-visualizer.js +0 -84
  133. package/build-module/components/grid-visualizer/grid-visualizer.js.map +0 -1
  134. package/build-module/components/grid-visualizer/index.js +0 -3
  135. package/build-module/components/grid-visualizer/index.js.map +0 -1
  136. package/build-module/components/grid-visualizer/utils.js +0 -4
  137. package/build-module/components/grid-visualizer/utils.js.map +0 -1
  138. package/src/components/grid-visualizer/grid-visualizer.js +0 -101
  139. package/src/components/grid-visualizer/index.js +0 -2
  140. package/src/components/grid-visualizer/style.scss +0 -34
  141. package/src/components/grid-visualizer/utils.js +0 -5
  142. /package/src/components/font-sizes/{README.MD → README.md} +0 -0
@@ -0,0 +1,178 @@
1
+ export function range( start, length ) {
2
+ return Array.from( { length }, ( _, i ) => start + i );
3
+ }
4
+
5
+ export class GridRect {
6
+ constructor( {
7
+ columnStart,
8
+ rowStart,
9
+ columnEnd,
10
+ rowEnd,
11
+ columnSpan,
12
+ rowSpan,
13
+ } = {} ) {
14
+ this.columnStart = columnStart ?? 1;
15
+ this.rowStart = rowStart ?? 1;
16
+ if ( columnSpan !== undefined ) {
17
+ this.columnEnd = this.columnStart + columnSpan - 1;
18
+ } else {
19
+ this.columnEnd = columnEnd ?? this.columnStart;
20
+ }
21
+ if ( rowSpan !== undefined ) {
22
+ this.rowEnd = this.rowStart + rowSpan - 1;
23
+ } else {
24
+ this.rowEnd = rowEnd ?? this.rowStart;
25
+ }
26
+ }
27
+
28
+ get columnSpan() {
29
+ return this.columnEnd - this.columnStart + 1;
30
+ }
31
+
32
+ get rowSpan() {
33
+ return this.rowEnd - this.rowStart + 1;
34
+ }
35
+
36
+ contains( column, row ) {
37
+ return (
38
+ column >= this.columnStart &&
39
+ column <= this.columnEnd &&
40
+ row >= this.rowStart &&
41
+ row <= this.rowEnd
42
+ );
43
+ }
44
+
45
+ containsRect( rect ) {
46
+ return (
47
+ this.contains( rect.columnStart, rect.rowStart ) &&
48
+ this.contains( rect.columnEnd, rect.rowEnd )
49
+ );
50
+ }
51
+
52
+ intersectsRect( rect ) {
53
+ return (
54
+ this.columnStart <= rect.columnEnd &&
55
+ this.columnEnd >= rect.columnStart &&
56
+ this.rowStart <= rect.rowEnd &&
57
+ this.rowEnd >= rect.rowStart
58
+ );
59
+ }
60
+ }
61
+
62
+ export function getComputedCSS( element, property ) {
63
+ return element.ownerDocument.defaultView
64
+ .getComputedStyle( element )
65
+ .getPropertyValue( property );
66
+ }
67
+
68
+ /**
69
+ * Given a grid-template-columns or grid-template-rows CSS property value, gets the start and end
70
+ * position in pixels of each grid track.
71
+ *
72
+ * https://css-tricks.com/snippets/css/complete-guide-grid/#aa-grid-track
73
+ *
74
+ * @param {string} template The grid-template-columns or grid-template-rows CSS property value.
75
+ * Only supports fixed sizes in pixels.
76
+ * @param {number} gap The gap between grid tracks in pixels.
77
+ *
78
+ * @return {Array<{start: number, end: number}>} An array of objects with the start and end
79
+ * position in pixels of each grid track.
80
+ */
81
+ export function getGridTracks( template, gap ) {
82
+ const tracks = [];
83
+ for ( const size of template.split( ' ' ) ) {
84
+ const previousTrack = tracks[ tracks.length - 1 ];
85
+ const start = previousTrack ? previousTrack.end + gap : 0;
86
+ const end = start + parseFloat( size );
87
+ tracks.push( { start, end } );
88
+ }
89
+ return tracks;
90
+ }
91
+
92
+ /**
93
+ * Given an array of grid tracks and a position in pixels, gets the index of the closest track to
94
+ * that position.
95
+ *
96
+ * https://css-tricks.com/snippets/css/complete-guide-grid/#aa-grid-track
97
+ *
98
+ * @param {Array<{start: number, end: number}>} tracks An array of objects with the start and end
99
+ * position in pixels of each grid track.
100
+ * @param {number} position The position in pixels.
101
+ * @param {string} edge The edge of the track to compare the
102
+ * position to. Either 'start' or 'end'.
103
+ *
104
+ * @return {number} The index of the closest track to the position. 0-based, unlike CSS grid which
105
+ * is 1-based.
106
+ */
107
+ export function getClosestTrack( tracks, position, edge = 'start' ) {
108
+ return tracks.reduce(
109
+ ( closest, track, index ) =>
110
+ Math.abs( track[ edge ] - position ) <
111
+ Math.abs( tracks[ closest ][ edge ] - position )
112
+ ? index
113
+ : closest,
114
+ 0
115
+ );
116
+ }
117
+
118
+ export function getGridRect( gridElement, rect ) {
119
+ const columnGap = parseFloat( getComputedCSS( gridElement, 'column-gap' ) );
120
+ const rowGap = parseFloat( getComputedCSS( gridElement, 'row-gap' ) );
121
+ const gridColumnTracks = getGridTracks(
122
+ getComputedCSS( gridElement, 'grid-template-columns' ),
123
+ columnGap
124
+ );
125
+ const gridRowTracks = getGridTracks(
126
+ getComputedCSS( gridElement, 'grid-template-rows' ),
127
+ rowGap
128
+ );
129
+ const columnStart = getClosestTrack( gridColumnTracks, rect.left ) + 1;
130
+ const rowStart = getClosestTrack( gridRowTracks, rect.top ) + 1;
131
+ const columnEnd =
132
+ getClosestTrack( gridColumnTracks, rect.right, 'end' ) + 1;
133
+ const rowEnd = getClosestTrack( gridRowTracks, rect.bottom, 'end' ) + 1;
134
+ return new GridRect( {
135
+ columnStart,
136
+ columnEnd,
137
+ rowStart,
138
+ rowEnd,
139
+ } );
140
+ }
141
+
142
+ export function getGridItemRect( gridItemElement ) {
143
+ return getGridRect(
144
+ gridItemElement.parentElement,
145
+ new window.DOMRect(
146
+ gridItemElement.offsetLeft,
147
+ gridItemElement.offsetTop,
148
+ gridItemElement.offsetWidth,
149
+ gridItemElement.offsetHeight
150
+ )
151
+ );
152
+ }
153
+
154
+ export function getGridInfo( gridElement ) {
155
+ const gridTemplateColumns = getComputedCSS(
156
+ gridElement,
157
+ 'grid-template-columns'
158
+ );
159
+ const gridTemplateRows = getComputedCSS(
160
+ gridElement,
161
+ 'grid-template-rows'
162
+ );
163
+ const numColumns = gridTemplateColumns.split( ' ' ).length;
164
+ const numRows = gridTemplateRows.split( ' ' ).length;
165
+ const numItems = numColumns * numRows;
166
+ return {
167
+ numColumns,
168
+ numRows,
169
+ numItems,
170
+ currentColor: getComputedCSS( gridElement, 'color' ),
171
+ style: {
172
+ gridTemplateColumns,
173
+ gridTemplateRows,
174
+ gap: getComputedCSS( gridElement, 'gap' ),
175
+ padding: getComputedCSS( gridElement, 'padding' ),
176
+ },
177
+ };
178
+ }
@@ -78,7 +78,6 @@ export default function AspectRatioDropdown( { toggleProps } ) {
78
78
  label={ __( 'Aspect Ratio' ) }
79
79
  popoverProps={ POPOVER_PROPS }
80
80
  toggleProps={ toggleProps }
81
- className="wp-block-image__aspect-ratio"
82
81
  >
83
82
  { ( { onClose } ) => (
84
83
  <>
@@ -267,7 +267,9 @@ export function useInnerBlocksProps( props = {}, options = {} ) {
267
267
 
268
268
  const ref = useMergeRefs( [
269
269
  props.ref,
270
- __unstableDisableDropZone || isDropZoneDisabled
270
+ __unstableDisableDropZone ||
271
+ isDropZoneDisabled ||
272
+ ( layout?.columnCount && window.__experimentalEnableGridInteractivity )
271
273
  ? null
272
274
  : blockDropZoneRef,
273
275
  ] );
@@ -14,7 +14,7 @@ import {
14
14
  START_OF_SELECTED_AREA,
15
15
  } from '../../../utils/selection';
16
16
 
17
- function findSelection( blocks ) {
17
+ export function findSelection( blocks ) {
18
18
  let i = blocks.length;
19
19
 
20
20
  while ( i-- ) {
@@ -24,7 +24,6 @@ import {
24
24
  create,
25
25
  split,
26
26
  toHTMLString,
27
- slice,
28
27
  } from '@wordpress/rich-text';
29
28
  import { isURL } from '@wordpress/url';
30
29
 
@@ -46,6 +45,8 @@ import EmbedHandlerPicker from './embed-handler-picker';
46
45
  import { Content } from './content';
47
46
  import RichText from './native';
48
47
  import { withDeprecations } from './with-deprecations';
48
+ import { findSelection } from './event-listeners/input-rules';
49
+ import { START_OF_SELECTED_AREA } from '../../utils/selection';
49
50
 
50
51
  const classes = 'block-editor-rich-text__editable';
51
52
 
@@ -502,7 +503,7 @@ export function RichTextWrapper(
502
503
  );
503
504
 
504
505
  const inputRule = useCallback(
505
- ( value, valueToFormat ) => {
506
+ ( value ) => {
506
507
  if ( ! onReplace ) {
507
508
  return;
508
509
  }
@@ -518,7 +519,7 @@ export function RichTextWrapper(
518
519
  return;
519
520
  }
520
521
 
521
- const trimmedTextBefore = text.slice( 0, startPosition ).trim();
522
+ const trimmedTextBefore = text.slice( 0, start ).trim();
522
523
  const prefixTransforms = getBlockTransforms( 'from' ).filter(
523
524
  ( { type } ) => type === 'prefix'
524
525
  );
@@ -533,15 +534,16 @@ export function RichTextWrapper(
533
534
  return;
534
535
  }
535
536
 
536
- const content = valueToFormat(
537
- slice( value, startPosition, text.length )
538
- );
537
+ const content = toHTMLString( {
538
+ value: insert( value, START_OF_SELECTED_AREA, 0, start ),
539
+ } );
539
540
  const block = transformation.transform( content );
540
-
541
+ const currentSelection = findSelection( [ block ] );
541
542
  onReplace( [ block ] );
543
+ selectionChange( ...currentSelection );
542
544
  __unstableMarkAutomaticChange();
543
545
  },
544
- [ onReplace, __unstableMarkAutomaticChange ]
546
+ [ onReplace, start, selectionChange, __unstableMarkAutomaticChange ]
545
547
  );
546
548
 
547
549
  const mergedRef = useMergeRefs( [ providedRef, fallbackRef ] );
@@ -316,6 +316,23 @@ export class RichText extends Component {
316
316
  const contentWithoutRootTag = this.removeRootTagsProducedByAztec(
317
317
  event.nativeEvent.text
318
318
  );
319
+
320
+ const { __unstableInputRule } = this.props;
321
+ const currentValuePosition = {
322
+ end: this.isIOS ? this.selectionEnd : this.selectionEnd + 1,
323
+ start: this.isIOS ? this.selectionStart : this.selectionStart + 1,
324
+ };
325
+
326
+ if (
327
+ __unstableInputRule &&
328
+ __unstableInputRule( {
329
+ ...currentValuePosition,
330
+ ...this.formatToValue( contentWithoutRootTag ),
331
+ } )
332
+ ) {
333
+ return;
334
+ }
335
+
319
336
  // On iOS, onChange can be triggered after selection changes, even though there are no content changes.
320
337
  if ( contentWithoutRootTag === this.value?.toString() ) {
321
338
  return;
@@ -17,6 +17,23 @@ import { useStyleOverride } from './utils';
17
17
  import { store as blockEditorStore } from '../store';
18
18
  import { globalStylesDataKey } from '../store/private-keys';
19
19
 
20
+ const VARIATION_PREFIX = 'is-style-';
21
+
22
+ function getVariationMatches( className ) {
23
+ if ( ! className ) {
24
+ return [];
25
+ }
26
+ return className.split( /\s+/ ).reduce( ( matches, name ) => {
27
+ if ( name.startsWith( VARIATION_PREFIX ) ) {
28
+ const match = name.slice( VARIATION_PREFIX.length );
29
+ if ( match !== 'default' ) {
30
+ matches.push( match );
31
+ }
32
+ }
33
+ return matches;
34
+ }, [] );
35
+ }
36
+
20
37
  /**
21
38
  * Get the first block style variation that has been registered from the class string.
22
39
  *
@@ -28,14 +45,13 @@ import { globalStylesDataKey } from '../store/private-keys';
28
45
  function getVariationNameFromClass( className, registeredStyles = [] ) {
29
46
  // The global flag affects how capturing groups work in JS. So the regex
30
47
  // below will only return full CSS classes not just the variation name.
31
- const matches = className?.match( /\bis-style-(?!default)(\S+)\b/g );
48
+ const matches = getVariationMatches( className );
32
49
 
33
50
  if ( ! matches ) {
34
51
  return null;
35
52
  }
36
53
 
37
- for ( const variationClass of matches ) {
38
- const variation = variationClass.substring( 9 ); // Remove 'is-style-' prefix.
54
+ for ( const variation of matches ) {
39
55
  if ( registeredStyles.some( ( style ) => style.name === variation ) ) {
40
56
  return variation;
41
57
  }
@@ -94,7 +110,7 @@ function useBlockProps( { name, className, clientId } ) {
94
110
 
95
111
  const registeredStyles = getBlockStyles( name );
96
112
  const variation = getVariationNameFromClass( className, registeredStyles );
97
- const variationClass = `is-style-${ variation }-${ clientId }`;
113
+ const variationClass = `${ VARIATION_PREFIX }${ variation }-${ clientId }`;
98
114
 
99
115
  const { settings, styles } = useBlockStyleVariation(
100
116
  name,
@@ -116,7 +132,7 @@ function useBlockProps( { name, className, clientId } ) {
116
132
  const hasBlockGapSupport = false;
117
133
  const hasFallbackGapSupport = true;
118
134
  const disableLayoutStyles = true;
119
- const isTemplate = true;
135
+ const disableRootPadding = true;
120
136
 
121
137
  return toStyles(
122
138
  variationConfig,
@@ -124,7 +140,7 @@ function useBlockProps( { name, className, clientId } ) {
124
140
  hasBlockGapSupport,
125
141
  hasFallbackGapSupport,
126
142
  disableLayoutStyles,
127
- isTemplate,
143
+ disableRootPadding,
128
144
  {
129
145
  blockGap: false,
130
146
  blockStyles: true,
@@ -132,6 +148,7 @@ function useBlockProps( { name, className, clientId } ) {
132
148
  marginReset: false,
133
149
  presets: false,
134
150
  rootPadding: false,
151
+ variationStyles: true,
135
152
  }
136
153
  );
137
154
  }, [ variation, settings, styles, getBlockStyles, clientId ] );
@@ -152,5 +169,6 @@ function useBlockProps( { name, className, clientId } ) {
152
169
  export default {
153
170
  hasSupport: () => true,
154
171
  attributeKeys: [ 'className' ],
172
+ isMatch: ( { className } ) => getVariationMatches( className ).length > 0,
155
173
  useBlockProps,
156
174
  };
@@ -11,7 +11,11 @@ import { useState } from '@wordpress/element';
11
11
  import { store as blockEditorStore } from '../store';
12
12
  import { useStyleOverride } from './utils';
13
13
  import { useLayout } from '../components/block-list/layout';
14
- import { GridVisualizer, GridItemResizer } from '../components/grid-visualizer';
14
+ import {
15
+ GridVisualizer,
16
+ GridItemResizer,
17
+ GridItemMovers,
18
+ } from '../components/grid';
15
19
 
16
20
  function useBlockPropsChildLayoutStyles( { style } ) {
17
21
  const shouldRenderChildLayoutStyles = useSelect( ( select ) => {
@@ -135,10 +139,12 @@ function useBlockPropsChildLayoutStyles( { style } ) {
135
139
  }
136
140
 
137
141
  function ChildLayoutControlsPure( { clientId, style, setAttributes } ) {
142
+ const parentLayout = useLayout() || {};
138
143
  const {
139
144
  type: parentLayoutType = 'default',
140
145
  allowSizingOnChildren = false,
141
- } = useLayout() || {};
146
+ columnCount,
147
+ } = parentLayout;
142
148
 
143
149
  const rootClientId = useSelect(
144
150
  ( select ) => {
@@ -154,29 +160,43 @@ function ChildLayoutControlsPure( { clientId, style, setAttributes } ) {
154
160
  return null;
155
161
  }
156
162
 
163
+ const isManualGrid = !! columnCount;
164
+
165
+ function updateLayout( layout ) {
166
+ setAttributes( {
167
+ style: {
168
+ ...style,
169
+ layout: {
170
+ ...style?.layout,
171
+ ...layout,
172
+ },
173
+ },
174
+ } );
175
+ }
176
+
157
177
  return (
158
178
  <>
159
179
  <GridVisualizer
160
180
  clientId={ rootClientId }
161
181
  contentRef={ setResizerBounds }
182
+ parentLayout={ parentLayout }
162
183
  />
163
184
  { allowSizingOnChildren && (
164
185
  <GridItemResizer
165
186
  clientId={ clientId }
166
187
  // Don't allow resizing beyond the grid visualizer.
167
188
  bounds={ resizerBounds }
168
- onChange={ ( { columnSpan, rowSpan } ) => {
169
- setAttributes( {
170
- style: {
171
- ...style,
172
- layout: {
173
- ...style?.layout,
174
- columnSpan,
175
- rowSpan,
176
- },
177
- },
178
- } );
179
- } }
189
+ onChange={ updateLayout }
190
+ parentLayout={ parentLayout }
191
+ />
192
+ ) }
193
+ { isManualGrid && window.__experimentalEnableGridInteractivity && (
194
+ <GridItemMovers
195
+ layout={ style?.layout }
196
+ parentLayout={ parentLayout }
197
+ onChange={ updateLayout }
198
+ gridClientId={ rootClientId }
199
+ blockClientId={ clientId }
180
200
  />
181
201
  ) }
182
202
  </>
@@ -582,6 +582,7 @@ export function createBlockListBlockFilter( features ) {
582
582
  hasSupport,
583
583
  attributeKeys = [],
584
584
  useBlockProps,
585
+ isMatch,
585
586
  } = feature;
586
587
 
587
588
  const neededProps = {};
@@ -595,7 +596,8 @@ export function createBlockListBlockFilter( features ) {
595
596
  // Skip rendering if none of the needed attributes are
596
597
  // set.
597
598
  ! Object.keys( neededProps ).length ||
598
- ! hasSupport( props.name )
599
+ ! hasSupport( props.name ) ||
600
+ ( isMatch && ! isMatch( neededProps ) )
599
601
  ) {
600
602
  return null;
601
603
  }
@@ -23,7 +23,7 @@ import { appendSelectors, getBlockGapCSS } from './utils';
23
23
  import { getGapCSSValue } from '../hooks/gap';
24
24
  import { shouldSkipSerialization } from '../hooks/utils';
25
25
  import { LAYOUT_DEFINITIONS } from './definitions';
26
- import { GridVisualizer } from '../components/grid-visualizer';
26
+ import { GridVisualizer, useGridLayoutSync } from '../components/grid';
27
27
 
28
28
  const RANGE_CONTROL_MAX_VALUES = {
29
29
  px: 600,
@@ -93,7 +93,14 @@ export default {
93
93
  );
94
94
  },
95
95
  toolBarControls: function GridLayoutToolbarControls( { clientId } ) {
96
- return <GridVisualizer clientId={ clientId } />;
96
+ return (
97
+ <>
98
+ { window.__experimentalEnableGridInteractivity && (
99
+ <GridLayoutSync clientId={ clientId } />
100
+ ) }
101
+ <GridVisualizer clientId={ clientId } />
102
+ </>
103
+ );
97
104
  },
98
105
  getLayoutStyle: function getLayoutStyle( {
99
106
  selector,
@@ -245,9 +252,6 @@ function GridLayoutColumnsAndRowsControl( {
245
252
  return (
246
253
  <>
247
254
  <fieldset>
248
- <BaseControl.VisualLabel as="legend">
249
- { __( 'Columns' ) }
250
- </BaseControl.VisualLabel>
251
255
  <Flex gap={ 4 }>
252
256
  <FlexItem isBlock>
253
257
  <NumberControl
@@ -266,68 +270,43 @@ function GridLayoutColumnsAndRowsControl( {
266
270
  value={ columnCount }
267
271
  min={ 1 }
268
272
  label={ __( 'Columns' ) }
269
- hideLabelFromVision
270
273
  />
271
274
  </FlexItem>
275
+
272
276
  <FlexItem isBlock>
273
- <RangeControl
274
- value={ parseInt( columnCount, 10 ) } // RangeControl can't deal with strings.
275
- onChange={ ( value ) =>
276
- onChange( {
277
- ...layout,
278
- columnCount: value,
279
- } )
280
- }
281
- min={ 1 }
282
- max={ 16 }
283
- withInputField={ false }
284
- label={ __( 'Columns' ) }
285
- hideLabelFromVision
286
- />
277
+ { window.__experimentalEnableGridInteractivity &&
278
+ allowSizingOnChildren ? (
279
+ <NumberControl
280
+ size="__unstable-large"
281
+ onChange={ ( value ) => {
282
+ onChange( {
283
+ ...layout,
284
+ rowCount: value,
285
+ } );
286
+ } }
287
+ value={ rowCount }
288
+ min={ 1 }
289
+ label={ __( 'Rows' ) }
290
+ />
291
+ ) : (
292
+ <RangeControl
293
+ value={ parseInt( columnCount, 10 ) } // RangeControl can't deal with strings.
294
+ onChange={ ( value ) =>
295
+ onChange( {
296
+ ...layout,
297
+ columnCount: value,
298
+ } )
299
+ }
300
+ min={ 1 }
301
+ max={ 16 }
302
+ withInputField={ false }
303
+ label={ __( 'Columns' ) }
304
+ hideLabelFromVision
305
+ />
306
+ ) }
287
307
  </FlexItem>
288
308
  </Flex>
289
309
  </fieldset>
290
- { allowSizingOnChildren &&
291
- window.__experimentalEnableGridInteractivity && (
292
- <fieldset>
293
- <BaseControl.VisualLabel as="legend">
294
- { __( 'Rows' ) }
295
- </BaseControl.VisualLabel>
296
- <Flex gap={ 4 }>
297
- <FlexItem isBlock>
298
- <NumberControl
299
- size="__unstable-large"
300
- onChange={ ( value ) => {
301
- onChange( {
302
- ...layout,
303
- rowCount: value,
304
- } );
305
- } }
306
- value={ rowCount }
307
- min={ 1 }
308
- label={ __( 'Rows' ) }
309
- hideLabelFromVision
310
- />
311
- </FlexItem>
312
- <FlexItem isBlock>
313
- <RangeControl
314
- value={ parseInt( rowCount, 10 ) } // RangeControl can't deal with strings.
315
- onChange={ ( value ) =>
316
- onChange( {
317
- ...layout,
318
- rowCount: value,
319
- } )
320
- }
321
- min={ 1 }
322
- max={ 16 }
323
- withInputField={ false }
324
- label={ __( 'Rows' ) }
325
- hideLabelFromVision
326
- />
327
- </FlexItem>
328
- </Flex>
329
- </fieldset>
330
- ) }
331
310
  </>
332
311
  );
333
312
  }
@@ -366,10 +345,19 @@ function GridLayoutTypeControl( { layout, onChange } ) {
366
345
  return (
367
346
  <ToggleGroupControl
368
347
  __nextHasNoMarginBottom
369
- label={ __( 'Type' ) }
348
+ label={ __( 'Grid item position' ) }
370
349
  value={ isManual }
371
350
  onChange={ onChangeType }
372
351
  isBlock
352
+ help={
353
+ isManual === 'manual'
354
+ ? __(
355
+ 'Grid items can be manually placed in any position on the grid.'
356
+ )
357
+ : __(
358
+ 'Grid items are placed automatically depending on their order.'
359
+ )
360
+ }
373
361
  >
374
362
  <ToggleGroupControlOption
375
363
  key="auto"
@@ -384,3 +372,7 @@ function GridLayoutTypeControl( { layout, onChange } ) {
384
372
  </ToggleGroupControl>
385
373
  );
386
374
  }
375
+
376
+ function GridLayoutSync( props ) {
377
+ useGridLayoutSync( props );
378
+ }
@@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri
5
5
 
6
6
  export const { lock, unlock } =
7
7
  __dangerousOptInToUnstableAPIsOnlyForCoreModules(
8
- 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',
8
+ 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
9
9
  '@wordpress/block-editor'
10
10
  );
@@ -982,7 +982,7 @@ export const __unstableSplitSelection =
982
982
  },
983
983
  };
984
984
 
985
- const tail = {
985
+ let tail = {
986
986
  ...blockB,
987
987
  // Only preserve the original client ID if the end is different.
988
988
  clientId:
@@ -995,6 +995,26 @@ export const __unstableSplitSelection =
995
995
  },
996
996
  };
997
997
 
998
+ // When splitting a block, attempt to convert the tail block to the
999
+ // default block type. For example, when splitting a heading block, the
1000
+ // tail block will be converted to a paragraph block. Note that for
1001
+ // blocks such as a list item and button, this will be skipped because
1002
+ // the default block type cannot be inserted.
1003
+ const defaultBlockName = getDefaultBlockName();
1004
+ if (
1005
+ // A block is only split when the selection is within the same
1006
+ // block.
1007
+ blockA.clientId === blockB.clientId &&
1008
+ defaultBlockName &&
1009
+ tail.name !== defaultBlockName &&
1010
+ select.canInsertBlockType( defaultBlockName, anchorRootClientId )
1011
+ ) {
1012
+ const switched = switchToBlockType( tail, defaultBlockName );
1013
+ if ( switched?.length === 1 ) {
1014
+ tail = switched[ 0 ];
1015
+ }
1016
+ }
1017
+
998
1018
  if ( ! blocks.length ) {
999
1019
  dispatch.replaceBlocks( select.getSelectedBlockClientIds(), [
1000
1020
  head,
package/src/style.scss CHANGED
@@ -27,7 +27,7 @@
27
27
  @import "./components/duotone-control/style.scss";
28
28
  @import "./components/font-appearance-control/style.scss";
29
29
  @import "./components/global-styles/style.scss";
30
- @import "./components/grid-visualizer/style.scss";
30
+ @import "./components/grid/style.scss";
31
31
  @import "./components/height-control/style.scss";
32
32
  @import "./components/image-size-control/style.scss";
33
33
  @import "./components/inserter-list-item/style.scss";