@wordpress/block-editor 15.16.1-next.v.202604091042.0 → 15.17.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.
- package/CHANGELOG.md +2 -0
- package/build/components/copy-handler/index.cjs.map +2 -2
- package/build/components/link-control/link-preview.cjs +3 -1
- package/build/components/link-control/link-preview.cjs.map +2 -2
- package/build/components/preset-input-control/index.cjs +7 -4
- package/build/components/preset-input-control/index.cjs.map +2 -2
- package/build/components/rich-text/event-listeners/index.cjs.map +2 -2
- package/build/components/spacing-sizes-control/utils.cjs +1 -1
- package/build/components/spacing-sizes-control/utils.cjs.map +2 -2
- package/build/components/writing-flow/use-selection-observer.cjs +23 -1
- package/build/components/writing-flow/use-selection-observer.cjs.map +2 -2
- package/build/hooks/style.cjs +54 -52
- package/build/hooks/style.cjs.map +2 -2
- package/build-module/components/copy-handler/index.mjs.map +2 -2
- package/build-module/components/link-control/link-preview.mjs +3 -1
- package/build-module/components/link-control/link-preview.mjs.map +2 -2
- package/build-module/components/preset-input-control/index.mjs +7 -4
- package/build-module/components/preset-input-control/index.mjs.map +2 -2
- package/build-module/components/rich-text/event-listeners/index.mjs.map +2 -2
- package/build-module/components/spacing-sizes-control/utils.mjs +1 -1
- package/build-module/components/spacing-sizes-control/utils.mjs.map +2 -2
- package/build-module/components/writing-flow/use-selection-observer.mjs +23 -1
- package/build-module/components/writing-flow/use-selection-observer.mjs.map +2 -2
- package/build-module/hooks/style.mjs +54 -52
- package/build-module/hooks/style.mjs.map +2 -2
- package/package.json +38 -38
- package/src/components/copy-handler/index.js +1 -0
- package/src/components/link-control/link-preview.js +3 -1
- package/src/components/preset-input-control/index.js +10 -4
- package/src/components/preset-input-control/test/index.js +70 -0
- package/src/components/rich-text/event-listeners/index.js +1 -0
- package/src/components/spacing-sizes-control/utils.js +1 -1
- package/src/components/writing-flow/use-selection-observer.js +39 -1
- package/src/hooks/style.js +75 -61
|
@@ -187,68 +187,70 @@ var elementTypes = [
|
|
|
187
187
|
}
|
|
188
188
|
];
|
|
189
189
|
var STYLE_BLOCK_PROPS_REFERENCE = {};
|
|
190
|
-
function
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
190
|
+
function getElementCSSRules(blockElementStyles, blockName, baseSelector) {
|
|
191
|
+
if (!blockElementStyles) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const rules = [];
|
|
195
|
+
elementTypes.forEach(({ elementType, pseudo, elements }) => {
|
|
196
|
+
const skipSerialization = shouldSkipSerialization(
|
|
197
|
+
blockName,
|
|
198
|
+
COLOR_SUPPORT_KEY,
|
|
199
|
+
elementType
|
|
200
|
+
);
|
|
201
|
+
if (skipSerialization) {
|
|
199
202
|
return;
|
|
200
203
|
}
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
elementType
|
|
204
|
+
const elementStyles = blockElementStyles?.[elementType];
|
|
205
|
+
if (elementStyles) {
|
|
206
|
+
const selector = scopeSelector(
|
|
207
|
+
baseSelector,
|
|
208
|
+
ELEMENTS[elementType]
|
|
207
209
|
);
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
baseElementSelector,
|
|
215
|
-
ELEMENTS[elementType]
|
|
216
|
-
);
|
|
217
|
-
elementCSSRules.push(
|
|
218
|
-
compileCSS(elementStyles, { selector })
|
|
219
|
-
);
|
|
220
|
-
if (pseudo) {
|
|
221
|
-
pseudo.forEach((pseudoSelector) => {
|
|
222
|
-
if (elementStyles[pseudoSelector]) {
|
|
223
|
-
elementCSSRules.push(
|
|
224
|
-
compileCSS(elementStyles[pseudoSelector], {
|
|
225
|
-
selector: scopeSelector(
|
|
226
|
-
baseElementSelector,
|
|
227
|
-
`${ELEMENTS[elementType]}${pseudoSelector}`
|
|
228
|
-
)
|
|
229
|
-
})
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (elements) {
|
|
236
|
-
elements.forEach((element) => {
|
|
237
|
-
if (blockElementStyles[element]) {
|
|
238
|
-
elementCSSRules.push(
|
|
239
|
-
compileCSS(blockElementStyles[element], {
|
|
210
|
+
rules.push(compileCSS(elementStyles, { selector }));
|
|
211
|
+
if (pseudo) {
|
|
212
|
+
pseudo.forEach((pseudoSelector) => {
|
|
213
|
+
if (elementStyles[pseudoSelector]) {
|
|
214
|
+
rules.push(
|
|
215
|
+
compileCSS(elementStyles[pseudoSelector], {
|
|
240
216
|
selector: scopeSelector(
|
|
241
|
-
|
|
242
|
-
ELEMENTS[
|
|
217
|
+
baseSelector,
|
|
218
|
+
`${ELEMENTS[elementType]}${pseudoSelector}`
|
|
243
219
|
)
|
|
244
220
|
})
|
|
245
221
|
);
|
|
246
222
|
}
|
|
247
223
|
});
|
|
248
224
|
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
225
|
+
}
|
|
226
|
+
if (elements) {
|
|
227
|
+
elements.forEach((element) => {
|
|
228
|
+
if (blockElementStyles[element]) {
|
|
229
|
+
rules.push(
|
|
230
|
+
compileCSS(blockElementStyles[element], {
|
|
231
|
+
selector: scopeSelector(
|
|
232
|
+
baseSelector,
|
|
233
|
+
ELEMENTS[element]
|
|
234
|
+
)
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
return rules.length > 0 ? rules.join("") : void 0;
|
|
242
|
+
}
|
|
243
|
+
function useBlockProps({ name, style }) {
|
|
244
|
+
const blockElementsContainerIdentifier = useInstanceId(
|
|
245
|
+
STYLE_BLOCK_PROPS_REFERENCE,
|
|
246
|
+
"wp-elements"
|
|
247
|
+
);
|
|
248
|
+
const baseElementSelector = `.${blockElementsContainerIdentifier}`;
|
|
249
|
+
const blockElementStyles = style?.elements;
|
|
250
|
+
const styles = useMemo(
|
|
251
|
+
() => getElementCSSRules(blockElementStyles, name, baseElementSelector),
|
|
252
|
+
[baseElementSelector, blockElementStyles, name]
|
|
253
|
+
);
|
|
252
254
|
useStyleOverride({ css: styles });
|
|
253
255
|
return addSaveProps(
|
|
254
256
|
{ className: blockElementsContainerIdentifier },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/style.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { addFilter } from '@wordpress/hooks';\nimport {\n\tgetBlockSupport,\n\thasBlockSupport,\n\t__EXPERIMENTAL_ELEMENTS as ELEMENTS,\n} from '@wordpress/blocks';\nimport { useInstanceId } from '@wordpress/compose';\nimport { getCSSRules, compileCSS } from '@wordpress/style-engine';\n\n/**\n * Internal dependencies\n */\nimport { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background';\nimport { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border';\nimport { COLOR_SUPPORT_KEY, ColorEdit } from './color';\nimport {\n\tTypographyPanel,\n\tTYPOGRAPHY_SUPPORT_KEY,\n\tTYPOGRAPHY_SUPPORT_KEYS,\n} from './typography';\nimport {\n\tDIMENSIONS_SUPPORT_KEY,\n\tSPACING_SUPPORT_KEY,\n\tDimensionsPanel,\n} from './dimensions';\nimport {\n\tshouldSkipSerialization,\n\tuseStyleOverride,\n\tuseBlockSettings,\n} from './utils';\nimport { scopeSelector } from '../components/global-styles/utils';\nimport { useBlockEditingMode } from '../components/block-editing-mode';\n\nconst styleSupportKeys = [\n\t...TYPOGRAPHY_SUPPORT_KEYS,\n\tBORDER_SUPPORT_KEY,\n\tCOLOR_SUPPORT_KEY,\n\tDIMENSIONS_SUPPORT_KEY,\n\tBACKGROUND_SUPPORT_KEY,\n\tSPACING_SUPPORT_KEY,\n\tSHADOW_SUPPORT_KEY,\n];\n\nconst hasStyleSupport = ( nameOrType ) =>\n\tstyleSupportKeys.some( ( key ) => hasBlockSupport( nameOrType, key ) );\n\n/**\n * Returns the inline styles to add depending on the style object\n *\n * @param {Object} styles Styles configuration.\n *\n * @return {Object} Flattened CSS variables declaration.\n */\nexport function getInlineStyles( styles = {} ) {\n\tconst output = {};\n\t// The goal is to move everything to server side generated engine styles\n\t// This is temporary as we absorb more and more styles into the engine.\n\tgetCSSRules( styles ).forEach( ( rule ) => {\n\t\toutput[ rule.key ] = rule.value;\n\t} );\n\n\treturn output;\n}\n\n/**\n * Filters registered block settings, extending attributes to include `style` attribute.\n *\n * @param {Object} settings Original block settings.\n *\n * @return {Object} Filtered block settings.\n */\nfunction addAttribute( settings ) {\n\tif (\n\t\t! hasStyleSupport( settings ) &&\n\t\t! hasBlockSupport( settings, 'customCSS', true )\n\t) {\n\t\treturn settings;\n\t}\n\n\t// Allow blocks to specify their own attribute definition with default values if needed.\n\tif ( ! settings.attributes.style ) {\n\t\tObject.assign( settings.attributes, {\n\t\t\tstyle: {\n\t\t\t\ttype: 'object',\n\t\t\t},\n\t\t} );\n\t}\n\n\treturn settings;\n}\n\n/**\n * A dictionary of paths to flag skipping block support serialization as the key,\n * with values providing the style paths to be omitted from serialization.\n *\n * @constant\n * @type {Record<string, string[]>}\n */\nconst skipSerializationPathsEdit = {\n\t[ `${ BORDER_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ 'border' ],\n\t[ `${ COLOR_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tCOLOR_SUPPORT_KEY,\n\t],\n\t[ `${ TYPOGRAPHY_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tTYPOGRAPHY_SUPPORT_KEY,\n\t],\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tDIMENSIONS_SUPPORT_KEY,\n\t],\n\t[ `${ SPACING_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tSPACING_SUPPORT_KEY,\n\t],\n\t[ `${ SHADOW_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tSHADOW_SUPPORT_KEY,\n\t],\n};\n\n/**\n * A dictionary of paths to flag skipping block support serialization as the key,\n * with values providing the style paths to be omitted from serialization.\n *\n * Extends the Edit skip paths to enable skipping additional paths in just\n * the Save component. This allows a block support to be serialized within the\n * editor, while using an alternate approach, such as server-side rendering, when\n * the support is saved.\n *\n * @constant\n * @type {Record<string, string[]>}\n */\nconst skipSerializationPathsSave = {\n\t...skipSerializationPathsEdit,\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.aspectRatio` ]: [\n\t\t`${ DIMENSIONS_SUPPORT_KEY }.aspectRatio`,\n\t], // Skip serialization of aspect ratio in save mode.\n\t[ `${ BACKGROUND_SUPPORT_KEY }` ]: [ BACKGROUND_SUPPORT_KEY ], // Skip serialization of background support in save mode.\n};\n\nconst skipSerializationPathsSaveChecks = {\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.aspectRatio` ]: true,\n\t[ `${ BACKGROUND_SUPPORT_KEY }` ]: true,\n};\n\n/**\n * A dictionary used to normalize feature names between support flags, style\n * object properties and __experimentSkipSerialization configuration arrays.\n *\n * This allows not having to provide a migration for a support flag and possible\n * backwards compatibility bridges, while still achieving consistency between\n * the support flag and the skip serialization array.\n *\n * @constant\n * @type {Record<string, string>}\n */\nconst renamedFeatures = { gradients: 'gradient' };\n\n/**\n * A utility function used to remove one or more paths from a style object.\n * Works in a way similar to Lodash's `omit()`. See unit tests and examples below.\n *\n * It supports a single string path:\n *\n * ```\n * omitStyle( { color: 'red' }, 'color' ); // {}\n * ```\n *\n * or an array of paths:\n *\n * ```\n * omitStyle( { color: 'red', background: '#fff' }, [ 'color', 'background' ] ); // {}\n * ```\n *\n * It also allows you to specify paths at multiple levels in a string.\n *\n * ```\n * omitStyle( { typography: { textDecoration: 'underline' } }, 'typography.textDecoration' ); // {}\n * ```\n *\n * You can remove multiple paths at the same time:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\ttypography: {\n * \t\t\t\ttextDecoration: 'underline',\n * \t\t\t\ttextTransform: 'uppercase',\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t'typography.textDecoration',\n * \t\t\t'typography.textTransform',\n *\t\t]\n * );\n * // {}\n * ```\n *\n * You can also specify nested paths as arrays:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\ttypography: {\n * \t\t\t\ttextDecoration: 'underline',\n * \t\t\t\ttextTransform: 'uppercase',\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t[ 'typography', 'textDecoration' ],\n * \t\t\t[ 'typography', 'textTransform' ],\n *\t\t]\n * );\n * // {}\n * ```\n *\n * With regards to nesting of styles, infinite depth is supported:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\tborder: {\n * \t\t\t\tradius: {\n * \t\t\t\t\ttopLeft: '10px',\n * \t\t\t\t\ttopRight: '0.5rem',\n * \t\t\t\t}\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t[ 'border', 'radius', 'topRight' ],\n *\t\t]\n * );\n * // { border: { radius: { topLeft: '10px' } } }\n * ```\n *\n * The third argument, `preserveReference`, defines how to treat the input style object.\n * It is mostly necessary to properly handle mutation when recursively handling the style object.\n * Defaulting to `false`, this will always create a new object, avoiding to mutate `style`.\n * However, when recursing, we change that value to `true` in order to work with a single copy\n * of the original style object.\n *\n * @see https://lodash.com/docs/4.17.15#omit\n *\n * @param {Object} style Styles object.\n * @param {Array|string} paths Paths to remove.\n * @param {boolean} preserveReference True to mutate the `style` object, false otherwise.\n * @return {Object} Styles object with the specified paths removed.\n */\nexport function omitStyle( style, paths, preserveReference = false ) {\n\tif ( ! style ) {\n\t\treturn style;\n\t}\n\n\tlet newStyle = style;\n\tif ( ! preserveReference ) {\n\t\tnewStyle = JSON.parse( JSON.stringify( style ) );\n\t}\n\n\tif ( ! Array.isArray( paths ) ) {\n\t\tpaths = [ paths ];\n\t}\n\n\tpaths.forEach( ( path ) => {\n\t\tif ( ! Array.isArray( path ) ) {\n\t\t\tpath = path.split( '.' );\n\t\t}\n\n\t\tif ( path.length > 1 ) {\n\t\t\tconst [ firstSubpath, ...restPath ] = path;\n\t\t\tomitStyle( newStyle[ firstSubpath ], [ restPath ], true );\n\t\t} else if ( path.length === 1 ) {\n\t\t\tdelete newStyle[ path[ 0 ] ];\n\t\t}\n\t} );\n\n\treturn newStyle;\n}\n\n/**\n * Override props assigned to save component to inject the CSS variables definition.\n *\n * @param {Object} props Additional props applied to save element.\n * @param {Object|string} blockNameOrType Block type.\n * @param {Object} attributes Block attributes.\n * @param {?Record<string, string[]>} skipPaths An object of keys and paths to skip serialization.\n *\n * @return {Object} Filtered props applied to save element.\n */\nexport function addSaveProps(\n\tprops,\n\tblockNameOrType,\n\tattributes,\n\tskipPaths = skipSerializationPathsSave\n) {\n\tif ( ! hasStyleSupport( blockNameOrType ) ) {\n\t\treturn props;\n\t}\n\n\tlet { style } = attributes;\n\tObject.entries( skipPaths ).forEach( ( [ indicator, path ] ) => {\n\t\tconst skipSerialization =\n\t\t\tskipSerializationPathsSaveChecks[ indicator ] ||\n\t\t\tgetBlockSupport( blockNameOrType, indicator );\n\n\t\tif ( skipSerialization === true ) {\n\t\t\tstyle = omitStyle( style, path );\n\t\t}\n\n\t\tif ( Array.isArray( skipSerialization ) ) {\n\t\t\tskipSerialization.forEach( ( featureName ) => {\n\t\t\t\tconst feature = renamedFeatures[ featureName ] || featureName;\n\t\t\t\tstyle = omitStyle( style, [ [ ...path, feature ] ] );\n\t\t\t} );\n\t\t}\n\t} );\n\n\tprops.style = {\n\t\t...getInlineStyles( style ),\n\t\t...props.style,\n\t};\n\n\treturn props;\n}\n\nfunction BlockStyleControls( {\n\tclientId,\n\tname,\n\tsetAttributes,\n\t__unstableParentLayout,\n} ) {\n\tconst settings = useBlockSettings( name, __unstableParentLayout );\n\tconst blockEditingMode = useBlockEditingMode();\n\tconst passedProps = {\n\t\tclientId,\n\t\tname,\n\t\tsetAttributes,\n\t\tsettings: {\n\t\t\t...settings,\n\t\t\ttypography: {\n\t\t\t\t...settings.typography,\n\t\t\t\t// The text alignment UI for individual blocks is rendered in\n\t\t\t\t// the block toolbar, so disable it here.\n\t\t\t\ttextAlign: false,\n\t\t\t},\n\t\t},\n\t};\n\tif ( blockEditingMode !== 'default' ) {\n\t\treturn null;\n\t}\n\treturn (\n\t\t<>\n\t\t\t<ColorEdit { ...passedProps } />\n\t\t\t<BackgroundImagePanel { ...passedProps } />\n\t\t\t<TypographyPanel { ...passedProps } />\n\t\t\t<BorderPanel { ...passedProps } />\n\t\t\t<DimensionsPanel { ...passedProps } />\n\t\t</>\n\t);\n}\n\nexport default {\n\tedit: BlockStyleControls,\n\thasSupport: hasStyleSupport,\n\taddSaveProps,\n\tattributeKeys: [ 'style' ],\n\tuseBlockProps,\n};\n\n// Defines which element types are supported, including their hover styles or\n// any other elements that have been included under a single element type\n// e.g. heading and h1-h6.\nconst elementTypes = [\n\t{ elementType: 'button' },\n\t{ elementType: 'link', pseudo: [ ':hover' ] },\n\t{\n\t\telementType: 'heading',\n\t\telements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ],\n\t},\n];\n\n// Used for generating the instance ID\nconst STYLE_BLOCK_PROPS_REFERENCE = {};\n\nfunction useBlockProps( { name, style } ) {\n\tconst blockElementsContainerIdentifier = useInstanceId(\n\t\tSTYLE_BLOCK_PROPS_REFERENCE,\n\t\t'wp-elements'\n\t);\n\n\tconst baseElementSelector = `.${ blockElementsContainerIdentifier }`;\n\tconst blockElementStyles = style?.elements;\n\n\tconst styles = useMemo( () => {\n\t\tif ( ! blockElementStyles ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst elementCSSRules = [];\n\n\t\telementTypes.forEach( ( { elementType, pseudo, elements } ) => {\n\t\t\tconst skipSerialization = shouldSkipSerialization(\n\t\t\t\tname,\n\t\t\t\tCOLOR_SUPPORT_KEY,\n\t\t\t\telementType\n\t\t\t);\n\n\t\t\tif ( skipSerialization ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst elementStyles = blockElementStyles?.[ elementType ];\n\n\t\t\t// Process primary element type styles.\n\t\t\tif ( elementStyles ) {\n\t\t\t\tconst selector = scopeSelector(\n\t\t\t\t\tbaseElementSelector,\n\t\t\t\t\tELEMENTS[ elementType ]\n\t\t\t\t);\n\n\t\t\t\telementCSSRules.push(\n\t\t\t\t\tcompileCSS( elementStyles, { selector } )\n\t\t\t\t);\n\n\t\t\t\t// Process any interactive states for the element type.\n\t\t\t\tif ( pseudo ) {\n\t\t\t\t\tpseudo.forEach( ( pseudoSelector ) => {\n\t\t\t\t\t\tif ( elementStyles[ pseudoSelector ] ) {\n\t\t\t\t\t\t\telementCSSRules.push(\n\t\t\t\t\t\t\t\tcompileCSS( elementStyles[ pseudoSelector ], {\n\t\t\t\t\t\t\t\t\tselector: scopeSelector(\n\t\t\t\t\t\t\t\t\t\tbaseElementSelector,\n\t\t\t\t\t\t\t\t\t\t`${ ELEMENTS[ elementType ] }${ pseudoSelector }`\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Process related elements e.g. h1-h6 for headings\n\t\t\tif ( elements ) {\n\t\t\t\telements.forEach( ( element ) => {\n\t\t\t\t\tif ( blockElementStyles[ element ] ) {\n\t\t\t\t\t\telementCSSRules.push(\n\t\t\t\t\t\t\tcompileCSS( blockElementStyles[ element ], {\n\t\t\t\t\t\t\t\tselector: scopeSelector(\n\t\t\t\t\t\t\t\t\tbaseElementSelector,\n\t\t\t\t\t\t\t\t\tELEMENTS[ element ]\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\treturn elementCSSRules.length > 0\n\t\t\t? elementCSSRules.join( '' )\n\t\t\t: undefined;\n\t}, [ baseElementSelector, blockElementStyles, name ] );\n\n\tuseStyleOverride( { css: styles } );\n\n\treturn addSaveProps(\n\t\t{ className: blockElementsContainerIdentifier },\n\t\tname,\n\t\t{ style },\n\t\tskipSerializationPathsEdit\n\t);\n}\n\naddFilter(\n\t'blocks.registerBlockType',\n\t'core/style/addAttribute',\n\taddAttribute\n);\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { addFilter } from '@wordpress/hooks';\nimport {\n\tgetBlockSupport,\n\thasBlockSupport,\n\t__EXPERIMENTAL_ELEMENTS as ELEMENTS,\n} from '@wordpress/blocks';\nimport { useInstanceId } from '@wordpress/compose';\nimport { getCSSRules, compileCSS } from '@wordpress/style-engine';\n\n/**\n * Internal dependencies\n */\nimport { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from './background';\nimport { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from './border';\nimport { COLOR_SUPPORT_KEY, ColorEdit } from './color';\nimport {\n\tTypographyPanel,\n\tTYPOGRAPHY_SUPPORT_KEY,\n\tTYPOGRAPHY_SUPPORT_KEYS,\n} from './typography';\nimport {\n\tDIMENSIONS_SUPPORT_KEY,\n\tSPACING_SUPPORT_KEY,\n\tDimensionsPanel,\n} from './dimensions';\nimport {\n\tshouldSkipSerialization,\n\tuseStyleOverride,\n\tuseBlockSettings,\n} from './utils';\nimport { scopeSelector } from '../components/global-styles/utils';\nimport { useBlockEditingMode } from '../components/block-editing-mode';\n\nconst styleSupportKeys = [\n\t...TYPOGRAPHY_SUPPORT_KEYS,\n\tBORDER_SUPPORT_KEY,\n\tCOLOR_SUPPORT_KEY,\n\tDIMENSIONS_SUPPORT_KEY,\n\tBACKGROUND_SUPPORT_KEY,\n\tSPACING_SUPPORT_KEY,\n\tSHADOW_SUPPORT_KEY,\n];\n\nconst hasStyleSupport = ( nameOrType ) =>\n\tstyleSupportKeys.some( ( key ) => hasBlockSupport( nameOrType, key ) );\n\n/**\n * Returns the inline styles to add depending on the style object\n *\n * @param {Object} styles Styles configuration.\n *\n * @return {Object} Flattened CSS variables declaration.\n */\nexport function getInlineStyles( styles = {} ) {\n\tconst output = {};\n\t// The goal is to move everything to server side generated engine styles\n\t// This is temporary as we absorb more and more styles into the engine.\n\tgetCSSRules( styles ).forEach( ( rule ) => {\n\t\toutput[ rule.key ] = rule.value;\n\t} );\n\n\treturn output;\n}\n\n/**\n * Filters registered block settings, extending attributes to include `style` attribute.\n *\n * @param {Object} settings Original block settings.\n *\n * @return {Object} Filtered block settings.\n */\nfunction addAttribute( settings ) {\n\tif (\n\t\t! hasStyleSupport( settings ) &&\n\t\t! hasBlockSupport( settings, 'customCSS', true )\n\t) {\n\t\treturn settings;\n\t}\n\n\t// Allow blocks to specify their own attribute definition with default values if needed.\n\tif ( ! settings.attributes.style ) {\n\t\tObject.assign( settings.attributes, {\n\t\t\tstyle: {\n\t\t\t\ttype: 'object',\n\t\t\t},\n\t\t} );\n\t}\n\n\treturn settings;\n}\n\n/**\n * A dictionary of paths to flag skipping block support serialization as the key,\n * with values providing the style paths to be omitted from serialization.\n *\n * @constant\n * @type {Record<string, string[]>}\n */\nconst skipSerializationPathsEdit = {\n\t[ `${ BORDER_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [ 'border' ],\n\t[ `${ COLOR_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tCOLOR_SUPPORT_KEY,\n\t],\n\t[ `${ TYPOGRAPHY_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tTYPOGRAPHY_SUPPORT_KEY,\n\t],\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tDIMENSIONS_SUPPORT_KEY,\n\t],\n\t[ `${ SPACING_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tSPACING_SUPPORT_KEY,\n\t],\n\t[ `${ SHADOW_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [\n\t\tSHADOW_SUPPORT_KEY,\n\t],\n};\n\n/**\n * A dictionary of paths to flag skipping block support serialization as the key,\n * with values providing the style paths to be omitted from serialization.\n *\n * Extends the Edit skip paths to enable skipping additional paths in just\n * the Save component. This allows a block support to be serialized within the\n * editor, while using an alternate approach, such as server-side rendering, when\n * the support is saved.\n *\n * @constant\n * @type {Record<string, string[]>}\n */\nconst skipSerializationPathsSave = {\n\t...skipSerializationPathsEdit,\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.aspectRatio` ]: [\n\t\t`${ DIMENSIONS_SUPPORT_KEY }.aspectRatio`,\n\t], // Skip serialization of aspect ratio in save mode.\n\t[ `${ BACKGROUND_SUPPORT_KEY }` ]: [ BACKGROUND_SUPPORT_KEY ], // Skip serialization of background support in save mode.\n};\n\nconst skipSerializationPathsSaveChecks = {\n\t[ `${ DIMENSIONS_SUPPORT_KEY }.aspectRatio` ]: true,\n\t[ `${ BACKGROUND_SUPPORT_KEY }` ]: true,\n};\n\n/**\n * A dictionary used to normalize feature names between support flags, style\n * object properties and __experimentSkipSerialization configuration arrays.\n *\n * This allows not having to provide a migration for a support flag and possible\n * backwards compatibility bridges, while still achieving consistency between\n * the support flag and the skip serialization array.\n *\n * @constant\n * @type {Record<string, string>}\n */\nconst renamedFeatures = { gradients: 'gradient' };\n\n/**\n * A utility function used to remove one or more paths from a style object.\n * Works in a way similar to Lodash's `omit()`. See unit tests and examples below.\n *\n * It supports a single string path:\n *\n * ```\n * omitStyle( { color: 'red' }, 'color' ); // {}\n * ```\n *\n * or an array of paths:\n *\n * ```\n * omitStyle( { color: 'red', background: '#fff' }, [ 'color', 'background' ] ); // {}\n * ```\n *\n * It also allows you to specify paths at multiple levels in a string.\n *\n * ```\n * omitStyle( { typography: { textDecoration: 'underline' } }, 'typography.textDecoration' ); // {}\n * ```\n *\n * You can remove multiple paths at the same time:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\ttypography: {\n * \t\t\t\ttextDecoration: 'underline',\n * \t\t\t\ttextTransform: 'uppercase',\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t'typography.textDecoration',\n * \t\t\t'typography.textTransform',\n *\t\t]\n * );\n * // {}\n * ```\n *\n * You can also specify nested paths as arrays:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\ttypography: {\n * \t\t\t\ttextDecoration: 'underline',\n * \t\t\t\ttextTransform: 'uppercase',\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t[ 'typography', 'textDecoration' ],\n * \t\t\t[ 'typography', 'textTransform' ],\n *\t\t]\n * );\n * // {}\n * ```\n *\n * With regards to nesting of styles, infinite depth is supported:\n *\n * ```\n * omitStyle(\n * \t\t{\n * \t\t\tborder: {\n * \t\t\t\tradius: {\n * \t\t\t\t\ttopLeft: '10px',\n * \t\t\t\t\ttopRight: '0.5rem',\n * \t\t\t\t}\n * \t\t\t}\n *\t\t},\n *\t\t[\n * \t\t\t[ 'border', 'radius', 'topRight' ],\n *\t\t]\n * );\n * // { border: { radius: { topLeft: '10px' } } }\n * ```\n *\n * The third argument, `preserveReference`, defines how to treat the input style object.\n * It is mostly necessary to properly handle mutation when recursively handling the style object.\n * Defaulting to `false`, this will always create a new object, avoiding to mutate `style`.\n * However, when recursing, we change that value to `true` in order to work with a single copy\n * of the original style object.\n *\n * @see https://lodash.com/docs/4.17.15#omit\n *\n * @param {Object} style Styles object.\n * @param {Array|string} paths Paths to remove.\n * @param {boolean} preserveReference True to mutate the `style` object, false otherwise.\n * @return {Object} Styles object with the specified paths removed.\n */\nexport function omitStyle( style, paths, preserveReference = false ) {\n\tif ( ! style ) {\n\t\treturn style;\n\t}\n\n\tlet newStyle = style;\n\tif ( ! preserveReference ) {\n\t\tnewStyle = JSON.parse( JSON.stringify( style ) );\n\t}\n\n\tif ( ! Array.isArray( paths ) ) {\n\t\tpaths = [ paths ];\n\t}\n\n\tpaths.forEach( ( path ) => {\n\t\tif ( ! Array.isArray( path ) ) {\n\t\t\tpath = path.split( '.' );\n\t\t}\n\n\t\tif ( path.length > 1 ) {\n\t\t\tconst [ firstSubpath, ...restPath ] = path;\n\t\t\tomitStyle( newStyle[ firstSubpath ], [ restPath ], true );\n\t\t} else if ( path.length === 1 ) {\n\t\t\tdelete newStyle[ path[ 0 ] ];\n\t\t}\n\t} );\n\n\treturn newStyle;\n}\n\n/**\n * Override props assigned to save component to inject the CSS variables definition.\n *\n * @param {Object} props Additional props applied to save element.\n * @param {Object|string} blockNameOrType Block type.\n * @param {Object} attributes Block attributes.\n * @param {?Record<string, string[]>} skipPaths An object of keys and paths to skip serialization.\n *\n * @return {Object} Filtered props applied to save element.\n */\nexport function addSaveProps(\n\tprops,\n\tblockNameOrType,\n\tattributes,\n\tskipPaths = skipSerializationPathsSave\n) {\n\tif ( ! hasStyleSupport( blockNameOrType ) ) {\n\t\treturn props;\n\t}\n\n\tlet { style } = attributes;\n\tObject.entries( skipPaths ).forEach( ( [ indicator, path ] ) => {\n\t\tconst skipSerialization =\n\t\t\tskipSerializationPathsSaveChecks[ indicator ] ||\n\t\t\tgetBlockSupport( blockNameOrType, indicator );\n\n\t\tif ( skipSerialization === true ) {\n\t\t\tstyle = omitStyle( style, path );\n\t\t}\n\n\t\tif ( Array.isArray( skipSerialization ) ) {\n\t\t\tskipSerialization.forEach( ( featureName ) => {\n\t\t\t\tconst feature = renamedFeatures[ featureName ] || featureName;\n\t\t\t\tstyle = omitStyle( style, [ [ ...path, feature ] ] );\n\t\t\t} );\n\t\t}\n\t} );\n\n\tprops.style = {\n\t\t...getInlineStyles( style ),\n\t\t...props.style,\n\t};\n\n\treturn props;\n}\n\nfunction BlockStyleControls( {\n\tclientId,\n\tname,\n\tsetAttributes,\n\t__unstableParentLayout,\n} ) {\n\tconst settings = useBlockSettings( name, __unstableParentLayout );\n\tconst blockEditingMode = useBlockEditingMode();\n\tconst passedProps = {\n\t\tclientId,\n\t\tname,\n\t\tsetAttributes,\n\t\tsettings: {\n\t\t\t...settings,\n\t\t\ttypography: {\n\t\t\t\t...settings.typography,\n\t\t\t\t// The text alignment UI for individual blocks is rendered in\n\t\t\t\t// the block toolbar, so disable it here.\n\t\t\t\ttextAlign: false,\n\t\t\t},\n\t\t},\n\t};\n\tif ( blockEditingMode !== 'default' ) {\n\t\treturn null;\n\t}\n\treturn (\n\t\t<>\n\t\t\t<ColorEdit { ...passedProps } />\n\t\t\t<BackgroundImagePanel { ...passedProps } />\n\t\t\t<TypographyPanel { ...passedProps } />\n\t\t\t<BorderPanel { ...passedProps } />\n\t\t\t<DimensionsPanel { ...passedProps } />\n\t\t</>\n\t);\n}\n\nexport default {\n\tedit: BlockStyleControls,\n\thasSupport: hasStyleSupport,\n\taddSaveProps,\n\tattributeKeys: [ 'style' ],\n\tuseBlockProps,\n};\n\n// Defines which element types are supported, including their hover styles or\n// any other elements that have been included under a single element type\n// e.g. heading and h1-h6.\nconst elementTypes = [\n\t{ elementType: 'button' },\n\t{ elementType: 'link', pseudo: [ ':hover' ] },\n\t{\n\t\telementType: 'heading',\n\t\telements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ],\n\t},\n];\n\n// Used for generating the instance ID\nconst STYLE_BLOCK_PROPS_REFERENCE = {};\n\n/**\n * Generates CSS rules for block element styles (buttons, links, headings, etc.).\n *\n * Iterates over supported element types and compiles their styles, including\n * pseudo-selectors (e.g. :hover) and related sub-elements (e.g. h1-h6 for headings),\n * into scoped CSS rule strings.\n *\n * @param {Object} blockElementStyles The block's `style.elements` object.\n * @param {string} blockName The block name, used for skip-serialization checks.\n * @param {string} baseSelector The base CSS selector to scope rules under.\n * @return {string|undefined} Concatenated CSS rules string, or undefined if none.\n */\nfunction getElementCSSRules( blockElementStyles, blockName, baseSelector ) {\n\tif ( ! blockElementStyles ) {\n\t\treturn;\n\t}\n\n\tconst rules = [];\n\n\telementTypes.forEach( ( { elementType, pseudo, elements } ) => {\n\t\tconst skipSerialization = shouldSkipSerialization(\n\t\t\tblockName,\n\t\t\tCOLOR_SUPPORT_KEY,\n\t\t\telementType\n\t\t);\n\n\t\tif ( skipSerialization ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst elementStyles = blockElementStyles?.[ elementType ];\n\n\t\t// Process primary element type styles.\n\t\tif ( elementStyles ) {\n\t\t\tconst selector = scopeSelector(\n\t\t\t\tbaseSelector,\n\t\t\t\tELEMENTS[ elementType ]\n\t\t\t);\n\n\t\t\trules.push( compileCSS( elementStyles, { selector } ) );\n\n\t\t\t// Process any interactive states for the element type.\n\t\t\tif ( pseudo ) {\n\t\t\t\tpseudo.forEach( ( pseudoSelector ) => {\n\t\t\t\t\tif ( elementStyles[ pseudoSelector ] ) {\n\t\t\t\t\t\trules.push(\n\t\t\t\t\t\t\tcompileCSS( elementStyles[ pseudoSelector ], {\n\t\t\t\t\t\t\t\tselector: scopeSelector(\n\t\t\t\t\t\t\t\t\tbaseSelector,\n\t\t\t\t\t\t\t\t\t`${ ELEMENTS[ elementType ] }${ pseudoSelector }`\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\t// Process related elements e.g. h1-h6 for headings\n\t\tif ( elements ) {\n\t\t\telements.forEach( ( element ) => {\n\t\t\t\tif ( blockElementStyles[ element ] ) {\n\t\t\t\t\trules.push(\n\t\t\t\t\t\tcompileCSS( blockElementStyles[ element ], {\n\t\t\t\t\t\t\tselector: scopeSelector(\n\t\t\t\t\t\t\t\tbaseSelector,\n\t\t\t\t\t\t\t\tELEMENTS[ element ]\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t} )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\n\treturn rules.length > 0 ? rules.join( '' ) : undefined;\n}\n\nfunction useBlockProps( { name, style } ) {\n\tconst blockElementsContainerIdentifier = useInstanceId(\n\t\tSTYLE_BLOCK_PROPS_REFERENCE,\n\t\t'wp-elements'\n\t);\n\n\tconst baseElementSelector = `.${ blockElementsContainerIdentifier }`;\n\tconst blockElementStyles = style?.elements;\n\n\tconst styles = useMemo(\n\t\t() =>\n\t\t\tgetElementCSSRules( blockElementStyles, name, baseElementSelector ),\n\t\t[ baseElementSelector, blockElementStyles, name ]\n\t);\n\n\tuseStyleOverride( { css: styles } );\n\n\treturn addSaveProps(\n\t\t{ className: blockElementsContainerIdentifier },\n\t\tname,\n\t\t{ style },\n\t\tskipSerializationPathsEdit\n\t);\n}\n\naddFilter(\n\t'blocks.registerBlockType',\n\t'core/style/addAttribute',\n\taddAttribute\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/block-editor",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.17.0",
|
|
4
4
|
"description": "Generic block editor.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -61,42 +61,42 @@
|
|
|
61
61
|
],
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@react-spring/web": "^9.4.5",
|
|
64
|
-
"@wordpress/a11y": "^4.
|
|
65
|
-
"@wordpress/base-styles": "^6.
|
|
66
|
-
"@wordpress/blob": "^4.
|
|
67
|
-
"@wordpress/block-serialization-default-parser": "^5.
|
|
68
|
-
"@wordpress/blocks": "^15.
|
|
69
|
-
"@wordpress/commands": "^1.
|
|
70
|
-
"@wordpress/components": "^32.
|
|
71
|
-
"@wordpress/compose": "^7.
|
|
72
|
-
"@wordpress/data": "^10.
|
|
73
|
-
"@wordpress/dataviews": "^14.1.
|
|
74
|
-
"@wordpress/date": "^5.
|
|
75
|
-
"@wordpress/deprecated": "^4.
|
|
76
|
-
"@wordpress/dom": "^4.
|
|
77
|
-
"@wordpress/element": "^6.44.
|
|
78
|
-
"@wordpress/escape-html": "^3.
|
|
79
|
-
"@wordpress/global-styles-engine": "^1.
|
|
80
|
-
"@wordpress/hooks": "^4.
|
|
81
|
-
"@wordpress/html-entities": "^4.
|
|
82
|
-
"@wordpress/i18n": "^6.17.
|
|
83
|
-
"@wordpress/icons": "^12.
|
|
84
|
-
"@wordpress/image-cropper": "^1.
|
|
85
|
-
"@wordpress/interactivity": "^6.
|
|
86
|
-
"@wordpress/is-shallow-equal": "^5.
|
|
87
|
-
"@wordpress/keyboard-shortcuts": "^5.
|
|
88
|
-
"@wordpress/keycodes": "^4.
|
|
89
|
-
"@wordpress/notices": "^5.
|
|
90
|
-
"@wordpress/preferences": "^4.
|
|
91
|
-
"@wordpress/priority-queue": "^3.
|
|
92
|
-
"@wordpress/private-apis": "^1.
|
|
93
|
-
"@wordpress/rich-text": "^7.
|
|
94
|
-
"@wordpress/style-engine": "^2.
|
|
95
|
-
"@wordpress/token-list": "^3.
|
|
96
|
-
"@wordpress/upload-media": "^0.
|
|
97
|
-
"@wordpress/url": "^4.
|
|
98
|
-
"@wordpress/warning": "^3.
|
|
99
|
-
"@wordpress/wordcount": "^4.
|
|
64
|
+
"@wordpress/a11y": "^4.44.0",
|
|
65
|
+
"@wordpress/base-styles": "^6.20.0",
|
|
66
|
+
"@wordpress/blob": "^4.44.0",
|
|
67
|
+
"@wordpress/block-serialization-default-parser": "^5.44.0",
|
|
68
|
+
"@wordpress/blocks": "^15.17.0",
|
|
69
|
+
"@wordpress/commands": "^1.44.0",
|
|
70
|
+
"@wordpress/components": "^32.6.0",
|
|
71
|
+
"@wordpress/compose": "^7.44.0",
|
|
72
|
+
"@wordpress/data": "^10.44.0",
|
|
73
|
+
"@wordpress/dataviews": "^14.1.0",
|
|
74
|
+
"@wordpress/date": "^5.44.0",
|
|
75
|
+
"@wordpress/deprecated": "^4.44.0",
|
|
76
|
+
"@wordpress/dom": "^4.44.0",
|
|
77
|
+
"@wordpress/element": "^6.44.0",
|
|
78
|
+
"@wordpress/escape-html": "^3.44.0",
|
|
79
|
+
"@wordpress/global-styles-engine": "^1.11.0",
|
|
80
|
+
"@wordpress/hooks": "^4.44.0",
|
|
81
|
+
"@wordpress/html-entities": "^4.44.0",
|
|
82
|
+
"@wordpress/i18n": "^6.17.0",
|
|
83
|
+
"@wordpress/icons": "^12.2.0",
|
|
84
|
+
"@wordpress/image-cropper": "^1.8.0",
|
|
85
|
+
"@wordpress/interactivity": "^6.44.0",
|
|
86
|
+
"@wordpress/is-shallow-equal": "^5.44.0",
|
|
87
|
+
"@wordpress/keyboard-shortcuts": "^5.44.0",
|
|
88
|
+
"@wordpress/keycodes": "^4.44.0",
|
|
89
|
+
"@wordpress/notices": "^5.44.0",
|
|
90
|
+
"@wordpress/preferences": "^4.44.0",
|
|
91
|
+
"@wordpress/priority-queue": "^3.44.0",
|
|
92
|
+
"@wordpress/private-apis": "^1.44.0",
|
|
93
|
+
"@wordpress/rich-text": "^7.44.0",
|
|
94
|
+
"@wordpress/style-engine": "^2.44.0",
|
|
95
|
+
"@wordpress/token-list": "^3.44.0",
|
|
96
|
+
"@wordpress/upload-media": "^0.29.0",
|
|
97
|
+
"@wordpress/url": "^4.44.0",
|
|
98
|
+
"@wordpress/warning": "^3.44.0",
|
|
99
|
+
"@wordpress/wordcount": "^4.44.0",
|
|
100
100
|
"change-case": "^4.1.2",
|
|
101
101
|
"clsx": "^2.1.1",
|
|
102
102
|
"colord": "^2.7.0",
|
|
@@ -123,5 +123,5 @@
|
|
|
123
123
|
"publishConfig": {
|
|
124
124
|
"access": "public"
|
|
125
125
|
},
|
|
126
|
-
"gitHead": "
|
|
126
|
+
"gitHead": "b862d8c84121a47bbeff882f6c87e61681ce2e0d"
|
|
127
127
|
}
|
|
@@ -70,7 +70,9 @@ export default function LinkPreview( {
|
|
|
70
70
|
|
|
71
71
|
const displayTitle =
|
|
72
72
|
! isEmptyURL &&
|
|
73
|
-
stripHTML(
|
|
73
|
+
stripHTML(
|
|
74
|
+
value?.entityTitle || richData?.title || value?.title || displayURL
|
|
75
|
+
);
|
|
74
76
|
|
|
75
77
|
let icon;
|
|
76
78
|
|
|
@@ -168,12 +168,18 @@ export default function PresetInputControl( {
|
|
|
168
168
|
unitConfig?.max ?? customValueSettings[ computedUnit ]?.max ?? 10;
|
|
169
169
|
|
|
170
170
|
const handleCustomValueChange = ( newValue ) => {
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
// Treat empty or undefined as an explicit clear and propagate undefined.
|
|
172
|
+
if ( newValue === undefined || newValue === '' ) {
|
|
173
|
+
onChange( undefined );
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
173
176
|
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
// Ignore non-numeric intermediate input (e.g. just a unit).
|
|
178
|
+
if ( isNaN( parseFloat( newValue ) ) ) {
|
|
179
|
+
return;
|
|
176
180
|
}
|
|
181
|
+
|
|
182
|
+
onChange( newValue );
|
|
177
183
|
};
|
|
178
184
|
const handleCustomValueSliderChange = ( next ) => {
|
|
179
185
|
onChange( [ next, computedUnit ].join( '' ) );
|
|
@@ -92,6 +92,76 @@ describe( 'PresetInputControl', () => {
|
|
|
92
92
|
expect( mockOnChange ).toHaveBeenCalledWith( '25px' );
|
|
93
93
|
} );
|
|
94
94
|
|
|
95
|
+
it( 'clears value with undefined when input is fully erased via backspace', () => {
|
|
96
|
+
render(
|
|
97
|
+
<PresetInputControl
|
|
98
|
+
{ ...defaultProps }
|
|
99
|
+
presets={ presets }
|
|
100
|
+
value="60px"
|
|
101
|
+
disableCustomValues={ false }
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const input = screen.getByRole( 'spinbutton' );
|
|
106
|
+
|
|
107
|
+
// Simulate the bug scenario: backspace through "60" one character
|
|
108
|
+
// at a time. fireEvent.change is used here (rather than userEvent
|
|
109
|
+
// keyboard interactions) because the controlled UnitControl input
|
|
110
|
+
// does not respond to synthesised key events in jsdom. The
|
|
111
|
+
// intermediate "6" forwarding is expected and correct; the bug
|
|
112
|
+
// was that the final clear silently failed to propagate, leaving
|
|
113
|
+
// the parent stuck on the partial value.
|
|
114
|
+
fireEvent.change( input, { target: { value: '6' } } );
|
|
115
|
+
fireEvent.change( input, { target: { value: '' } } );
|
|
116
|
+
|
|
117
|
+
// The final clear must propagate as undefined, not be swallowed,
|
|
118
|
+
// and never be persisted as an empty string.
|
|
119
|
+
expect( mockOnChange ).toHaveBeenLastCalledWith( undefined );
|
|
120
|
+
expect( mockOnChange ).not.toHaveBeenCalledWith( '' );
|
|
121
|
+
} );
|
|
122
|
+
|
|
123
|
+
it( 'clears value with undefined when input is cleared in one shot', async () => {
|
|
124
|
+
const user = userEvent.setup();
|
|
125
|
+
|
|
126
|
+
render(
|
|
127
|
+
<PresetInputControl
|
|
128
|
+
{ ...defaultProps }
|
|
129
|
+
presets={ presets }
|
|
130
|
+
value="25px"
|
|
131
|
+
disableCustomValues={ false }
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const input = screen.getByRole( 'spinbutton' );
|
|
136
|
+
await user.clear( input );
|
|
137
|
+
|
|
138
|
+
expect( mockOnChange ).toHaveBeenCalledWith( undefined );
|
|
139
|
+
expect( mockOnChange ).not.toHaveBeenCalledWith( '' );
|
|
140
|
+
} );
|
|
141
|
+
|
|
142
|
+
it( 'does not call onChange for non-numeric intermediate input', async () => {
|
|
143
|
+
const user = userEvent.setup();
|
|
144
|
+
|
|
145
|
+
render(
|
|
146
|
+
<PresetInputControl
|
|
147
|
+
{ ...defaultProps }
|
|
148
|
+
presets={ presets }
|
|
149
|
+
value="15px"
|
|
150
|
+
disableCustomValues={ false }
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const input = screen.getByRole( 'spinbutton' );
|
|
155
|
+
await user.clear( input );
|
|
156
|
+
mockOnChange.mockClear();
|
|
157
|
+
|
|
158
|
+
// Typing a stray non-numeric character should not propagate a change.
|
|
159
|
+
await user.type( input, 'a' );
|
|
160
|
+
|
|
161
|
+
expect( mockOnChange ).not.toHaveBeenCalledWith( 'a' );
|
|
162
|
+
expect( mockOnChange ).not.toHaveBeenCalledWith( 'apx' );
|
|
163
|
+
} );
|
|
164
|
+
|
|
95
165
|
it( 'uses select dropdown for many presets', async () => {
|
|
96
166
|
const manyPresets = Array.from( { length: 12 }, ( _, i ) => ( {
|
|
97
167
|
name: `Preset ${ i + 1 }`,
|
|
@@ -36,6 +36,7 @@ const allEventListeners = [
|
|
|
36
36
|
export function useEventListeners( props ) {
|
|
37
37
|
const propsRef = useRef( props );
|
|
38
38
|
useInsertionEffect( () => {
|
|
39
|
+
// eslint-disable-next-line react-compiler/react-compiler -- false positive, see https://github.com/facebook/react/issues/29196
|
|
39
40
|
propsRef.current = props;
|
|
40
41
|
} );
|
|
41
42
|
const refEffects = useMemo(
|
|
@@ -214,7 +214,45 @@ export default function useSelectionObserver() {
|
|
|
214
214
|
const isSingularSelection = startClientId === endClientId;
|
|
215
215
|
if ( isSingularSelection ) {
|
|
216
216
|
if ( ! isMultiSelecting() ) {
|
|
217
|
-
|
|
217
|
+
// If the selection is not collapsed and falls
|
|
218
|
+
// within a RichText that doesn't have focus
|
|
219
|
+
// (e.g. the user started dragging from the block
|
|
220
|
+
// wrapper padding), dispatch a full
|
|
221
|
+
// selectionChange so the format toolbar appears.
|
|
222
|
+
const richTextElement =
|
|
223
|
+
! selection.isCollapsed &&
|
|
224
|
+
( getRichTextElement( startNode ) ||
|
|
225
|
+
getRichTextElement( endNode ) );
|
|
226
|
+
|
|
227
|
+
if (
|
|
228
|
+
richTextElement &&
|
|
229
|
+
ownerDocument.activeElement !== richTextElement
|
|
230
|
+
) {
|
|
231
|
+
const range = selection.getRangeAt( 0 );
|
|
232
|
+
const richTextData = create( {
|
|
233
|
+
element: richTextElement,
|
|
234
|
+
range,
|
|
235
|
+
__unstableIsEditableTree: true,
|
|
236
|
+
} );
|
|
237
|
+
selectionChange( {
|
|
238
|
+
start: {
|
|
239
|
+
clientId: startClientId,
|
|
240
|
+
attributeKey:
|
|
241
|
+
richTextElement.dataset
|
|
242
|
+
.wpBlockAttributeKey,
|
|
243
|
+
offset: richTextData.start ?? 0,
|
|
244
|
+
},
|
|
245
|
+
end: {
|
|
246
|
+
clientId: startClientId,
|
|
247
|
+
attributeKey:
|
|
248
|
+
richTextElement.dataset
|
|
249
|
+
.wpBlockAttributeKey,
|
|
250
|
+
offset: richTextData.end,
|
|
251
|
+
},
|
|
252
|
+
} );
|
|
253
|
+
} else {
|
|
254
|
+
selectBlock( startClientId );
|
|
255
|
+
}
|
|
218
256
|
} else {
|
|
219
257
|
multiSelect( startClientId, startClientId );
|
|
220
258
|
}
|