@wordpress/block-editor 12.6.0 → 12.7.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 (199) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +2 -2
  3. package/build/autocompleters/block.js +6 -2
  4. package/build/autocompleters/block.js.map +1 -1
  5. package/build/components/block-editing-mode/index.js +1 -1
  6. package/build/components/block-editing-mode/index.js.map +1 -1
  7. package/build/components/block-list/block.js +4 -2
  8. package/build/components/block-list/block.js.map +1 -1
  9. package/build/components/block-list/index.js +2 -4
  10. package/build/components/block-list/index.js.map +1 -1
  11. package/build/components/block-parent-selector/index.js +6 -21
  12. package/build/components/block-parent-selector/index.js.map +1 -1
  13. package/build/components/block-preview/auto.js +6 -1
  14. package/build/components/block-preview/auto.js.map +1 -1
  15. package/build/components/block-settings-menu/block-settings-dropdown.js +3 -17
  16. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  17. package/build/components/block-toolbar/index.js +4 -34
  18. package/build/components/block-toolbar/index.js.map +1 -1
  19. package/build/components/block-toolbar/utils.js +56 -51
  20. package/build/components/block-toolbar/utils.js.map +1 -1
  21. package/build/components/block-tools/block-contextual-toolbar.js +4 -2
  22. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  23. package/build/components/block-variation-picker/index.native.js +10 -20
  24. package/build/components/block-variation-picker/index.native.js.map +1 -1
  25. package/build/components/editor-styles/index.js +2 -2
  26. package/build/components/editor-styles/index.js.map +1 -1
  27. package/build/components/font-sizes/fluid-utils.js +11 -11
  28. package/build/components/font-sizes/fluid-utils.js.map +1 -1
  29. package/build/components/global-styles/behaviors-panel.js +66 -0
  30. package/build/components/global-styles/behaviors-panel.js.map +1 -0
  31. package/build/components/global-styles/hooks.js +118 -4
  32. package/build/components/global-styles/hooks.js.map +1 -1
  33. package/build/components/global-styles/index.js +20 -0
  34. package/build/components/global-styles/index.js.map +1 -1
  35. package/build/components/global-styles/typography-utils.js +4 -4
  36. package/build/components/global-styles/typography-utils.js.map +1 -1
  37. package/build/components/global-styles/utils.js +1 -1
  38. package/build/components/global-styles/utils.js.map +1 -1
  39. package/build/components/inserter/hooks/use-block-types-state.js +6 -2
  40. package/build/components/inserter/hooks/use-block-types-state.js.map +1 -1
  41. package/build/components/inserter/hooks/use-debounced-input.js +5 -7
  42. package/build/components/inserter/hooks/use-debounced-input.js.map +1 -1
  43. package/build/components/inserter/hooks/use-patterns-state.js +3 -2
  44. package/build/components/inserter/hooks/use-patterns-state.js.map +1 -1
  45. package/build/components/inserter/reusable-blocks-tab.js +3 -2
  46. package/build/components/inserter/reusable-blocks-tab.js.map +1 -1
  47. package/build/components/inserter-list-item/index.js +1 -1
  48. package/build/components/inserter-list-item/index.js.map +1 -1
  49. package/build/components/link-control/index.js +47 -6
  50. package/build/components/link-control/index.js.map +1 -1
  51. package/build/components/link-control/link-preview.js +3 -3
  52. package/build/components/link-control/link-preview.js.map +1 -1
  53. package/build/components/list-view/use-list-view-drop-zone.js +6 -1
  54. package/build/components/list-view/use-list-view-drop-zone.js.map +1 -1
  55. package/build/components/media-replace-flow/index.native.js +15 -3
  56. package/build/components/media-replace-flow/index.native.js.map +1 -1
  57. package/build/components/rich-text/format-edit.js +57 -28
  58. package/build/components/rich-text/format-edit.js.map +1 -1
  59. package/build/components/rich-text/get-rich-text-values.js +11 -18
  60. package/build/components/rich-text/get-rich-text-values.js.map +1 -1
  61. package/build/components/spacing-sizes-control/utils.js +2 -2
  62. package/build/components/spacing-sizes-control/utils.js.map +1 -1
  63. package/build/hooks/behaviors.js +5 -12
  64. package/build/hooks/behaviors.js.map +1 -1
  65. package/build/hooks/border.js +2 -1
  66. package/build/hooks/border.js.map +1 -1
  67. package/build/hooks/style.js +11 -2
  68. package/build/hooks/style.js.map +1 -1
  69. package/build/private-apis.js +4 -1
  70. package/build/private-apis.js.map +1 -1
  71. package/build/store/actions.js +2 -3
  72. package/build/store/actions.js.map +1 -1
  73. package/build/store/selectors.js +4 -71
  74. package/build/store/selectors.js.map +1 -1
  75. package/build-module/autocompleters/block.js +7 -3
  76. package/build-module/autocompleters/block.js.map +1 -1
  77. package/build-module/components/block-editing-mode/index.js +1 -1
  78. package/build-module/components/block-editing-mode/index.js.map +1 -1
  79. package/build-module/components/block-list/block.js +4 -2
  80. package/build-module/components/block-list/block.js.map +1 -1
  81. package/build-module/components/block-list/index.js +2 -3
  82. package/build-module/components/block-list/index.js.map +1 -1
  83. package/build-module/components/block-parent-selector/index.js +7 -22
  84. package/build-module/components/block-parent-selector/index.js.map +1 -1
  85. package/build-module/components/block-preview/auto.js +6 -1
  86. package/build-module/components/block-preview/auto.js.map +1 -1
  87. package/build-module/components/block-settings-menu/block-settings-dropdown.js +4 -18
  88. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  89. package/build-module/components/block-toolbar/index.js +6 -36
  90. package/build-module/components/block-toolbar/index.js.map +1 -1
  91. package/build-module/components/block-toolbar/utils.js +54 -49
  92. package/build-module/components/block-toolbar/utils.js.map +1 -1
  93. package/build-module/components/block-tools/block-contextual-toolbar.js +4 -2
  94. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  95. package/build-module/components/block-variation-picker/index.native.js +13 -23
  96. package/build-module/components/block-variation-picker/index.native.js.map +1 -1
  97. package/build-module/components/editor-styles/index.js +2 -2
  98. package/build-module/components/editor-styles/index.js.map +1 -1
  99. package/build-module/components/font-sizes/fluid-utils.js +11 -11
  100. package/build-module/components/font-sizes/fluid-utils.js.map +1 -1
  101. package/build-module/components/global-styles/behaviors-panel.js +57 -0
  102. package/build-module/components/global-styles/behaviors-panel.js.map +1 -0
  103. package/build-module/components/global-styles/hooks.js +115 -5
  104. package/build-module/components/global-styles/hooks.js.map +1 -1
  105. package/build-module/components/global-styles/index.js +2 -1
  106. package/build-module/components/global-styles/index.js.map +1 -1
  107. package/build-module/components/global-styles/typography-utils.js +4 -4
  108. package/build-module/components/global-styles/typography-utils.js.map +1 -1
  109. package/build-module/components/global-styles/utils.js +1 -1
  110. package/build-module/components/global-styles/utils.js.map +1 -1
  111. package/build-module/components/inserter/hooks/use-block-types-state.js +7 -3
  112. package/build-module/components/inserter/hooks/use-block-types-state.js.map +1 -1
  113. package/build-module/components/inserter/hooks/use-debounced-input.js +5 -7
  114. package/build-module/components/inserter/hooks/use-debounced-input.js.map +1 -1
  115. package/build-module/components/inserter/hooks/use-patterns-state.js +3 -2
  116. package/build-module/components/inserter/hooks/use-patterns-state.js.map +1 -1
  117. package/build-module/components/inserter/reusable-blocks-tab.js +3 -2
  118. package/build-module/components/inserter/reusable-blocks-tab.js.map +1 -1
  119. package/build-module/components/inserter-list-item/index.js +1 -1
  120. package/build-module/components/inserter-list-item/index.js.map +1 -1
  121. package/build-module/components/link-control/index.js +45 -6
  122. package/build-module/components/link-control/index.js.map +1 -1
  123. package/build-module/components/link-control/link-preview.js +3 -3
  124. package/build-module/components/link-control/link-preview.js.map +1 -1
  125. package/build-module/components/list-view/use-list-view-drop-zone.js +6 -1
  126. package/build-module/components/list-view/use-list-view-drop-zone.js.map +1 -1
  127. package/build-module/components/media-replace-flow/index.native.js +15 -3
  128. package/build-module/components/media-replace-flow/index.native.js.map +1 -1
  129. package/build-module/components/rich-text/format-edit.js +51 -26
  130. package/build-module/components/rich-text/format-edit.js.map +1 -1
  131. package/build-module/components/rich-text/get-rich-text-values.js +13 -18
  132. package/build-module/components/rich-text/get-rich-text-values.js.map +1 -1
  133. package/build-module/components/spacing-sizes-control/utils.js +2 -2
  134. package/build-module/components/spacing-sizes-control/utils.js.map +1 -1
  135. package/build-module/hooks/behaviors.js +5 -12
  136. package/build-module/hooks/behaviors.js.map +1 -1
  137. package/build-module/hooks/border.js +2 -1
  138. package/build-module/hooks/border.js.map +1 -1
  139. package/build-module/hooks/style.js +11 -2
  140. package/build-module/hooks/style.js.map +1 -1
  141. package/build-module/private-apis.js +3 -1
  142. package/build-module/private-apis.js.map +1 -1
  143. package/build-module/store/actions.js +2 -3
  144. package/build-module/store/actions.js.map +1 -1
  145. package/build-module/store/selectors.js +4 -69
  146. package/build-module/store/selectors.js.map +1 -1
  147. package/build-style/style-rtl.css +18 -5
  148. package/build-style/style.css +18 -5
  149. package/package.json +31 -31
  150. package/src/autocompleters/block.js +21 -6
  151. package/src/components/block-draggable/test/index.native.js +2 -3
  152. package/src/components/block-editing-mode/index.js +1 -1
  153. package/src/components/block-list/block.js +6 -1
  154. package/src/components/block-list/index.js +3 -6
  155. package/src/components/block-list/test/block-invalid-warning.native.js +8 -1
  156. package/src/components/block-mover/test/__snapshots__/index.native.js.snap +24 -0
  157. package/src/components/block-parent-selector/index.js +30 -42
  158. package/src/components/block-preview/auto.js +8 -1
  159. package/src/components/block-preview/style.scss +2 -1
  160. package/src/components/block-settings-menu/block-settings-dropdown.js +4 -13
  161. package/src/components/block-toolbar/index.js +36 -63
  162. package/src/components/block-toolbar/utils.js +57 -45
  163. package/src/components/block-tools/block-contextual-toolbar.js +43 -35
  164. package/src/components/block-tools/style.scss +17 -5
  165. package/src/components/block-variation-picker/index.native.js +52 -72
  166. package/src/components/color-palette/test/__snapshots__/control.js.snap +1 -1
  167. package/src/components/editor-styles/index.js +2 -2
  168. package/src/components/font-sizes/fluid-utils.js +17 -17
  169. package/src/components/font-sizes/test/fluid-utils.js +6 -6
  170. package/src/components/global-styles/behaviors-panel.js +71 -0
  171. package/src/components/global-styles/hooks.js +114 -5
  172. package/src/components/global-styles/index.js +3 -0
  173. package/src/components/global-styles/test/typography-utils.js +6 -6
  174. package/src/components/global-styles/typography-utils.js +4 -4
  175. package/src/components/global-styles/utils.js +2 -1
  176. package/src/components/inserter/hooks/use-block-types-state.js +15 -6
  177. package/src/components/inserter/hooks/use-debounced-input.js +8 -7
  178. package/src/components/inserter/hooks/use-patterns-state.js +2 -1
  179. package/src/components/inserter/reusable-blocks-tab.js +4 -1
  180. package/src/components/inserter-list-item/index.js +3 -1
  181. package/src/components/link-control/README.md +12 -3
  182. package/src/components/link-control/index.js +43 -6
  183. package/src/components/link-control/link-preview.js +6 -4
  184. package/src/components/link-control/style.scss +3 -2
  185. package/src/components/link-control/test/index.js +2 -1
  186. package/src/components/list-view/use-list-view-drop-zone.js +5 -1
  187. package/src/components/media-replace-flow/index.native.js +12 -3
  188. package/src/components/media-upload/test/index.native.js +1 -0
  189. package/src/components/rich-text/format-edit.js +62 -38
  190. package/src/components/rich-text/get-rich-text-values.js +22 -28
  191. package/src/components/spacing-sizes-control/test/utils.js +9 -1
  192. package/src/components/spacing-sizes-control/utils.js +2 -2
  193. package/src/hooks/behaviors.js +10 -16
  194. package/src/hooks/border.js +2 -1
  195. package/src/hooks/style.js +7 -3
  196. package/src/private-apis.js +2 -0
  197. package/src/store/actions.js +22 -28
  198. package/src/store/selectors.js +3 -80
  199. package/src/store/test/selectors.js +7 -6
@@ -32,8 +32,8 @@ const DEFAULT_MINIMUM_FONT_SIZE_LIMIT = '14px';
32
32
  * ```
33
33
  *
34
34
  * @param {Object} args
35
- * @param {?string} args.minimumViewPortWidth Minimum viewport size from which type will have fluidity. Optional if fontSize is specified.
36
- * @param {?string} args.maximumViewPortWidth Maximum size up to which type will have fluidity. Optional if fontSize is specified.
35
+ * @param {?string} args.minimumViewportWidth Minimum viewport size from which type will have fluidity. Optional if fontSize is specified.
36
+ * @param {?string} args.maximumViewportWidth Maximum size up to which type will have fluidity. Optional if fontSize is specified.
37
37
  * @param {string|number} [args.fontSize] Size to derive maximumFontSize and minimumFontSize from, if necessary. Optional if minimumFontSize and maximumFontSize are specified.
38
38
  * @param {?string} args.maximumFontSize Maximum font size for any clamp() calculation. Optional.
39
39
  * @param {?string} args.minimumFontSize Minimum font size for any clamp() calculation. Optional.
@@ -46,8 +46,8 @@ export function getComputedFluidTypographyValue( {
46
46
  minimumFontSize,
47
47
  maximumFontSize,
48
48
  fontSize,
49
- minimumViewPortWidth = DEFAULT_MINIMUM_VIEWPORT_WIDTH,
50
- maximumViewPortWidth = DEFAULT_MAXIMUM_VIEWPORT_WIDTH,
49
+ minimumViewportWidth = DEFAULT_MINIMUM_VIEWPORT_WIDTH,
50
+ maximumViewportWidth = DEFAULT_MAXIMUM_VIEWPORT_WIDTH,
51
51
  scaleFactor = DEFAULT_SCALE_FACTOR,
52
52
  minimumFontSizeLimit,
53
53
  } ) {
@@ -163,19 +163,19 @@ export function getComputedFluidTypographyValue( {
163
163
  } );
164
164
 
165
165
  // Viewport widths defined for fluid typography. Normalize units
166
- const maximumViewPortWidthParsed = getTypographyValueAndUnit(
167
- maximumViewPortWidth,
166
+ const maximumViewportWidthParsed = getTypographyValueAndUnit(
167
+ maximumViewportWidth,
168
168
  { coerceTo: fontSizeUnit }
169
169
  );
170
- const minumumViewPortWidthParsed = getTypographyValueAndUnit(
171
- minimumViewPortWidth,
170
+ const minimumViewportWidthParsed = getTypographyValueAndUnit(
171
+ minimumViewportWidth,
172
172
  { coerceTo: fontSizeUnit }
173
173
  );
174
174
 
175
175
  // Protect against unsupported units.
176
176
  if (
177
- ! maximumViewPortWidthParsed ||
178
- ! minumumViewPortWidthParsed ||
177
+ ! maximumViewportWidthParsed ||
178
+ ! minimumViewportWidthParsed ||
179
179
  ! minimumFontSizeRem
180
180
  ) {
181
181
  return null;
@@ -183,23 +183,23 @@ export function getComputedFluidTypographyValue( {
183
183
 
184
184
  // Build CSS rule.
185
185
  // Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
186
- const minViewPortWidthOffsetValue = roundToPrecision(
187
- minumumViewPortWidthParsed.value / 100,
186
+ const minViewportWidthOffsetValue = roundToPrecision(
187
+ minimumViewportWidthParsed.value / 100,
188
188
  3
189
189
  );
190
190
 
191
- const viewPortWidthOffset =
192
- roundToPrecision( minViewPortWidthOffsetValue, 3 ) + fontSizeUnit;
191
+ const viewportWidthOffset =
192
+ roundToPrecision( minViewportWidthOffsetValue, 3 ) + fontSizeUnit;
193
193
  const linearFactor =
194
194
  100 *
195
195
  ( ( maximumFontSizeParsed.value - minimumFontSizeParsed.value ) /
196
- ( maximumViewPortWidthParsed.value -
197
- minumumViewPortWidthParsed.value ) );
196
+ ( maximumViewportWidthParsed.value -
197
+ minimumViewportWidthParsed.value ) );
198
198
  const linearFactorScaled = roundToPrecision(
199
199
  ( linearFactor || 1 ) * scaleFactor,
200
200
  3
201
201
  );
202
- const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewPortWidthOffset }) * ${ linearFactorScaled })`;
202
+ const fluidTargetFontSize = `${ minimumFontSizeRem.value }${ minimumFontSizeRem.unit } + ((1vw - ${ viewportWidthOffset }) * ${ linearFactorScaled })`;
203
203
 
204
204
  return `clamp(${ minimumFontSize }, ${ fluidTargetFontSize }, ${ maximumFontSize })`;
205
205
  }
@@ -56,8 +56,8 @@ describe( 'getComputedFluidTypographyValue()', () => {
56
56
  it( 'should return a fluid font size when given a min and max viewport width', () => {
57
57
  const fluidTypographyValues = getComputedFluidTypographyValue( {
58
58
  fontSize: '30px',
59
- minimumViewPortWidth: '500px',
60
- maximumViewPortWidth: '1000px',
59
+ minimumViewportWidth: '500px',
60
+ maximumViewportWidth: '1000px',
61
61
  } );
62
62
  expect( fluidTypographyValues ).toBe(
63
63
  'clamp(18.959px, 1.185rem + ((1vw - 5px) * 2.208), 30px)'
@@ -74,18 +74,18 @@ describe( 'getComputedFluidTypographyValue()', () => {
74
74
  );
75
75
  } );
76
76
 
77
- it( 'should return null when maximumViewPortWidth is not a supported value or unit', () => {
77
+ it( 'should return null when maximumViewportWidth is not a supported value or unit', () => {
78
78
  const fluidTypographyValues = getComputedFluidTypographyValue( {
79
79
  fontSize: '30px',
80
- maximumViewPortWidth: 'min(calc(100% - 60px), 1200px)',
80
+ maximumViewportWidth: 'min(calc(100% - 60px), 1200px)',
81
81
  } );
82
82
  expect( fluidTypographyValues ).toBeNull();
83
83
  } );
84
84
 
85
- it( 'should return `null` font size when minimumViewPortWidth is not a supported value or unit', () => {
85
+ it( 'should return `null` font size when minimumViewportWidth is not a supported value or unit', () => {
86
86
  const fluidTypographyValues = getComputedFluidTypographyValue( {
87
87
  fontSize: '33px',
88
- minimumViewPortWidth: 'calc(100% - 60px)',
88
+ minimumViewportWidth: 'calc(100% - 60px)',
89
89
  } );
90
90
  expect( fluidTypographyValues ).toBeNull();
91
91
  } );
@@ -0,0 +1,71 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { SelectControl } from '@wordpress/components';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ export default function ( { onChange, value, behaviors } ) {
8
+ const defaultBehaviors = {
9
+ default: {
10
+ value: 'default',
11
+ label: __( 'Default' ),
12
+ },
13
+ noBehaviors: {
14
+ value: '',
15
+ label: __( 'No behaviors' ),
16
+ },
17
+ };
18
+
19
+ const behaviorsOptions = Object.entries( behaviors ).map(
20
+ ( [ behaviorName ] ) => ( {
21
+ value: behaviorName,
22
+ // Capitalize the first letter of the behavior name.
23
+ label: `${ behaviorName.charAt( 0 ).toUpperCase() }${ behaviorName
24
+ .slice( 1 )
25
+ .toLowerCase() }`,
26
+ } )
27
+ );
28
+
29
+ const options = [
30
+ ...Object.values( defaultBehaviors ),
31
+ ...behaviorsOptions,
32
+ ];
33
+
34
+ const animations = [
35
+ {
36
+ value: 'zoom',
37
+ label: __( 'Zoom' ),
38
+ },
39
+ {
40
+ value: 'fade',
41
+ label: __( 'Fade' ),
42
+ },
43
+ ];
44
+ return (
45
+ <div style={ { marginTop: '2rem' } }>
46
+ <SelectControl
47
+ label={ __( 'Behaviors' ) }
48
+ // At the moment we are only supporting one behavior (Lightbox)
49
+ value={ value }
50
+ options={ options }
51
+ onChange={ onChange }
52
+ hideCancelButton={ true }
53
+ size="__unstable-large"
54
+ />
55
+ { value === 'lightbox' && (
56
+ <SelectControl
57
+ label={ __( 'Animation' ) }
58
+ value={
59
+ behaviors?.lightbox.animation
60
+ ? behaviors?.lightbox.animation
61
+ : ''
62
+ }
63
+ options={ animations }
64
+ onChange={ onChange }
65
+ hideCancelButton={ false }
66
+ size="__unstable-large"
67
+ />
68
+ ) }
69
+ </div>
70
+ );
71
+ }
@@ -8,7 +8,7 @@ import fastDeepEqual from 'fast-deep-equal/es6';
8
8
  */
9
9
  import { useContext, useCallback, useMemo } from '@wordpress/element';
10
10
  import { useSelect } from '@wordpress/data';
11
- import { store as blocksStore } from '@wordpress/blocks';
11
+ import { store as blocksStore, hasBlockSupport } from '@wordpress/blocks';
12
12
  import { _x } from '@wordpress/i18n';
13
13
 
14
14
  /**
@@ -19,10 +19,11 @@ import { getValueFromObjectPath, setImmutably } from '../../utils/object';
19
19
  import { GlobalStylesContext } from './context';
20
20
  import { unlock } from '../../lock-unlock';
21
21
 
22
- const EMPTY_CONFIG = { settings: {}, styles: {} };
22
+ const EMPTY_CONFIG = { settings: {}, styles: {}, behaviors: {} };
23
23
 
24
24
  const VALID_SETTINGS = [
25
25
  'appearanceTools',
26
+ 'behaviors',
26
27
  'useRootPaddingAwareAlignments',
27
28
  'border.color',
28
29
  'border.radius',
@@ -88,7 +89,6 @@ export const useGlobalStylesReset = () => {
88
89
 
89
90
  export function useGlobalSetting( propertyPath, blockName, source = 'all' ) {
90
91
  const { setUserConfig, ...configs } = useContext( GlobalStylesContext );
91
-
92
92
  const appendedBlockPath = blockName ? '.blocks.' + blockName : '';
93
93
  const appendedPropertyPath = propertyPath ? '.' + propertyPath : '';
94
94
  const contextualPath = `settings${ appendedBlockPath }${ appendedPropertyPath }`;
@@ -135,7 +135,6 @@ export function useGlobalSetting( propertyPath, blockName, source = 'all' ) {
135
135
  setImmutably( currentConfig, contextualPath.split( '.' ), newValue )
136
136
  );
137
137
  };
138
-
139
138
  return [ settingValue, setSetting ];
140
139
  }
141
140
 
@@ -327,7 +326,8 @@ export function useSettingsForBlockElement(
327
326
  const sides = Array.isArray( supports?.spacing?.[ key ] )
328
327
  ? supports?.spacing?.[ key ]
329
328
  : supports?.spacing?.[ key ]?.sides;
330
- if ( sides?.length ) {
329
+ // Check if spacing type is supported before adding sides.
330
+ if ( sides?.length && updatedSettings.spacing?.[ key ] ) {
331
331
  updatedSettings.spacing = {
332
332
  ...updatedSettings.spacing,
333
333
  [ key ]: {
@@ -461,3 +461,112 @@ export function useGradientsPerOrigin( settings ) {
461
461
  shouldDisplayDefaultGradients,
462
462
  ] );
463
463
  }
464
+
465
+ export function __experimentalUseGlobalBehaviors( blockName, source = 'all' ) {
466
+ const {
467
+ merged: mergedConfig,
468
+ base: baseConfig,
469
+ user: userConfig,
470
+ setUserConfig,
471
+ } = useContext( GlobalStylesContext );
472
+ const finalPath = ! blockName
473
+ ? `behaviors`
474
+ : `behaviors.blocks.${ blockName }`;
475
+
476
+ let rawResult, result;
477
+ switch ( source ) {
478
+ case 'all':
479
+ rawResult = getValueFromObjectPath( mergedConfig, finalPath );
480
+ result = getValueFromVariable( mergedConfig, blockName, rawResult );
481
+ break;
482
+ case 'user':
483
+ rawResult = getValueFromObjectPath( userConfig, finalPath );
484
+ result = getValueFromVariable( mergedConfig, blockName, rawResult );
485
+ break;
486
+ case 'base':
487
+ rawResult = getValueFromObjectPath( baseConfig, finalPath );
488
+ result = getValueFromVariable( baseConfig, blockName, rawResult );
489
+ break;
490
+ default:
491
+ throw 'Unsupported source';
492
+ }
493
+
494
+ const animation = result?.lightbox?.animation || 'zoom';
495
+
496
+ const setBehavior = ( newValue ) => {
497
+ let newBehavior;
498
+ // The user saves with Apply Globally option.
499
+ if ( typeof newValue === 'object' ) {
500
+ newBehavior = newValue;
501
+ } else {
502
+ switch ( newValue ) {
503
+ case 'lightbox':
504
+ newBehavior = {
505
+ lightbox: {
506
+ enabled: true,
507
+ animation,
508
+ },
509
+ };
510
+ break;
511
+ case 'fade':
512
+ newBehavior = {
513
+ lightbox: {
514
+ enabled: true,
515
+ animation: 'fade',
516
+ },
517
+ };
518
+ break;
519
+ case 'zoom':
520
+ newBehavior = {
521
+ lightbox: {
522
+ enabled: true,
523
+ animation: 'zoom',
524
+ },
525
+ };
526
+ break;
527
+ case '':
528
+ newBehavior = {
529
+ lightbox: {
530
+ enabled: false,
531
+ animation,
532
+ },
533
+ };
534
+ break;
535
+ default:
536
+ break;
537
+ }
538
+ }
539
+ setUserConfig( ( currentConfig ) =>
540
+ setImmutably( currentConfig, finalPath.split( '.' ), newBehavior )
541
+ );
542
+ };
543
+ let behavior = '';
544
+ if ( result === undefined ) behavior = 'default';
545
+ if ( result?.lightbox.enabled ) behavior = 'lightbox';
546
+
547
+ return { behavior, inheritedBehaviors: result, setBehavior };
548
+ }
549
+
550
+ export function __experimentalUseHasBehaviorsPanel(
551
+ settings,
552
+ name,
553
+ { blockSupportOnly = false } = {}
554
+ ) {
555
+ if ( ! settings?.behaviors ) {
556
+ return false;
557
+ }
558
+
559
+ // If every behavior is disabled on block supports, do not show the behaviors inspector control.
560
+ const hasSomeBlockSupport = Object.keys( settings?.behaviors ).some(
561
+ ( key ) => hasBlockSupport( name, `behaviors.${ key }` )
562
+ );
563
+
564
+ if ( blockSupportOnly ) {
565
+ return hasSomeBlockSupport;
566
+ }
567
+
568
+ // If every behavior is disabled, do not show the behaviors inspector control.
569
+ return Object.values( settings?.behaviors ).some(
570
+ ( value ) => value === true && hasSomeBlockSupport
571
+ );
572
+ }
@@ -1,4 +1,6 @@
1
1
  export {
2
+ __experimentalUseGlobalBehaviors,
3
+ __experimentalUseHasBehaviorsPanel,
2
4
  useGlobalStylesReset,
3
5
  useGlobalSetting,
4
6
  useGlobalStyle,
@@ -23,5 +25,6 @@ export { default as BorderPanel, useHasBorderPanel } from './border-panel';
23
25
  export { default as ColorPanel, useHasColorPanel } from './color-panel';
24
26
  export { default as EffectsPanel, useHasEffectsPanel } from './effects-panel';
25
27
  export { default as FiltersPanel, useHasFiltersPanel } from './filters-panel';
28
+ export { default as __experimentalBehaviorsPanel } from './behaviors-panel';
26
29
  export { default as AdvancedPanel } from './advanced-panel';
27
30
  export { areGlobalStyleConfigsEqual } from './utils';
@@ -192,7 +192,7 @@ describe( 'typography utils', () => {
192
192
 
193
193
  {
194
194
  message:
195
- 'should apply maxViewPortWidth as maximum viewport width',
195
+ 'should apply maxViewportWidth as maximum viewport width',
196
196
  preset: {
197
197
  size: '80px',
198
198
  fluid: {
@@ -202,7 +202,7 @@ describe( 'typography utils', () => {
202
202
  },
203
203
  typographySettings: {
204
204
  fluid: {
205
- maxViewPortWidth: '1100px',
205
+ maxViewportWidth: '1100px',
206
206
  },
207
207
  },
208
208
  expected:
@@ -548,18 +548,18 @@ describe( 'typography utils', () => {
548
548
  layout: { wideSize: '1000rem' },
549
549
  },
550
550
  expected: {
551
- fluid: { maxViewPortWidth: '1000rem', minFontSize: '16px' },
551
+ fluid: { maxViewportWidth: '1000rem', minFontSize: '16px' },
552
552
  },
553
553
  },
554
554
 
555
555
  {
556
556
  message:
557
- 'should prioritize fluid `maxViewPortWidth` over `layout.wideSize`',
557
+ 'should prioritize fluid `maxViewportWidth` over `layout.wideSize`',
558
558
  settings: {
559
- typography: { fluid: { maxViewPortWidth: '10px' } },
559
+ typography: { fluid: { maxViewportWidth: '10px' } },
560
560
  layout: { wideSize: '1000rem' },
561
561
  },
562
- expected: { fluid: { maxViewPortWidth: '10px' } },
562
+ expected: { fluid: { maxViewportWidth: '10px' } },
563
563
  },
564
564
  ].forEach( ( { message, settings, expected } ) => {
565
565
  it( `${ message }`, () => {
@@ -25,8 +25,8 @@ import { getComputedFluidTypographyValue } from '../font-sizes/fluid-utils';
25
25
 
26
26
  /**
27
27
  * @typedef {Object} TypographySettings
28
- * @property {?string} minViewPortWidth Minimum viewport size from which type will have fluidity. Optional if size is specified.
29
- * @property {?string} maxViewPortWidth Maximum size up to which type will have fluidity. Optional if size is specified.
28
+ * @property {?string} minViewportWidth Minimum viewport size from which type will have fluidity. Optional if size is specified.
29
+ * @property {?string} maxViewportWidth Maximum size up to which type will have fluidity. Optional if size is specified.
30
30
  * @property {?number} scaleFactor A scale factor to determine how fast a font scales within boundaries. Optional.
31
31
  * @property {?number} minFontSizeFactor How much to scale defaultFontSize by to derive minimumFontSize. Optional.
32
32
  * @property {?string} minFontSize The smallest a calculated font size may be. Optional.
@@ -67,7 +67,7 @@ export function getTypographyFontSizeValue( preset, typographyOptions ) {
67
67
  maximumFontSize: preset?.fluid?.max,
68
68
  fontSize: defaultSize,
69
69
  minimumFontSizeLimit: fluidTypographySettings?.minFontSize,
70
- maximumViewPortWidth: fluidTypographySettings?.maxViewPortWidth,
70
+ maximumViewportWidth: fluidTypographySettings?.maxViewportWidth,
71
71
  } );
72
72
 
73
73
  if ( !! fluidFontSizeValue ) {
@@ -102,7 +102,7 @@ export function getFluidTypographyOptionsFromSettings( settings ) {
102
102
  layoutSettings?.wideSize
103
103
  ? {
104
104
  fluid: {
105
- maxViewPortWidth: layoutSettings.wideSize,
105
+ maxViewportWidth: layoutSettings.wideSize,
106
106
  ...typographySettings.fluid,
107
107
  },
108
108
  }
@@ -415,6 +415,7 @@ export function areGlobalStyleConfigsEqual( original, variation ) {
415
415
  }
416
416
  return (
417
417
  fastDeepEqual( original?.styles, variation?.styles ) &&
418
- fastDeepEqual( original?.settings, variation?.settings )
418
+ fastDeepEqual( original?.settings, variation?.settings ) &&
419
+ fastDeepEqual( original?.behaviors, variation?.behaviors )
419
420
  );
420
421
  }
@@ -5,6 +5,7 @@ import {
5
5
  createBlock,
6
6
  createBlocksFromInnerBlocksTemplate,
7
7
  store as blocksStore,
8
+ parse,
8
9
  } from '@wordpress/blocks';
9
10
  import { useSelect } from '@wordpress/data';
10
11
  import { useCallback } from '@wordpress/element';
@@ -37,12 +38,20 @@ const useBlockTypesState = ( rootClientId, onInsert ) => {
37
38
  );
38
39
 
39
40
  const onSelectItem = useCallback(
40
- ( { name, initialAttributes, innerBlocks }, shouldFocusBlock ) => {
41
- const insertedBlock = createBlock(
42
- name,
43
- initialAttributes,
44
- createBlocksFromInnerBlocksTemplate( innerBlocks )
45
- );
41
+ (
42
+ { name, initialAttributes, innerBlocks, syncStatus, content },
43
+ shouldFocusBlock
44
+ ) => {
45
+ const insertedBlock =
46
+ syncStatus === 'unsynced'
47
+ ? parse( content, {
48
+ __unstableSkipMigrationLogs: true,
49
+ } )
50
+ : createBlock(
51
+ name,
52
+ initialAttributes,
53
+ createBlocksFromInnerBlocksTemplate( innerBlocks )
54
+ );
46
55
 
47
56
  onInsert( insertedBlock, undefined, shouldFocusBlock );
48
57
  },
@@ -6,12 +6,13 @@ import { useDebounce } from '@wordpress/compose';
6
6
 
7
7
  export default function useDebouncedInput( defaultValue = '' ) {
8
8
  const [ input, setInput ] = useState( defaultValue );
9
- const [ debounced, setter ] = useState( defaultValue );
10
- const setDebounced = useDebounce( setter, 250 );
9
+ const [ debouncedInput, setDebouncedState ] = useState( defaultValue );
10
+
11
+ const setDebouncedInput = useDebounce( setDebouncedState, 250 );
12
+
11
13
  useEffect( () => {
12
- if ( debounced !== input ) {
13
- setDebounced( input );
14
- }
15
- }, [ debounced, input ] );
16
- return [ input, setInput, debounced ];
14
+ setDebouncedInput( input );
15
+ }, [ input ] );
16
+
17
+ return [ input, setInput, debouncedInput ];
17
18
  }
@@ -15,7 +15,7 @@ import { store as blockEditorStore } from '../../../store';
15
15
  const CUSTOM_CATEGORY = {
16
16
  name: 'custom',
17
17
  label: __( 'My patterns' ),
18
- description: __( 'Custom patterns add by site users' ),
18
+ description: __( 'Custom patterns added by site users' ),
19
19
  };
20
20
 
21
21
  /**
@@ -61,6 +61,7 @@ const usePatternsState = ( onInsert, rootClientId ) => {
61
61
  ),
62
62
  {
63
63
  type: 'snackbar',
64
+ id: 'block-pattern-inserted-notice',
64
65
  }
65
66
  );
66
67
  },
@@ -22,7 +22,10 @@ function ReusableBlocksList( { onHover, onInsert, rootClientId } ) {
22
22
  );
23
23
 
24
24
  const filteredItems = useMemo( () => {
25
- return items.filter( ( { category } ) => category === 'reusable' );
25
+ return items.filter(
26
+ ( { category, syncStatus } ) =>
27
+ category === 'reusable' && syncStatus !== 'unsynced'
28
+ );
26
29
  }, [ items ] );
27
30
 
28
31
  if ( filteredItems.length === 0 ) {
@@ -49,7 +49,9 @@ function InserterListItem( {
49
49
  ];
50
50
  }, [ item.name, item.initialAttributes, item.initialAttributes ] );
51
51
 
52
- const isSynced = isReusableBlock( item ) || isTemplatePart( item );
52
+ const isSynced =
53
+ ( isReusableBlock( item ) && item.syncStatus !== 'unsynced' ) ||
54
+ isTemplatePart( item );
53
55
 
54
56
  return (
55
57
  <InserterDraggableBlocks
@@ -15,6 +15,16 @@ The distinction between the two components is perhaps best summarized by the fol
15
15
  - `<URLInput>` - an input for presenting and managing selection behaviors associated with choosing a URL, optionally from a pool of available candidates.
16
16
  - `<LinkControl>` - includes the features of `<URLInput>`, plus additional UI and behaviors to control how this URL applies to the concept of a "link". This includes link "settings" (eg: "opens in new tab", etc) and dynamic, "on the fly" link creation capabilities.
17
17
 
18
+ ## Persistent "Advanced" (settings) toggle state
19
+
20
+ By default the link "settings" are hidden and can be toggled open/closed by way of a button labelled `Advanced` in the UI.
21
+
22
+ In some circumstances if may be desirable to persist the toggle state of this portion of the UI so that it remains in the last state triggered by user interaction.
23
+
24
+ For example, once the user has toggled the UI to "open", then it may remain open across all links on the site until such time as the user toggles the UI back again.
25
+
26
+ Consumers who which to take advantage of this functionality should ensure that their block editor environment utilizes the [`@wordpress/preferences`](packages/preferences/README.md) package. By default the `<LinkControl>` component will attempt to persist the state of UI to a setting named `linkControlSettingsDrawer` with a scope of `core/block-editor`. If the preferences package is not available then local state is used and the setting will not be persisted.
27
+
18
28
  ## Search Suggestions
19
29
 
20
30
  When creating links the `LinkControl` component will handle two kinds of input from users:
@@ -69,9 +79,7 @@ An array of settings objects associated with a link (for example: a setting to d
69
79
  To disable settings, pass in an empty array. for example:
70
80
 
71
81
  ```jsx
72
- <LinkControl
73
- settings={ [] }
74
- />
82
+ <LinkControl settings={ [] } />
75
83
  ```
76
84
 
77
85
  ### onChange
@@ -192,6 +200,7 @@ A `suggestion` should have the following shape:
192
200
  )}
193
201
  />
194
202
  ```
203
+
195
204
  ### renderControlBottom
196
205
 
197
206
  - Type: `Function`
@@ -12,6 +12,8 @@ import { useRef, useState, useEffect } from '@wordpress/element';
12
12
  import { focus } from '@wordpress/dom';
13
13
  import { ENTER } from '@wordpress/keycodes';
14
14
  import { isShallowEqualObjects } from '@wordpress/is-shallow-equal';
15
+ import { useSelect, useDispatch } from '@wordpress/data';
16
+ import { store as preferencesStore } from '@wordpress/preferences';
15
17
 
16
18
  /**
17
19
  * Internal dependencies
@@ -101,6 +103,9 @@ import { DEFAULT_LINK_SETTINGS } from './constants';
101
103
 
102
104
  const noop = () => {};
103
105
 
106
+ const PREFERENCE_SCOPE = 'core/block-editor';
107
+ const PREFERENCE_KEY = 'linkControlSettingsDrawer';
108
+
104
109
  /**
105
110
  * Renders a link control. A link control is a controlled input which maintains
106
111
  * a value associated with a link (HTML anchor element) and relevant settings
@@ -133,6 +138,41 @@ function LinkControl( {
133
138
  withCreateSuggestion = true;
134
139
  }
135
140
 
141
+ const [ settingsOpen, setSettingsOpen ] = useState( false );
142
+
143
+ const { advancedSettingsPreference } = useSelect( ( select ) => {
144
+ const prefsStore = select( preferencesStore );
145
+
146
+ return {
147
+ advancedSettingsPreference:
148
+ prefsStore.get( PREFERENCE_SCOPE, PREFERENCE_KEY ) ?? false,
149
+ };
150
+ }, [] );
151
+
152
+ const { set: setPreference } = useDispatch( preferencesStore );
153
+
154
+ /**
155
+ * Sets the open/closed state of the Advanced Settings Drawer,
156
+ * optionlly persisting the state to the user's preferences.
157
+ *
158
+ * Note that Block Editor components can be consumed by non-WordPress
159
+ * environments which may not have preferences setup.
160
+ * Therefore a local state is also used as a fallback.
161
+ *
162
+ * @param {boolean} prefVal the open/closed state of the Advanced Settings Drawer.
163
+ */
164
+ const setSettingsOpenWithPreference = ( prefVal ) => {
165
+ if ( setPreference ) {
166
+ setPreference( PREFERENCE_SCOPE, PREFERENCE_KEY, prefVal );
167
+ }
168
+ setSettingsOpen( prefVal );
169
+ };
170
+
171
+ // Block Editor components can be consumed by non-WordPress environments
172
+ // which may not have these preferences setup.
173
+ // Therefore a local state is used as a fallback.
174
+ const isSettingsOpen = advancedSettingsPreference || settingsOpen;
175
+
136
176
  const isMounting = useRef( true );
137
177
  const wrapperNode = useRef();
138
178
  const textInputRef = useRef();
@@ -140,8 +180,6 @@ function LinkControl( {
140
180
 
141
181
  const settingsKeys = settings.map( ( { id } ) => id );
142
182
 
143
- const [ settingsOpen, setSettingsOpen ] = useState( false );
144
-
145
183
  const [
146
184
  internalControlValue,
147
185
  setInternalControlValue,
@@ -207,7 +245,6 @@ function LinkControl( {
207
245
  wrapperNode.current.ownerDocument.activeElement
208
246
  );
209
247
 
210
- setSettingsOpen( false );
211
248
  setIsEditingLink( false );
212
249
  };
213
250
 
@@ -292,7 +329,6 @@ function LinkControl( {
292
329
  const shownUnlinkControl =
293
330
  onRemove && value && ! isEditingLink && ! isCreatingPage;
294
331
 
295
- const showSettings = !! settings?.length && isEditingLink && hasLinkValue;
296
332
  const showActions = isEditingLink && hasLinkValue;
297
333
 
298
334
  // Only show text control once a URL value has been committed
@@ -302,6 +338,7 @@ function LinkControl( {
302
338
 
303
339
  const isEditing = ( isEditingLink || ! value ) && ! isCreatingPage;
304
340
  const isDisabled = ! valueHasChanges || currentInputIsEmpty;
341
+ const showSettings = !! settings?.length && isEditingLink && hasLinkValue;
305
342
 
306
343
  return (
307
344
  <div
@@ -385,8 +422,8 @@ function LinkControl( {
385
422
  <div className="block-editor-link-control__tools">
386
423
  { ! currentInputIsEmpty && (
387
424
  <LinkControlSettingsDrawer
388
- settingsOpen={ settingsOpen }
389
- setSettingsOpen={ setSettingsOpen }
425
+ settingsOpen={ isSettingsOpen }
426
+ setSettingsOpen={ setSettingsOpenWithPreference }
390
427
  >
391
428
  <LinkSettings
392
429
  value={ internalControlValue }