@wordpress/block-editor
Version:
274 lines (273 loc) • 8.61 kB
JavaScript
// packages/block-editor/src/hooks/duotone.js
import { extend } from "colord";
import namesPlugin from "colord/plugins/names";
import {
getBlockSupport,
getBlockType,
hasBlockSupport
} from "@wordpress/blocks";
import { useInstanceId } from "@wordpress/compose";
import { addFilter } from "@wordpress/hooks";
import { useMemo, useEffect } from "@wordpress/element";
import { getBlockSelector } from "@wordpress/global-styles-engine";
import {
BlockControls,
InspectorControls,
__experimentalDuotoneControl as DuotoneControl,
useSettings
} from "../components";
import {
getDuotoneFilter,
getDuotoneStylesheet,
getDuotoneUnsetStylesheet
} from "../components/duotone/utils";
import { scopeSelector } from "../components/global-styles/utils";
import {
cleanEmptyObject,
useBlockSettings,
usePrivateStyleOverride
} from "./utils";
import { default as StylesFiltersPanel } from "../components/global-styles/filters-panel";
import { useBlockEditingMode } from "../components/block-editing-mode";
import { useBlockElement } from "../components/block-list/use-block-props/use-block-refs";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var EMPTY_ARRAY = [];
var isSafari = window?.navigator.userAgent && window.navigator.userAgent.includes("Safari") && !window.navigator.userAgent.includes("Chrome") && !window.navigator.userAgent.includes("Chromium");
extend([namesPlugin]);
function useMultiOriginPresets({ presetSetting, defaultSetting }) {
const [enableDefault, userPresets, themePresets, defaultPresets] = useSettings(
defaultSetting,
`${presetSetting}.custom`,
`${presetSetting}.theme`,
`${presetSetting}.default`
);
return useMemo(
() => [
...userPresets || EMPTY_ARRAY,
...themePresets || EMPTY_ARRAY,
...enableDefault && defaultPresets || EMPTY_ARRAY
],
[enableDefault, userPresets, themePresets, defaultPresets]
);
}
function getColorsFromDuotonePreset(duotone, duotonePalette) {
if (!duotone) {
return;
}
const preset = duotonePalette?.find(({ slug }) => {
return duotone === `var:preset|duotone|${slug}`;
});
return preset ? preset.colors : void 0;
}
function getDuotonePresetFromColors(colors, duotonePalette) {
if (!colors || !Array.isArray(colors)) {
return;
}
const preset = duotonePalette?.find((duotonePreset) => {
return duotonePreset?.colors?.every(
(val, index) => val === colors[index]
);
});
return preset ? `var:preset|duotone|${preset.slug}` : void 0;
}
function DuotonePanelPure({ style, setAttributes, name }) {
const duotoneStyle = style?.color?.duotone;
const settings = useBlockSettings(name);
const blockEditingMode = useBlockEditingMode();
const duotonePalette = useMultiOriginPresets({
presetSetting: "color.duotone",
defaultSetting: "color.defaultDuotone"
});
const colorPalette = useMultiOriginPresets({
presetSetting: "color.palette",
defaultSetting: "color.defaultPalette"
});
const [enableCustomColors, enableCustomDuotone] = useSettings(
"color.custom",
"color.customDuotone"
);
const disableCustomColors = !enableCustomColors;
const disableCustomDuotone = !enableCustomDuotone || colorPalette?.length === 0 && disableCustomColors;
if (duotonePalette?.length === 0 && disableCustomDuotone) {
return null;
}
if (blockEditingMode !== "default") {
return null;
}
const duotonePresetOrColors = duotoneStyle === "unset" || Array.isArray(duotoneStyle) ? duotoneStyle : getColorsFromDuotonePreset(duotoneStyle, duotonePalette);
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(InspectorControls, { group: "filter", children: /* @__PURE__ */ jsx(
StylesFiltersPanel,
{
value: { filter: { duotone: duotonePresetOrColors } },
onChange: (newDuotone) => {
const newStyle = {
...style,
color: {
...newDuotone?.filter
}
};
setAttributes({
style: cleanEmptyObject(newStyle)
});
},
settings
}
) }),
/* @__PURE__ */ jsx(BlockControls, { group: "block", __experimentalShareWithChildBlocks: true, children: /* @__PURE__ */ jsx(
DuotoneControl,
{
duotonePalette,
colorPalette,
disableCustomDuotone,
disableCustomColors,
value: duotonePresetOrColors,
onChange: (newDuotone) => {
const maybePreset = getDuotonePresetFromColors(
newDuotone,
duotonePalette
);
const newStyle = {
...style,
color: {
...style?.color,
duotone: maybePreset ?? newDuotone
// use preset or fallback to custom colors.
}
};
setAttributes({
style: cleanEmptyObject(newStyle)
});
},
settings
}
) })
] });
}
var duotone_default = {
shareWithChildBlocks: true,
edit: DuotonePanelPure,
useBlockProps,
attributeKeys: ["style"],
hasSupport(name) {
return hasBlockSupport(name, "filter.duotone");
}
};
function addDuotoneAttributes(settings) {
if (!hasBlockSupport(settings, "filter.duotone")) {
return settings;
}
if (!settings.attributes.style) {
Object.assign(settings.attributes, {
style: {
type: "object"
}
});
}
return settings;
}
function useDuotoneStyles({
clientId,
id: filterId,
selector: duotoneSelector,
attribute: duotoneAttr
}) {
const duotonePalette = useMultiOriginPresets({
presetSetting: "color.duotone",
defaultSetting: "color.defaultDuotone"
});
const isCustom = Array.isArray(duotoneAttr);
const duotonePreset = isCustom ? void 0 : getColorsFromDuotonePreset(duotoneAttr, duotonePalette);
const isPreset = typeof duotoneAttr === "string" && duotonePreset;
const isCSS = typeof duotoneAttr === "string" && !isPreset;
let colors = null;
if (isPreset) {
colors = duotonePreset;
} else if (isCSS) {
colors = duotoneAttr;
} else if (isCustom) {
colors = duotoneAttr;
}
const selectors = duotoneSelector.split(",");
const selectorsScoped = selectors.map((selectorPart) => {
return `.${filterId}${selectorPart.trim()}`;
});
const selector = selectorsScoped.join(", ");
const isValidFilter = Array.isArray(colors) || colors === "unset";
usePrivateStyleOverride(
isValidFilter ? {
css: colors !== "unset" ? getDuotoneStylesheet(selector, filterId) : getDuotoneUnsetStylesheet(selector),
__unstableType: "presets"
} : void 0
);
usePrivateStyleOverride(
isValidFilter ? {
assets: colors !== "unset" ? getDuotoneFilter(filterId, colors) : "",
__unstableType: "svgs"
} : void 0
);
const blockElement = useBlockElement(clientId);
useEffect(() => {
if (!isValidFilter) {
return;
}
if (blockElement && isSafari) {
const display = blockElement.style.display;
blockElement.style.setProperty("display", "inline-block");
blockElement.offsetHeight;
blockElement.style.setProperty("display", display);
}
}, [isValidFilter, blockElement, colors]);
}
var DUOTONE_BLOCK_PROPS_REFERENCE = {};
function useBlockProps({ clientId, name, style }) {
const id = useInstanceId(DUOTONE_BLOCK_PROPS_REFERENCE);
const selector = useMemo(() => {
const blockType = getBlockType(name);
if (blockType) {
const duotoneSupport = getBlockSupport(
blockType,
"filter.duotone",
false
);
if (!duotoneSupport) {
return null;
}
const experimentalDuotone = getBlockSupport(
blockType,
"color.__experimentalDuotone",
false
);
if (experimentalDuotone) {
const rootSelector = getBlockSelector(blockType);
return typeof experimentalDuotone === "string" ? scopeSelector(rootSelector, experimentalDuotone) : rootSelector;
}
return getBlockSelector(blockType, "filter.duotone", {
fallback: true
});
}
}, [name]);
const attribute = style?.color?.duotone;
const filterClass = `wp-duotone-${id}`;
const shouldRender = selector && attribute;
useDuotoneStyles({
clientId,
id: filterClass,
selector,
attribute
});
return {
className: shouldRender ? filterClass : ""
};
}
addFilter(
"blocks.registerBlockType",
"core/editor/duotone/add-attributes",
addDuotoneAttributes
);
export {
duotone_default as default,
getColorsFromDuotonePreset,
getDuotonePresetFromColors
};
//# sourceMappingURL=duotone.js.map