@wordpress/block-editor
Version:
272 lines (271 loc) • 7.92 kB
JavaScript
// packages/block-editor/src/hooks/style.js
import { useMemo } from "@wordpress/element";
import { addFilter } from "@wordpress/hooks";
import {
getBlockSupport,
hasBlockSupport,
__EXPERIMENTAL_ELEMENTS as ELEMENTS
} from "@wordpress/blocks";
import { useInstanceId } from "@wordpress/compose";
import { getCSSRules, compileCSS } from "@wordpress/style-engine";
import { BACKGROUND_SUPPORT_KEY, BackgroundImagePanel } from "./background";
import { BORDER_SUPPORT_KEY, BorderPanel, SHADOW_SUPPORT_KEY } from "./border";
import { COLOR_SUPPORT_KEY, ColorEdit } from "./color";
import {
TypographyPanel,
TYPOGRAPHY_SUPPORT_KEY,
TYPOGRAPHY_SUPPORT_KEYS
} from "./typography";
import {
DIMENSIONS_SUPPORT_KEY,
SPACING_SUPPORT_KEY,
DimensionsPanel
} from "./dimensions";
import {
shouldSkipSerialization,
useStyleOverride,
useBlockSettings
} from "./utils";
import { scopeSelector } from "../components/global-styles/utils";
import { useBlockEditingMode } from "../components/block-editing-mode";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var styleSupportKeys = [
...TYPOGRAPHY_SUPPORT_KEYS,
BORDER_SUPPORT_KEY,
COLOR_SUPPORT_KEY,
DIMENSIONS_SUPPORT_KEY,
BACKGROUND_SUPPORT_KEY,
SPACING_SUPPORT_KEY,
SHADOW_SUPPORT_KEY
];
var hasStyleSupport = (nameOrType) => styleSupportKeys.some((key) => hasBlockSupport(nameOrType, key));
function getInlineStyles(styles = {}) {
const output = {};
getCSSRules(styles).forEach((rule) => {
output[rule.key] = rule.value;
});
return output;
}
function addAttribute(settings) {
if (!hasStyleSupport(settings)) {
return settings;
}
if (!settings.attributes.style) {
Object.assign(settings.attributes, {
style: {
type: "object"
}
});
}
return settings;
}
var skipSerializationPathsEdit = {
[`${BORDER_SUPPORT_KEY}.__experimentalSkipSerialization`]: ["border"],
[`${COLOR_SUPPORT_KEY}.__experimentalSkipSerialization`]: [
COLOR_SUPPORT_KEY
],
[`${TYPOGRAPHY_SUPPORT_KEY}.__experimentalSkipSerialization`]: [
TYPOGRAPHY_SUPPORT_KEY
],
[`${DIMENSIONS_SUPPORT_KEY}.__experimentalSkipSerialization`]: [
DIMENSIONS_SUPPORT_KEY
],
[`${SPACING_SUPPORT_KEY}.__experimentalSkipSerialization`]: [
SPACING_SUPPORT_KEY
],
[`${SHADOW_SUPPORT_KEY}.__experimentalSkipSerialization`]: [
SHADOW_SUPPORT_KEY
]
};
var skipSerializationPathsSave = {
...skipSerializationPathsEdit,
[`${DIMENSIONS_SUPPORT_KEY}.aspectRatio`]: [
`${DIMENSIONS_SUPPORT_KEY}.aspectRatio`
],
// Skip serialization of aspect ratio in save mode.
[`${BACKGROUND_SUPPORT_KEY}`]: [BACKGROUND_SUPPORT_KEY]
// Skip serialization of background support in save mode.
};
var skipSerializationPathsSaveChecks = {
[`${DIMENSIONS_SUPPORT_KEY}.aspectRatio`]: true,
[`${BACKGROUND_SUPPORT_KEY}`]: true
};
var renamedFeatures = { gradients: "gradient" };
function omitStyle(style, paths, preserveReference = false) {
if (!style) {
return style;
}
let newStyle = style;
if (!preserveReference) {
newStyle = JSON.parse(JSON.stringify(style));
}
if (!Array.isArray(paths)) {
paths = [paths];
}
paths.forEach((path) => {
if (!Array.isArray(path)) {
path = path.split(".");
}
if (path.length > 1) {
const [firstSubpath, ...restPath] = path;
omitStyle(newStyle[firstSubpath], [restPath], true);
} else if (path.length === 1) {
delete newStyle[path[0]];
}
});
return newStyle;
}
function addSaveProps(props, blockNameOrType, attributes, skipPaths = skipSerializationPathsSave) {
if (!hasStyleSupport(blockNameOrType)) {
return props;
}
let { style } = attributes;
Object.entries(skipPaths).forEach(([indicator, path]) => {
const skipSerialization = skipSerializationPathsSaveChecks[indicator] || getBlockSupport(blockNameOrType, indicator);
if (skipSerialization === true) {
style = omitStyle(style, path);
}
if (Array.isArray(skipSerialization)) {
skipSerialization.forEach((featureName) => {
const feature = renamedFeatures[featureName] || featureName;
style = omitStyle(style, [[...path, feature]]);
});
}
});
props.style = {
...getInlineStyles(style),
...props.style
};
return props;
}
function BlockStyleControls({
clientId,
name,
setAttributes,
__unstableParentLayout
}) {
const settings = useBlockSettings(name, __unstableParentLayout);
const blockEditingMode = useBlockEditingMode();
const passedProps = {
clientId,
name,
setAttributes,
settings: {
...settings,
typography: {
...settings.typography,
// The text alignment UI for individual blocks is rendered in
// the block toolbar, so disable it here.
textAlign: false
}
}
};
if (blockEditingMode !== "default") {
return null;
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(ColorEdit, { ...passedProps }),
/* @__PURE__ */ jsx(BackgroundImagePanel, { ...passedProps }),
/* @__PURE__ */ jsx(TypographyPanel, { ...passedProps }),
/* @__PURE__ */ jsx(BorderPanel, { ...passedProps }),
/* @__PURE__ */ jsx(DimensionsPanel, { ...passedProps })
] });
}
var style_default = {
edit: BlockStyleControls,
hasSupport: hasStyleSupport,
addSaveProps,
attributeKeys: ["style"],
useBlockProps
};
var elementTypes = [
{ elementType: "button" },
{ elementType: "link", pseudo: [":hover"] },
{
elementType: "heading",
elements: ["h1", "h2", "h3", "h4", "h5", "h6"]
}
];
var STYLE_BLOCK_PROPS_REFERENCE = {};
function useBlockProps({ name, style }) {
const blockElementsContainerIdentifier = useInstanceId(
STYLE_BLOCK_PROPS_REFERENCE,
"wp-elements"
);
const baseElementSelector = `.${blockElementsContainerIdentifier}`;
const blockElementStyles = style?.elements;
const styles = useMemo(() => {
if (!blockElementStyles) {
return;
}
const elementCSSRules = [];
elementTypes.forEach(({ elementType, pseudo, elements }) => {
const skipSerialization = shouldSkipSerialization(
name,
COLOR_SUPPORT_KEY,
elementType
);
if (skipSerialization) {
return;
}
const elementStyles = blockElementStyles?.[elementType];
if (elementStyles) {
const selector = scopeSelector(
baseElementSelector,
ELEMENTS[elementType]
);
elementCSSRules.push(
compileCSS(elementStyles, { selector })
);
if (pseudo) {
pseudo.forEach((pseudoSelector) => {
if (elementStyles[pseudoSelector]) {
elementCSSRules.push(
compileCSS(elementStyles[pseudoSelector], {
selector: scopeSelector(
baseElementSelector,
`${ELEMENTS[elementType]}${pseudoSelector}`
)
})
);
}
});
}
}
if (elements) {
elements.forEach((element) => {
if (blockElementStyles[element]) {
elementCSSRules.push(
compileCSS(blockElementStyles[element], {
selector: scopeSelector(
baseElementSelector,
ELEMENTS[element]
)
})
);
}
});
}
});
return elementCSSRules.length > 0 ? elementCSSRules.join("") : void 0;
}, [baseElementSelector, blockElementStyles, name]);
useStyleOverride({ css: styles });
return addSaveProps(
{ className: blockElementsContainerIdentifier },
name,
{ style },
skipSerializationPathsEdit
);
}
addFilter(
"blocks.registerBlockType",
"core/style/addAttribute",
addAttribute
);
export {
addSaveProps,
style_default as default,
getInlineStyles,
omitStyle
};
//# sourceMappingURL=style.js.map