@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
@@ -13,7 +13,7 @@ const PATTERN_OVERRIDES_SOURCE = 'core/pattern-overrides';
13
13
  const BLOCK_BINDINGS_ALLOWED_BLOCKS = {
14
14
  'core/paragraph': ['content'],
15
15
  'core/heading': ['content'],
16
- 'core/image': ['id', 'url', 'title', 'alt'],
16
+ 'core/image': ['id', 'url', 'title', 'alt', 'caption'],
17
17
  'core/button': ['url', 'text', 'linkTarget', 'rel'],
18
18
  'core/post-date': ['datetime']
19
19
  };
@@ -1 +1 @@
1
- {"version":3,"names":["useDispatch","useRegistry","store","blockEditorStore","useBlockEditContext","DEFAULT_ATTRIBUTE","PATTERN_OVERRIDES_SOURCE","BLOCK_BINDINGS_ALLOWED_BLOCKS","isObjectEmpty","object","Object","keys","length","canBindBlock","blockName","canBindAttribute","attributeName","includes","getBindableAttributes","hasPatternOverridesDefaultBinding","bindings","source","replacePatternOverridesDefaultBinding","supportedAttributes","bindingsWithDefaults","bindingSource","useBlockBindingsUtils","clientId","contextClientId","blockClientId","updateBlockAttributes","getBlockAttributes","select","updateBlockBindings","metadata","currentBindings","newBindings","entries","forEach","attribute","binding","newMetadata","undefined","removeAllBlockBindings"],"sources":["@wordpress/block-editor/src/utils/block-bindings.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useRegistry } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../store';\nimport { useBlockEditContext } from '../components/block-edit';\n\nconst DEFAULT_ATTRIBUTE = '__default';\nconst PATTERN_OVERRIDES_SOURCE = 'core/pattern-overrides';\nconst BLOCK_BINDINGS_ALLOWED_BLOCKS = {\n\t'core/paragraph': [ 'content' ],\n\t'core/heading': [ 'content' ],\n\t'core/image': [ 'id', 'url', 'title', 'alt' ],\n\t'core/button': [ 'url', 'text', 'linkTarget', 'rel' ],\n\t'core/post-date': [ 'datetime' ],\n};\n\n/**\n * Checks if the given object is empty.\n *\n * @param {?Object} object The object to check.\n *\n * @return {boolean} Whether the object is empty.\n */\nfunction isObjectEmpty( object ) {\n\treturn ! object || Object.keys( object ).length === 0;\n}\n\n/**\n * Based on the given block name, checks if it is possible to bind the block.\n *\n * @param {string} blockName The name of the block.\n *\n * @return {boolean} Whether it is possible to bind the block to sources.\n */\nexport function canBindBlock( blockName ) {\n\treturn blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS;\n}\n\n/**\n * Based on the given block name and attribute name, checks if it is possible to bind the block attribute.\n *\n * @param {string} blockName The name of the block.\n * @param {string} attributeName The name of attribute.\n *\n * @return {boolean} Whether it is possible to bind the block attribute.\n */\nexport function canBindAttribute( blockName, attributeName ) {\n\treturn (\n\t\tcanBindBlock( blockName ) &&\n\t\tBLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName )\n\t);\n}\n\n/**\n * Gets the bindable attributes for a given block.\n *\n * @param {string} blockName The name of the block.\n *\n * @return {string[]} The bindable attributes for the block.\n */\nexport function getBindableAttributes( blockName ) {\n\treturn BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ];\n}\n\n/**\n * Checks if the block has the `__default` binding for pattern overrides.\n *\n * @param {?Record<string, object>} bindings A block's bindings from the metadata attribute.\n *\n * @return {boolean} Whether the block has the `__default` binding for pattern overrides.\n */\nexport function hasPatternOverridesDefaultBinding( bindings ) {\n\treturn bindings?.[ DEFAULT_ATTRIBUTE ]?.source === PATTERN_OVERRIDES_SOURCE;\n}\n\n/**\n * Returns the bindings with the `__default` binding for pattern overrides\n * replaced with the full-set of supported attributes. e.g.:\n *\n * - bindings passed in: `{ __default: { source: 'core/pattern-overrides' } }`\n * - bindings returned: `{ content: { source: 'core/pattern-overrides' } }`\n *\n * @param {string} blockName The block name (e.g. 'core/paragraph').\n * @param {?Record<string, object>} bindings A block's bindings from the metadata attribute.\n *\n * @return {Object} The bindings with default replaced for pattern overrides.\n */\nexport function replacePatternOverridesDefaultBinding( blockName, bindings ) {\n\t// The `__default` binding currently only works for pattern overrides.\n\tif ( hasPatternOverridesDefaultBinding( bindings ) ) {\n\t\tconst supportedAttributes = BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ];\n\t\tconst bindingsWithDefaults = {};\n\t\tfor ( const attributeName of supportedAttributes ) {\n\t\t\t// If the block has mixed binding sources, retain any non pattern override bindings.\n\t\t\tconst bindingSource = bindings[ attributeName ]\n\t\t\t\t? bindings[ attributeName ]\n\t\t\t\t: { source: PATTERN_OVERRIDES_SOURCE };\n\t\t\tbindingsWithDefaults[ attributeName ] = bindingSource;\n\t\t}\n\n\t\treturn bindingsWithDefaults;\n\t}\n\n\treturn bindings;\n}\n\n/**\n * Contains utils to update the block `bindings` metadata.\n *\n * @typedef {Object} WPBlockBindingsUtils\n *\n * @property {Function} updateBlockBindings Updates the value of the bindings connected to block attributes.\n * @property {Function} removeAllBlockBindings Removes the bindings property of the `metadata` attribute.\n */\n\n/**\n * Retrieves the existing utils needed to update the block `bindings` metadata.\n * They can be used to create, modify, or remove connections from the existing block attributes.\n *\n * It contains the following utils:\n * - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`.\n * - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute.\n *\n * @since 6.7.0 Introduced in WordPress core.\n *\n * @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context.\n *\n * @return {?WPBlockBindingsUtils} Object containing the block bindings utils.\n *\n * @example\n * ```js\n * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n * const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils();\n *\n * // Update url and alt attributes.\n * updateBlockBindings( {\n * url: {\n * source: 'core/post-meta',\n * args: {\n * key: 'url_custom_field',\n * },\n * },\n * alt: {\n * source: 'core/post-meta',\n * args: {\n * key: 'text_custom_field',\n * },\n * },\n * } );\n *\n * // Remove binding from url attribute.\n * updateBlockBindings( { url: undefined } );\n *\n * // Remove bindings from all attributes.\n * removeAllBlockBindings();\n * ```\n */\nexport function useBlockBindingsUtils( clientId ) {\n\tconst { clientId: contextClientId } = useBlockEditContext();\n\tconst blockClientId = clientId || contextClientId;\n\tconst { updateBlockAttributes } = useDispatch( blockEditorStore );\n\tconst { getBlockAttributes } = useRegistry().select( blockEditorStore );\n\n\t/**\n\t * Updates the value of the bindings connected to block attributes.\n\t * It removes the binding when the new value is `undefined`.\n\t *\n\t * @param {Object} bindings Bindings including the attributes to update and the new object.\n\t * @param {string} bindings.source The source name to connect to.\n\t * @param {Object} [bindings.args] Object containing the arguments needed by the source.\n\t *\n\t * @example\n\t * ```js\n\t * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n\t *\n\t * const { updateBlockBindings } = useBlockBindingsUtils();\n\t * updateBlockBindings( {\n\t * url: {\n\t * source: 'core/post-meta',\n\t * args: {\n\t * key: 'url_custom_field',\n\t * },\n\t * \t },\n\t * alt: {\n\t * source: 'core/post-meta',\n\t * args: {\n\t * key: 'text_custom_field',\n\t * },\n\t * \t }\n\t * } );\n\t * ```\n\t */\n\tconst updateBlockBindings = ( bindings ) => {\n\t\tconst { metadata: { bindings: currentBindings, ...metadata } = {} } =\n\t\t\tgetBlockAttributes( blockClientId );\n\t\tconst newBindings = { ...currentBindings };\n\n\t\tObject.entries( bindings ).forEach( ( [ attribute, binding ] ) => {\n\t\t\tif ( ! binding && newBindings[ attribute ] ) {\n\t\t\t\tdelete newBindings[ attribute ];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewBindings[ attribute ] = binding;\n\t\t} );\n\n\t\tconst newMetadata = {\n\t\t\t...metadata,\n\t\t\tbindings: newBindings,\n\t\t};\n\n\t\tif ( isObjectEmpty( newMetadata.bindings ) ) {\n\t\t\tdelete newMetadata.bindings;\n\t\t}\n\n\t\tupdateBlockAttributes( blockClientId, {\n\t\t\tmetadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata,\n\t\t} );\n\t};\n\n\t/**\n\t * Removes the bindings property of the `metadata` attribute.\n\t *\n\t * @example\n\t * ```js\n\t * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n\t *\n\t * const { removeAllBlockBindings } = useBlockBindingsUtils();\n\t * removeAllBlockBindings();\n\t * ```\n\t */\n\tconst removeAllBlockBindings = () => {\n\t\tconst { metadata: { bindings, ...metadata } = {} } =\n\t\t\tgetBlockAttributes( blockClientId );\n\t\tupdateBlockAttributes( blockClientId, {\n\t\t\tmetadata: isObjectEmpty( metadata ) ? undefined : metadata,\n\t\t} );\n\t};\n\n\treturn { updateBlockBindings, removeAllBlockBindings };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useDispatch","useRegistry","store","blockEditorStore","useBlockEditContext","DEFAULT_ATTRIBUTE","PATTERN_OVERRIDES_SOURCE","BLOCK_BINDINGS_ALLOWED_BLOCKS","isObjectEmpty","object","Object","keys","length","canBindBlock","blockName","canBindAttribute","attributeName","includes","getBindableAttributes","hasPatternOverridesDefaultBinding","bindings","source","replacePatternOverridesDefaultBinding","supportedAttributes","bindingsWithDefaults","bindingSource","useBlockBindingsUtils","clientId","contextClientId","blockClientId","updateBlockAttributes","getBlockAttributes","select","updateBlockBindings","metadata","currentBindings","newBindings","entries","forEach","attribute","binding","newMetadata","undefined","removeAllBlockBindings"],"sources":["@wordpress/block-editor/src/utils/block-bindings.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useRegistry } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../store';\nimport { useBlockEditContext } from '../components/block-edit';\n\nconst DEFAULT_ATTRIBUTE = '__default';\nconst PATTERN_OVERRIDES_SOURCE = 'core/pattern-overrides';\nconst BLOCK_BINDINGS_ALLOWED_BLOCKS = {\n\t'core/paragraph': [ 'content' ],\n\t'core/heading': [ 'content' ],\n\t'core/image': [ 'id', 'url', 'title', 'alt', 'caption' ],\n\t'core/button': [ 'url', 'text', 'linkTarget', 'rel' ],\n\t'core/post-date': [ 'datetime' ],\n};\n\n/**\n * Checks if the given object is empty.\n *\n * @param {?Object} object The object to check.\n *\n * @return {boolean} Whether the object is empty.\n */\nfunction isObjectEmpty( object ) {\n\treturn ! object || Object.keys( object ).length === 0;\n}\n\n/**\n * Based on the given block name, checks if it is possible to bind the block.\n *\n * @param {string} blockName The name of the block.\n *\n * @return {boolean} Whether it is possible to bind the block to sources.\n */\nexport function canBindBlock( blockName ) {\n\treturn blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS;\n}\n\n/**\n * Based on the given block name and attribute name, checks if it is possible to bind the block attribute.\n *\n * @param {string} blockName The name of the block.\n * @param {string} attributeName The name of attribute.\n *\n * @return {boolean} Whether it is possible to bind the block attribute.\n */\nexport function canBindAttribute( blockName, attributeName ) {\n\treturn (\n\t\tcanBindBlock( blockName ) &&\n\t\tBLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ].includes( attributeName )\n\t);\n}\n\n/**\n * Gets the bindable attributes for a given block.\n *\n * @param {string} blockName The name of the block.\n *\n * @return {string[]} The bindable attributes for the block.\n */\nexport function getBindableAttributes( blockName ) {\n\treturn BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ];\n}\n\n/**\n * Checks if the block has the `__default` binding for pattern overrides.\n *\n * @param {?Record<string, object>} bindings A block's bindings from the metadata attribute.\n *\n * @return {boolean} Whether the block has the `__default` binding for pattern overrides.\n */\nexport function hasPatternOverridesDefaultBinding( bindings ) {\n\treturn bindings?.[ DEFAULT_ATTRIBUTE ]?.source === PATTERN_OVERRIDES_SOURCE;\n}\n\n/**\n * Returns the bindings with the `__default` binding for pattern overrides\n * replaced with the full-set of supported attributes. e.g.:\n *\n * - bindings passed in: `{ __default: { source: 'core/pattern-overrides' } }`\n * - bindings returned: `{ content: { source: 'core/pattern-overrides' } }`\n *\n * @param {string} blockName The block name (e.g. 'core/paragraph').\n * @param {?Record<string, object>} bindings A block's bindings from the metadata attribute.\n *\n * @return {Object} The bindings with default replaced for pattern overrides.\n */\nexport function replacePatternOverridesDefaultBinding( blockName, bindings ) {\n\t// The `__default` binding currently only works for pattern overrides.\n\tif ( hasPatternOverridesDefaultBinding( bindings ) ) {\n\t\tconst supportedAttributes = BLOCK_BINDINGS_ALLOWED_BLOCKS[ blockName ];\n\t\tconst bindingsWithDefaults = {};\n\t\tfor ( const attributeName of supportedAttributes ) {\n\t\t\t// If the block has mixed binding sources, retain any non pattern override bindings.\n\t\t\tconst bindingSource = bindings[ attributeName ]\n\t\t\t\t? bindings[ attributeName ]\n\t\t\t\t: { source: PATTERN_OVERRIDES_SOURCE };\n\t\t\tbindingsWithDefaults[ attributeName ] = bindingSource;\n\t\t}\n\n\t\treturn bindingsWithDefaults;\n\t}\n\n\treturn bindings;\n}\n\n/**\n * Contains utils to update the block `bindings` metadata.\n *\n * @typedef {Object} WPBlockBindingsUtils\n *\n * @property {Function} updateBlockBindings Updates the value of the bindings connected to block attributes.\n * @property {Function} removeAllBlockBindings Removes the bindings property of the `metadata` attribute.\n */\n\n/**\n * Retrieves the existing utils needed to update the block `bindings` metadata.\n * They can be used to create, modify, or remove connections from the existing block attributes.\n *\n * It contains the following utils:\n * - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`.\n * - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute.\n *\n * @since 6.7.0 Introduced in WordPress core.\n *\n * @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context.\n *\n * @return {?WPBlockBindingsUtils} Object containing the block bindings utils.\n *\n * @example\n * ```js\n * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n * const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils();\n *\n * // Update url and alt attributes.\n * updateBlockBindings( {\n * url: {\n * source: 'core/post-meta',\n * args: {\n * key: 'url_custom_field',\n * },\n * },\n * alt: {\n * source: 'core/post-meta',\n * args: {\n * key: 'text_custom_field',\n * },\n * },\n * } );\n *\n * // Remove binding from url attribute.\n * updateBlockBindings( { url: undefined } );\n *\n * // Remove bindings from all attributes.\n * removeAllBlockBindings();\n * ```\n */\nexport function useBlockBindingsUtils( clientId ) {\n\tconst { clientId: contextClientId } = useBlockEditContext();\n\tconst blockClientId = clientId || contextClientId;\n\tconst { updateBlockAttributes } = useDispatch( blockEditorStore );\n\tconst { getBlockAttributes } = useRegistry().select( blockEditorStore );\n\n\t/**\n\t * Updates the value of the bindings connected to block attributes.\n\t * It removes the binding when the new value is `undefined`.\n\t *\n\t * @param {Object} bindings Bindings including the attributes to update and the new object.\n\t * @param {string} bindings.source The source name to connect to.\n\t * @param {Object} [bindings.args] Object containing the arguments needed by the source.\n\t *\n\t * @example\n\t * ```js\n\t * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n\t *\n\t * const { updateBlockBindings } = useBlockBindingsUtils();\n\t * updateBlockBindings( {\n\t * url: {\n\t * source: 'core/post-meta',\n\t * args: {\n\t * key: 'url_custom_field',\n\t * },\n\t * \t },\n\t * alt: {\n\t * source: 'core/post-meta',\n\t * args: {\n\t * key: 'text_custom_field',\n\t * },\n\t * \t }\n\t * } );\n\t * ```\n\t */\n\tconst updateBlockBindings = ( bindings ) => {\n\t\tconst { metadata: { bindings: currentBindings, ...metadata } = {} } =\n\t\t\tgetBlockAttributes( blockClientId );\n\t\tconst newBindings = { ...currentBindings };\n\n\t\tObject.entries( bindings ).forEach( ( [ attribute, binding ] ) => {\n\t\t\tif ( ! binding && newBindings[ attribute ] ) {\n\t\t\t\tdelete newBindings[ attribute ];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewBindings[ attribute ] = binding;\n\t\t} );\n\n\t\tconst newMetadata = {\n\t\t\t...metadata,\n\t\t\tbindings: newBindings,\n\t\t};\n\n\t\tif ( isObjectEmpty( newMetadata.bindings ) ) {\n\t\t\tdelete newMetadata.bindings;\n\t\t}\n\n\t\tupdateBlockAttributes( blockClientId, {\n\t\t\tmetadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata,\n\t\t} );\n\t};\n\n\t/**\n\t * Removes the bindings property of the `metadata` attribute.\n\t *\n\t * @example\n\t * ```js\n\t * import { useBlockBindingsUtils } from '@wordpress/block-editor'\n\t *\n\t * const { removeAllBlockBindings } = useBlockBindingsUtils();\n\t * removeAllBlockBindings();\n\t * ```\n\t */\n\tconst removeAllBlockBindings = () => {\n\t\tconst { metadata: { bindings, ...metadata } = {} } =\n\t\t\tgetBlockAttributes( blockClientId );\n\t\tupdateBlockAttributes( blockClientId, {\n\t\t\tmetadata: isObjectEmpty( metadata ) ? undefined : metadata,\n\t\t} );\n\t};\n\n\treturn { updateBlockBindings, removeAllBlockBindings };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,WAAW,EAAEC,WAAW,QAAQ,iBAAiB;;AAE1D;AACA;AACA;AACA,SAASC,KAAK,IAAIC,gBAAgB,QAAQ,UAAU;AACpD,SAASC,mBAAmB,QAAQ,0BAA0B;AAE9D,MAAMC,iBAAiB,GAAG,WAAW;AACrC,MAAMC,wBAAwB,GAAG,wBAAwB;AACzD,MAAMC,6BAA6B,GAAG;EACrC,gBAAgB,EAAE,CAAE,SAAS,CAAE;EAC/B,cAAc,EAAE,CAAE,SAAS,CAAE;EAC7B,YAAY,EAAE,CAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAE;EACxD,aAAa,EAAE,CAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,CAAE;EACrD,gBAAgB,EAAE,CAAE,UAAU;AAC/B,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,aAAaA,CAAEC,MAAM,EAAG;EAChC,OAAO,CAAEA,MAAM,IAAIC,MAAM,CAACC,IAAI,CAAEF,MAAO,CAAC,CAACG,MAAM,KAAK,CAAC;AACtD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,YAAYA,CAAEC,SAAS,EAAG;EACzC,OAAOA,SAAS,IAAIP,6BAA6B;AAClD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASQ,gBAAgBA,CAAED,SAAS,EAAEE,aAAa,EAAG;EAC5D,OACCH,YAAY,CAAEC,SAAU,CAAC,IACzBP,6BAA6B,CAAEO,SAAS,CAAE,CAACG,QAAQ,CAAED,aAAc,CAAC;AAEtE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,qBAAqBA,CAAEJ,SAAS,EAAG;EAClD,OAAOP,6BAA6B,CAAEO,SAAS,CAAE;AAClD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,iCAAiCA,CAAEC,QAAQ,EAAG;EAC7D,OAAOA,QAAQ,GAAIf,iBAAiB,CAAE,EAAEgB,MAAM,KAAKf,wBAAwB;AAC5E;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASgB,qCAAqCA,CAAER,SAAS,EAAEM,QAAQ,EAAG;EAC5E;EACA,IAAKD,iCAAiC,CAAEC,QAAS,CAAC,EAAG;IACpD,MAAMG,mBAAmB,GAAGhB,6BAA6B,CAAEO,SAAS,CAAE;IACtE,MAAMU,oBAAoB,GAAG,CAAC,CAAC;IAC/B,KAAM,MAAMR,aAAa,IAAIO,mBAAmB,EAAG;MAClD;MACA,MAAME,aAAa,GAAGL,QAAQ,CAAEJ,aAAa,CAAE,GAC5CI,QAAQ,CAAEJ,aAAa,CAAE,GACzB;QAAEK,MAAM,EAAEf;MAAyB,CAAC;MACvCkB,oBAAoB,CAAER,aAAa,CAAE,GAAGS,aAAa;IACtD;IAEA,OAAOD,oBAAoB;EAC5B;EAEA,OAAOJ,QAAQ;AAChB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,qBAAqBA,CAAEC,QAAQ,EAAG;EACjD,MAAM;IAAEA,QAAQ,EAAEC;EAAgB,CAAC,GAAGxB,mBAAmB,CAAC,CAAC;EAC3D,MAAMyB,aAAa,GAAGF,QAAQ,IAAIC,eAAe;EACjD,MAAM;IAAEE;EAAsB,CAAC,GAAG9B,WAAW,CAAEG,gBAAiB,CAAC;EACjE,MAAM;IAAE4B;EAAmB,CAAC,GAAG9B,WAAW,CAAC,CAAC,CAAC+B,MAAM,CAAE7B,gBAAiB,CAAC;;EAEvE;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACC,MAAM8B,mBAAmB,GAAKb,QAAQ,IAAM;IAC3C,MAAM;MAAEc,QAAQ,EAAE;QAAEd,QAAQ,EAAEe,eAAe;QAAE,GAAGD;MAAS,CAAC,GAAG,CAAC;IAAE,CAAC,GAClEH,kBAAkB,CAAEF,aAAc,CAAC;IACpC,MAAMO,WAAW,GAAG;MAAE,GAAGD;IAAgB,CAAC;IAE1CzB,MAAM,CAAC2B,OAAO,CAAEjB,QAAS,CAAC,CAACkB,OAAO,CAAE,CAAE,CAAEC,SAAS,EAAEC,OAAO,CAAE,KAAM;MACjE,IAAK,CAAEA,OAAO,IAAIJ,WAAW,CAAEG,SAAS,CAAE,EAAG;QAC5C,OAAOH,WAAW,CAAEG,SAAS,CAAE;QAC/B;MACD;MACAH,WAAW,CAAEG,SAAS,CAAE,GAAGC,OAAO;IACnC,CAAE,CAAC;IAEH,MAAMC,WAAW,GAAG;MACnB,GAAGP,QAAQ;MACXd,QAAQ,EAAEgB;IACX,CAAC;IAED,IAAK5B,aAAa,CAAEiC,WAAW,CAACrB,QAAS,CAAC,EAAG;MAC5C,OAAOqB,WAAW,CAACrB,QAAQ;IAC5B;IAEAU,qBAAqB,CAAED,aAAa,EAAE;MACrCK,QAAQ,EAAE1B,aAAa,CAAEiC,WAAY,CAAC,GAAGC,SAAS,GAAGD;IACtD,CAAE,CAAC;EACJ,CAAC;;EAED;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACC,MAAME,sBAAsB,GAAGA,CAAA,KAAM;IACpC,MAAM;MAAET,QAAQ,EAAE;QAAEd,QAAQ;QAAE,GAAGc;MAAS,CAAC,GAAG,CAAC;IAAE,CAAC,GACjDH,kBAAkB,CAAEF,aAAc,CAAC;IACpCC,qBAAqB,CAAED,aAAa,EAAE;MACrCK,QAAQ,EAAE1B,aAAa,CAAE0B,QAAS,CAAC,GAAGQ,SAAS,GAAGR;IACnD,CAAE,CAAC;EACJ,CAAC;EAED,OAAO;IAAED,mBAAmB;IAAEU;EAAuB,CAAC;AACvD","ignoreList":[]}
@@ -467,6 +467,11 @@ iframe[name=editor-canvas] {
467
467
  border-top: 1px solid #ddd;
468
468
  }
469
469
 
470
+ .block-editor-block-inspector-edit-contents-button {
471
+ margin-top: 8px;
472
+ justify-content: center;
473
+ }
474
+
470
475
  /**
471
476
  * Insertion Point.
472
477
  */
@@ -3697,7 +3702,7 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3697
3702
  .block-editor-block-toolbar.is-synced .block-editor-block-switcher .components-button .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button .block-editor-block-icon {
3698
3703
  color: var(--wp-block-synced-color);
3699
3704
  }
3700
- .block-editor-block-toolbar.is-synced .components-toolbar-button.block-editor-block-switcher__no-switcher-icon:disabled .block-editor-block-icon.has-colors, .block-editor-block-toolbar.is-connected .components-toolbar-button.block-editor-block-switcher__no-switcher-icon:disabled .block-editor-block-icon.has-colors {
3705
+ .block-editor-block-toolbar.is-synced .block-editor-block-switcher__no-switcher-icon[aria-disabled=true] .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher__no-switcher-icon[aria-disabled=true] .block-editor-block-icon {
3701
3706
  color: var(--wp-block-synced-color);
3702
3707
  }
3703
3708
  .block-editor-block-toolbar > :last-child,
@@ -3806,13 +3811,13 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3806
3811
  display: inline-flex;
3807
3812
  }
3808
3813
 
3809
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon {
3814
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text)) {
3810
3815
  width: auto;
3811
3816
  }
3812
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon svg {
3817
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text)) svg {
3813
3818
  display: none;
3814
3819
  }
3815
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon::after {
3820
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text))::after {
3816
3821
  content: attr(aria-label);
3817
3822
  font-size: 12px;
3818
3823
  }
@@ -467,6 +467,11 @@ iframe[name=editor-canvas] {
467
467
  border-top: 1px solid #ddd;
468
468
  }
469
469
 
470
+ .block-editor-block-inspector-edit-contents-button {
471
+ margin-top: 8px;
472
+ justify-content: center;
473
+ }
474
+
470
475
  /**
471
476
  * Insertion Point.
472
477
  */
@@ -3699,7 +3704,7 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3699
3704
  .block-editor-block-toolbar.is-synced .block-editor-block-switcher .components-button .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher .components-button .block-editor-block-icon {
3700
3705
  color: var(--wp-block-synced-color);
3701
3706
  }
3702
- .block-editor-block-toolbar.is-synced .components-toolbar-button.block-editor-block-switcher__no-switcher-icon:disabled .block-editor-block-icon.has-colors, .block-editor-block-toolbar.is-connected .components-toolbar-button.block-editor-block-switcher__no-switcher-icon:disabled .block-editor-block-icon.has-colors {
3707
+ .block-editor-block-toolbar.is-synced .block-editor-block-switcher__no-switcher-icon[aria-disabled=true] .block-editor-block-icon, .block-editor-block-toolbar.is-connected .block-editor-block-switcher__no-switcher-icon[aria-disabled=true] .block-editor-block-icon {
3703
3708
  color: var(--wp-block-synced-color);
3704
3709
  }
3705
3710
  .block-editor-block-toolbar > :last-child,
@@ -3808,13 +3813,13 @@ div.block-editor-bindings__panel button:hover .block-editor-bindings__item span
3808
3813
  display: inline-flex;
3809
3814
  }
3810
3815
 
3811
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon {
3816
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text)) {
3812
3817
  width: auto;
3813
3818
  }
3814
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon svg {
3819
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text)) svg {
3815
3820
  display: none;
3816
3821
  }
3817
- .show-icon-labels .block-editor-block-toolbar .components-button.has-icon::after {
3822
+ .show-icon-labels .block-editor-block-toolbar .components-button.has-icon:where(:not(.has-text))::after {
3818
3823
  content: attr(aria-label);
3819
3824
  font-size: 12px;
3820
3825
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "15.3.1-next.6f42e1382.0",
3
+ "version": "15.3.1-next.a730c9c8c.0",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -37,38 +37,38 @@
37
37
  "@emotion/react": "^11.7.1",
38
38
  "@emotion/styled": "^11.6.0",
39
39
  "@react-spring/web": "^9.4.5",
40
- "@wordpress/a11y": "^4.30.1-next.6f42e1382.0",
41
- "@wordpress/api-fetch": "^7.30.1-next.6f42e1382.0",
42
- "@wordpress/blob": "^4.30.1-next.6f42e1382.0",
43
- "@wordpress/block-serialization-default-parser": "^5.30.1-next.6f42e1382.0",
44
- "@wordpress/blocks": "^15.3.1-next.6f42e1382.0",
45
- "@wordpress/commands": "^1.30.1-next.6f42e1382.0",
46
- "@wordpress/components": "^30.3.2-next.6f42e1382.0",
47
- "@wordpress/compose": "^7.30.1-next.6f42e1382.0",
48
- "@wordpress/data": "^10.30.1-next.6f42e1382.0",
49
- "@wordpress/date": "^5.30.1-next.6f42e1382.0",
50
- "@wordpress/deprecated": "^4.30.1-next.6f42e1382.0",
51
- "@wordpress/dom": "^4.30.1-next.6f42e1382.0",
52
- "@wordpress/element": "^6.30.1-next.6f42e1382.0",
53
- "@wordpress/escape-html": "^3.30.1-next.6f42e1382.0",
54
- "@wordpress/hooks": "^4.30.1-next.6f42e1382.0",
55
- "@wordpress/html-entities": "^4.30.1-next.6f42e1382.0",
56
- "@wordpress/i18n": "^6.3.1-next.6f42e1382.0",
57
- "@wordpress/icons": "^10.30.1-next.6f42e1382.0",
58
- "@wordpress/is-shallow-equal": "^5.30.1-next.6f42e1382.0",
59
- "@wordpress/keyboard-shortcuts": "^5.30.1-next.6f42e1382.0",
60
- "@wordpress/keycodes": "^4.30.1-next.6f42e1382.0",
61
- "@wordpress/notices": "^5.30.1-next.6f42e1382.0",
62
- "@wordpress/preferences": "^4.30.1-next.6f42e1382.0",
63
- "@wordpress/priority-queue": "^3.30.1-next.6f42e1382.0",
64
- "@wordpress/private-apis": "^1.30.1-next.6f42e1382.0",
65
- "@wordpress/rich-text": "^7.30.1-next.6f42e1382.0",
66
- "@wordpress/style-engine": "^2.30.1-next.6f42e1382.0",
67
- "@wordpress/token-list": "^3.30.1-next.6f42e1382.0",
68
- "@wordpress/upload-media": "^0.15.1-next.6f42e1382.0",
69
- "@wordpress/url": "^4.30.1-next.6f42e1382.0",
70
- "@wordpress/warning": "^3.30.1-next.6f42e1382.0",
71
- "@wordpress/wordcount": "^4.30.1-next.6f42e1382.0",
40
+ "@wordpress/a11y": "^4.30.1-next.a730c9c8c.0",
41
+ "@wordpress/api-fetch": "^7.30.1-next.a730c9c8c.0",
42
+ "@wordpress/blob": "^4.30.1-next.a730c9c8c.0",
43
+ "@wordpress/block-serialization-default-parser": "^5.30.1-next.a730c9c8c.0",
44
+ "@wordpress/blocks": "^15.3.1-next.a730c9c8c.0",
45
+ "@wordpress/commands": "^1.30.1-next.a730c9c8c.0",
46
+ "@wordpress/components": "^30.3.2-next.a730c9c8c.0",
47
+ "@wordpress/compose": "^7.30.1-next.a730c9c8c.0",
48
+ "@wordpress/data": "^10.30.1-next.a730c9c8c.0",
49
+ "@wordpress/date": "^5.30.1-next.a730c9c8c.0",
50
+ "@wordpress/deprecated": "^4.30.1-next.a730c9c8c.0",
51
+ "@wordpress/dom": "^4.30.1-next.a730c9c8c.0",
52
+ "@wordpress/element": "^6.30.1-next.a730c9c8c.0",
53
+ "@wordpress/escape-html": "^3.30.1-next.a730c9c8c.0",
54
+ "@wordpress/hooks": "^4.30.1-next.a730c9c8c.0",
55
+ "@wordpress/html-entities": "^4.30.1-next.a730c9c8c.0",
56
+ "@wordpress/i18n": "^6.3.1-next.a730c9c8c.0",
57
+ "@wordpress/icons": "^10.30.1-next.a730c9c8c.0",
58
+ "@wordpress/is-shallow-equal": "^5.30.1-next.a730c9c8c.0",
59
+ "@wordpress/keyboard-shortcuts": "^5.30.1-next.a730c9c8c.0",
60
+ "@wordpress/keycodes": "^4.30.1-next.a730c9c8c.0",
61
+ "@wordpress/notices": "^5.30.1-next.a730c9c8c.0",
62
+ "@wordpress/preferences": "^4.30.1-next.a730c9c8c.0",
63
+ "@wordpress/priority-queue": "^3.30.1-next.a730c9c8c.0",
64
+ "@wordpress/private-apis": "^1.30.1-next.a730c9c8c.0",
65
+ "@wordpress/rich-text": "^7.30.1-next.a730c9c8c.0",
66
+ "@wordpress/style-engine": "^2.30.1-next.a730c9c8c.0",
67
+ "@wordpress/token-list": "^3.30.1-next.a730c9c8c.0",
68
+ "@wordpress/upload-media": "^0.15.1-next.a730c9c8c.0",
69
+ "@wordpress/url": "^4.30.1-next.a730c9c8c.0",
70
+ "@wordpress/warning": "^3.30.1-next.a730c9c8c.0",
71
+ "@wordpress/wordcount": "^4.30.1-next.a730c9c8c.0",
72
72
  "change-case": "^4.1.2",
73
73
  "clsx": "^2.1.1",
74
74
  "colord": "^2.7.0",
@@ -91,5 +91,5 @@
91
91
  "publishConfig": {
92
92
  "access": "public"
93
93
  },
94
- "gitHead": "8806899f598577a3c90a55d9aa79fbc372fe1e75"
94
+ "gitHead": "85a580bd2c55f811c8969b42dbb10209d19d514e"
95
95
  }
@@ -53,9 +53,18 @@ const { Badge } = unlock( componentsPrivateApis );
53
53
  * @param {Object} [props.blockType] Deprecated: Object containing block type data.
54
54
  * @param {string} [props.className] Additional classes to apply to the card.
55
55
  * @param {string} [props.name] Custom block name to display before the title.
56
+ * @param {Element} [props.children] Children.
56
57
  * @return {Element} Block card component.
57
58
  */
58
- function BlockCard( { title, icon, description, blockType, className, name } ) {
59
+ function BlockCard( {
60
+ title,
61
+ icon,
62
+ description,
63
+ blockType,
64
+ className,
65
+ name,
66
+ children,
67
+ } ) {
59
68
  if ( blockType ) {
60
69
  deprecated( '`blockType` property in `BlockCard component`', {
61
70
  since: '5.7',
@@ -109,6 +118,7 @@ function BlockCard( { title, icon, description, blockType, className, name } ) {
109
118
  { description }
110
119
  </Text>
111
120
  ) }
121
+ { children }
112
122
  </VStack>
113
123
  </div>
114
124
  );
@@ -0,0 +1,46 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { Button } from '@wordpress/components';
5
+ import { useDispatch, useSelect } from '@wordpress/data';
6
+ import { __ } from '@wordpress/i18n';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { store as blockEditorStore } from '../../store';
12
+
13
+ export default function EditContentsButton( { clientId } ) {
14
+ const { updateBlockAttributes } = useDispatch( blockEditorStore );
15
+ const { attributes } = useSelect(
16
+ ( select ) => {
17
+ return {
18
+ attributes:
19
+ select( blockEditorStore ).getBlockAttributes( clientId ),
20
+ };
21
+ },
22
+ [ clientId ]
23
+ );
24
+
25
+ if ( ! attributes?.metadata?.patternName ) {
26
+ return null;
27
+ }
28
+
29
+ return (
30
+ <Button
31
+ className="block-editor-block-inspector-edit-contents-button"
32
+ __next40pxDefaultSize
33
+ variant="secondary"
34
+ onClick={ () => {
35
+ const { patternName, ...metadataWithoutPatternName } =
36
+ attributes?.metadata ?? {};
37
+ updateBlockAttributes( clientId, {
38
+ ...attributes,
39
+ metadata: metadataWithoutPatternName,
40
+ } );
41
+ } }
42
+ >
43
+ { __( 'Edit contents' ) }
44
+ </Button>
45
+ );
46
+ }
@@ -13,6 +13,7 @@ import { useSelect } from '@wordpress/data';
13
13
  /**
14
14
  * Internal dependencies
15
15
  */
16
+ import EditContentsButton from './edit-contents-button';
16
17
  import SkipToSelectedBlock from '../skip-to-selected-block';
17
18
  import BlockCard from '../block-card';
18
19
  import MultiSelectionInspector from '../multi-selection-inspector';
@@ -247,7 +248,11 @@ const BlockInspectorSingleBlock = ( {
247
248
  <BlockCard
248
249
  { ...blockInformation }
249
250
  className={ blockInformation.isSynced && 'is-synced' }
250
- />
251
+ >
252
+ { window?.__experimentalContentOnlyPatternInsertion && (
253
+ <EditContentsButton clientId={ clientId } />
254
+ ) }
255
+ </BlockCard>
251
256
  <BlockVariationTransforms blockClientId={ clientId } />
252
257
  { showTabs && (
253
258
  <InspectorControlsTabs
@@ -51,3 +51,8 @@
51
51
  .block-editor-block-inspector__no-block-tools {
52
52
  border-top: $border-width solid $gray-300;
53
53
  }
54
+
55
+ .block-editor-block-inspector-edit-contents-button {
56
+ margin-top: $grid-unit-10;
57
+ justify-content: center;
58
+ }
@@ -102,14 +102,16 @@ function BlockSwitcherDropdownMenuContents( {
102
102
  selectForMultipleBlocks( transformedBlocks );
103
103
  }
104
104
  /**
105
- * The `isTemplate` check is a stopgap solution here.
105
+ * The `isSynced` check is a stopgap solution here.
106
106
  * Ideally, the Transforms API should handle this
107
107
  * by allowing to exclude blocks from wildcard transformations.
108
108
  */
109
109
  const isSingleBlock = blocks.length === 1;
110
- const isTemplate = isSingleBlock && isTemplatePart( blocks[ 0 ] );
110
+ const isSynced =
111
+ isSingleBlock &&
112
+ ( isTemplatePart( blocks[ 0 ] ) || isReusableBlock( blocks[ 0 ] ) );
111
113
  const hasPossibleBlockTransformations =
112
- !! possibleBlockTransformations.length && canRemove && ! isTemplate;
114
+ !! possibleBlockTransformations?.length && canRemove && ! isSynced;
113
115
  const hasPossibleBlockVariationTransformations =
114
116
  !! blockVariationTransformations?.length;
115
117
  const hasPatternTransformation = !! patterns?.length && canRemove;
@@ -52,10 +52,8 @@
52
52
  color: var(--wp-block-synced-color);
53
53
  }
54
54
 
55
- .components-toolbar-button.block-editor-block-switcher__no-switcher-icon {
56
- &:disabled .block-editor-block-icon.has-colors {
57
- color: var(--wp-block-synced-color);
58
- }
55
+ .block-editor-block-switcher__no-switcher-icon[aria-disabled="true"] .block-editor-block-icon {
56
+ color: var(--wp-block-synced-color);
59
57
  }
60
58
  }
61
59
 
@@ -175,7 +173,7 @@
175
173
 
176
174
  .show-icon-labels {
177
175
  .block-editor-block-toolbar {
178
- .components-button.has-icon {
176
+ .components-button.has-icon:where(:not(.has-text)) {
179
177
  width: auto;
180
178
 
181
179
  // Hide the button icons when labels are set to display...
@@ -162,7 +162,8 @@ function __experimentalBlockVariationTransforms( { blockClientId } ) {
162
162
  return {
163
163
  activeBlockVariation: getActiveBlockVariation(
164
164
  name,
165
- getBlockAttributes( blockClientId )
165
+ getBlockAttributes( blockClientId ),
166
+ 'transform'
166
167
  ),
167
168
  variations: name && getBlockVariations( name, 'transform' ),
168
169
  isContentOnly:
@@ -7,6 +7,8 @@ import {
7
7
  hasMixedValues,
8
8
  hasDefinedValues,
9
9
  mode,
10
+ getPresetValueFromCustomValue,
11
+ getPresetValueFromControlValue,
10
12
  } from '../utils';
11
13
 
12
14
  const defaultUnitSelections = {
@@ -180,3 +182,72 @@ describe( 'mode', () => {
180
182
  expect( mode( values ) ).toBe( 'a' );
181
183
  } );
182
184
  } );
185
+
186
+ describe( 'getPresetValueFromCustomValue', () => {
187
+ const presets = [
188
+ { name: 'None', slug: '0', size: 0 },
189
+ { name: 'Small', slug: 'sm', size: '4px' },
190
+ { name: 'Medium', slug: 'md', size: 'clamp(2px, 1vw, 8px)' },
191
+ ];
192
+
193
+ it( 'should return "0" if value is "0"', () => {
194
+ expect( getPresetValueFromCustomValue( '0', presets ) ).toBe( '0' );
195
+ } );
196
+
197
+ it( 'should return preset reference if value matches a preset', () => {
198
+ expect( getPresetValueFromCustomValue( '4px', presets ) ).toBe(
199
+ 'var:preset|border-radius|sm'
200
+ );
201
+ expect(
202
+ getPresetValueFromCustomValue( 'clamp(2px, 1vw, 8px)', presets )
203
+ ).toBe( 'var:preset|border-radius|md' );
204
+ } );
205
+
206
+ it( 'should return value as-is if no matching preset', () => {
207
+ expect( getPresetValueFromCustomValue( '7px', presets ) ).toBe( '7px' );
208
+ } );
209
+
210
+ it( 'should return value as-is if already a preset reference', () => {
211
+ expect(
212
+ getPresetValueFromCustomValue(
213
+ 'var:preset|border-radius|md',
214
+ presets
215
+ )
216
+ ).toBe( 'var:preset|border-radius|md' );
217
+ } );
218
+
219
+ it( 'should return undefined if value is undefined', () => {
220
+ expect(
221
+ getPresetValueFromCustomValue( undefined, presets )
222
+ ).toBeUndefined();
223
+ } );
224
+ } );
225
+
226
+ describe( 'getPresetValueFromControlValue', () => {
227
+ const presets = [
228
+ { name: 'None', slug: '0', size: 0 },
229
+ { name: 'Small', slug: 'sm', size: '4px' },
230
+ { name: 'Medium', slug: 'md', size: 'clamp(2px, 1vw, 8px)' },
231
+ ];
232
+
233
+ it( 'should return "0" if control value is 0 and not selectList', () => {
234
+ expect( getPresetValueFromControlValue( 0, 'slider', presets ) ).toBe(
235
+ '0'
236
+ );
237
+ } );
238
+
239
+ it( 'should return undefined if control value is 0 and controlType is selectList', () => {
240
+ expect(
241
+ getPresetValueFromControlValue( 0, 'selectList', presets )
242
+ ).toBeUndefined();
243
+ } );
244
+
245
+ it( 'should return preset reference for other values', () => {
246
+ expect( getPresetValueFromControlValue( 1, 'slider', presets ) ).toBe(
247
+ 'var:preset|border-radius|sm'
248
+ );
249
+ expect( getPresetValueFromControlValue( 2, 'slider', presets ) ).toBe(
250
+ 'var:preset|border-radius|md'
251
+ );
252
+ } );
253
+ } );
@@ -234,6 +234,7 @@ export function getPresetValueFromControlValue(
234
234
  } else if ( size === 0 ) {
235
235
  return '0';
236
236
  }
237
+
237
238
  return `var:preset|border-radius|${ presets[ controlValue ]?.slug }`;
238
239
  }
239
240
 
@@ -147,15 +147,16 @@ export default function BorderPanel( {
147
147
  const showBorderRadius = useHasBorderRadiusControl( settings );
148
148
  const borderRadiusValues = useMemo( () => {
149
149
  if ( typeof border?.radius !== 'object' ) {
150
- return decodeValue( border?.radius );
150
+ return border?.radius;
151
151
  }
152
+
152
153
  return {
153
- topLeft: decodeValue( border?.radius?.topLeft ),
154
- topRight: decodeValue( border?.radius?.topRight ),
155
- bottomLeft: decodeValue( border?.radius?.bottomLeft ),
156
- bottomRight: decodeValue( border?.radius?.bottomRight ),
154
+ topLeft: border?.radius?.topLeft,
155
+ topRight: border?.radius?.topRight,
156
+ bottomLeft: border?.radius?.bottomLeft,
157
+ bottomRight: border?.radius?.bottomRight,
157
158
  };
158
- }, [ border?.radius, decodeValue ] );
159
+ }, [ border?.radius ] );
159
160
  const setBorderRadius = ( newBorderRadius ) =>
160
161
  setBorder( { ...border, radius: newBorderRadius } );
161
162
  const hasBorderRadius = () => {
@@ -2,7 +2,12 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
- import { useRef, useEffect, useState } from '@wordpress/element';
5
+ import {
6
+ useRef,
7
+ useEffect,
8
+ useState,
9
+ createInterpolateElement,
10
+ } from '@wordpress/element';
6
11
  import { focus } from '@wordpress/dom';
7
12
  import {
8
13
  ToolbarButton,
@@ -12,6 +17,7 @@ import {
12
17
  ToggleControl,
13
18
  TextControl,
14
19
  __experimentalVStack as VStack,
20
+ ExternalLink,
15
21
  } from '@wordpress/components';
16
22
  import {
17
23
  Icon,
@@ -230,9 +236,19 @@ const ImageURLInputUI = ( {
230
236
  <TextControl
231
237
  __next40pxDefaultSize
232
238
  __nextHasNoMarginBottom
233
- label={ __( 'Link rel' ) }
239
+ label={ __( 'Link relation' ) }
234
240
  value={ rel ?? '' }
235
241
  onChange={ onSetLinkRel }
242
+ help={ createInterpolateElement(
243
+ __(
244
+ 'The <a>Link Relation</a> attribute defines the relationship between a linked resource and the current document.'
245
+ ),
246
+ {
247
+ a: (
248
+ <ExternalLink href="https://developer.mozilla.org/docs/Web/HTML/Attributes/rel" />
249
+ ),
250
+ }
251
+ ) }
236
252
  />
237
253
  <TextControl
238
254
  __next40pxDefaultSize
@@ -137,6 +137,7 @@ export default function useClipboardHandler() {
137
137
  const {
138
138
  __experimentalCanUserUseUnfilteredHTML:
139
139
  canUserUseUnfilteredHTML,
140
+ mediaUpload,
140
141
  } = getSettings();
141
142
  const isInternal =
142
143
  event.clipboardData.getData( 'rich-text' ) === 'true';
@@ -148,6 +149,11 @@ export default function useClipboardHandler() {
148
149
  let blocks = [];
149
150
 
150
151
  if ( files.length ) {
152
+ if ( ! mediaUpload ) {
153
+ event.preventDefault();
154
+ return;
155
+ }
156
+
151
157
  const fromTransforms = getBlockTransforms( 'from' );
152
158
  blocks = files
153
159
  .reduce( ( accumulator, file ) => {
@@ -519,8 +519,9 @@ export function isSectionBlock( state, clientId ) {
519
519
  }
520
520
 
521
521
  const attributes = getBlockAttributes( state, clientId );
522
+ const isTemplatePart = blockName === 'core/template-part';
522
523
  if (
523
- attributes?.metadata?.patternName &&
524
+ ( attributes?.metadata?.patternName || isTemplatePart ) &&
524
525
  !! window?.__experimentalContentOnlyPatternInsertion
525
526
  ) {
526
527
  return true;
@@ -528,7 +529,7 @@ export function isSectionBlock( state, clientId ) {
528
529
 
529
530
  // Template parts become sections in navigation mode.
530
531
  const _isNavigationMode = isNavigationMode( state );
531
- if ( _isNavigationMode && blockName === 'core/template-part' ) {
532
+ if ( _isNavigationMode && isTemplatePart ) {
532
533
  return true;
533
534
  }
534
535