UNPKG

@wordpress/block-editor

Version:
262 lines (261 loc) 8.83 kB
// packages/block-editor/src/hooks/block-style-variation.js import { getBlockTypes, store as blocksStore } from "@wordpress/blocks"; import { useSelect } from "@wordpress/data"; import { useMemo } from "@wordpress/element"; import { toStyles, getBlockSelectors } from "@wordpress/global-styles-engine"; import { usePrivateStyleOverride } from "./utils"; import { getValueFromObjectPath } from "../utils/object"; import { store as blockEditorStore } from "../store"; import { globalStylesDataKey } from "../store/private-keys"; import { unlock } from "../lock-unlock"; import { Fragment, jsx } from "react/jsx-runtime"; var VARIATION_PREFIX = "is-style-"; function getVariationMatches(className) { if (!className) { return []; } return className.split(/\s+/).reduce((matches, name) => { if (name.startsWith(VARIATION_PREFIX)) { const match = name.slice(VARIATION_PREFIX.length); if (match !== "default") { matches.push(match); } } return matches; }, []); } function getVariationNameFromClass(className, registeredStyles = []) { const matches = getVariationMatches(className); if (!matches) { return null; } for (const variation of matches) { if (registeredStyles.some((style) => style.name === variation)) { return variation; } } return null; } function OverrideStyles({ override }) { usePrivateStyleOverride(override); } function __unstableBlockStyleVariationOverridesWithConfig({ config }) { const { getBlockStyles, overrides } = useSelect( (select) => ({ getBlockStyles: select(blocksStore).getBlockStyles, overrides: unlock(select(blockEditorStore)).getStyleOverrides() }), [] ); const { getBlockName } = useSelect(blockEditorStore); const overridesWithConfig = useMemo(() => { if (!overrides?.length) { return; } const newOverrides = []; const overriddenClientIds = []; for (const [, override] of overrides) { if (override?.variation && override?.clientId && /* * Because this component overwrites existing style overrides, * filter out any overrides that are already present in the store. */ !overriddenClientIds.includes(override.clientId)) { const blockName = getBlockName(override.clientId); const configStyles = config?.styles?.blocks?.[blockName]?.variations?.[override.variation]; if (configStyles) { const variationConfig = { settings: config?.settings, // The variation style data is all that is needed to generate // the styles for the current application to a block. The variation // name is updated to match the instance specific class name. styles: { blocks: { [blockName]: { variations: { [`${override.variation}-${override.clientId}`]: configStyles } } } } }; const blockSelectors = getBlockSelectors( getBlockTypes(), override.clientId ); const hasBlockGapSupport = false; const hasFallbackGapSupport = true; const disableLayoutStyles = true; const disableRootPadding = true; const variationStyles = toStyles( variationConfig, blockSelectors, hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, disableRootPadding, { blockGap: false, blockStyles: true, layoutStyles: false, marginReset: false, presets: false, rootPadding: false, variationStyles: true } ); newOverrides.push({ id: `${override.variation}-${override.clientId}`, css: variationStyles, __unstableType: "variation", variation: override.variation, // The clientId will be stored with the override and used to ensure // the order of overrides matches the order of blocks so that the // correct CSS cascade is maintained. clientId: override.clientId }); overriddenClientIds.push(override.clientId); } } } return newOverrides; }, [config, overrides, getBlockStyles, getBlockName]); if (!overridesWithConfig || !overridesWithConfig.length) { return; } return /* @__PURE__ */ jsx(Fragment, { children: overridesWithConfig.map((override) => /* @__PURE__ */ jsx(OverrideStyles, { override }, override.id)) }); } function getVariationStylesWithRefValues(globalStyles, name, variation) { if (!globalStyles?.styles?.blocks?.[name]?.variations?.[variation]) { return; } const replaceRefs = (variationStyles) => { Object.keys(variationStyles).forEach((key) => { const value = variationStyles[key]; if (typeof value === "object" && value !== null) { if (value.ref !== void 0) { if (typeof value.ref !== "string" || value.ref.trim() === "") { delete variationStyles[key]; } else { const refValue = getValueFromObjectPath( globalStyles, value.ref ); if (refValue) { variationStyles[key] = refValue; } else { delete variationStyles[key]; } } } else { replaceRefs(value); if (Object.keys(value).length === 0) { delete variationStyles[key]; } } } }); }; const styles = JSON.parse( JSON.stringify( globalStyles.styles.blocks[name].variations[variation] ) ); replaceRefs(styles); return styles; } function useBlockStyleVariation(name, variation, clientId) { const { globalSettings, globalStyles } = useSelect((select) => { const settings = select(blockEditorStore).getSettings(); return { globalSettings: settings.__experimentalFeatures, globalStyles: settings[globalStylesDataKey] }; }, []); return useMemo(() => { const variationStyles = getVariationStylesWithRefValues( { settings: globalSettings, styles: globalStyles }, name, variation ); return { settings: globalSettings, // The variation style data is all that is needed to generate // the styles for the current application to a block. The variation // name is updated to match the instance specific class name. styles: { blocks: { [name]: { variations: { [`${variation}-${clientId}`]: variationStyles } } } } }; }, [globalSettings, globalStyles, variation, clientId, name]); } function useBlockProps({ name, className, clientId }) { const { getBlockStyles } = useSelect(blocksStore); const registeredStyles = getBlockStyles(name); const variation = getVariationNameFromClass(className, registeredStyles); const variationClass = `${VARIATION_PREFIX}${variation}-${clientId}`; const { settings, styles } = useBlockStyleVariation( name, variation, clientId ); const variationStyles = useMemo(() => { if (!variation) { return; } const variationConfig = { settings, styles }; const blockSelectors = getBlockSelectors(getBlockTypes(), clientId); const hasBlockGapSupport = false; const hasFallbackGapSupport = true; const disableLayoutStyles = true; const disableRootPadding = true; return toStyles( variationConfig, blockSelectors, hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, disableRootPadding, { blockGap: false, blockStyles: true, layoutStyles: false, marginReset: false, presets: false, rootPadding: false, variationStyles: true } ); }, [variation, settings, styles, clientId]); usePrivateStyleOverride({ id: `variation-${clientId}`, css: variationStyles, __unstableType: "variation", variation, // The clientId will be stored with the override and used to ensure // the order of overrides matches the order of blocks so that the // correct CSS cascade is maintained. clientId }); return variation ? { className: variationClass } : {}; } var block_style_variation_default = { hasSupport: () => true, attributeKeys: ["className"], isMatch: ({ className }) => getVariationMatches(className).length > 0, useBlockProps }; export { __unstableBlockStyleVariationOverridesWithConfig, block_style_variation_default as default, getVariationStylesWithRefValues }; //# sourceMappingURL=block-style-variation.js.map