UNPKG

@wordpress/block-editor

Version:
288 lines (287 loc) 9.2 kB
// packages/block-editor/src/components/global-styles/border-panel.js import { BorderBoxControl, __experimentalHasSplitBorders as hasSplitBorders, __experimentalIsDefinedBorder as isDefinedBorder, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, BaseControl } from "@wordpress/components"; import { useCallback, useMemo } from "@wordpress/element"; import { __ } from "@wordpress/i18n"; import { getValueFromVariable } from "@wordpress/global-styles-engine"; import BorderRadiusControl from "../border-radius-control"; import { useColorsPerOrigin } from "./hooks"; import { useToolsPanelDropdownMenuProps } from "./utils"; import { setImmutably } from "../../utils/object"; import { useBorderPanelLabel } from "../../hooks/border"; import { ShadowPopover, useShadowPresets } from "./shadow-panel-components"; import { jsx, jsxs } from "react/jsx-runtime"; function useHasBorderPanel(settings) { const controls = Object.values(useHasBorderPanelControls(settings)); return controls.some(Boolean); } function useHasBorderPanelControls(settings) { const controls = { hasBorderColor: useHasBorderColorControl(settings), hasBorderRadius: useHasBorderRadiusControl(settings), hasBorderStyle: useHasBorderStyleControl(settings), hasBorderWidth: useHasBorderWidthControl(settings), hasShadow: useHasShadowControl(settings) }; return controls; } function useHasBorderColorControl(settings) { return settings?.border?.color; } function useHasBorderRadiusControl(settings) { return settings?.border?.radius; } function useHasBorderStyleControl(settings) { return settings?.border?.style; } function useHasBorderWidthControl(settings) { return settings?.border?.width; } function useHasShadowControl(settings) { const shadows = useShadowPresets(settings); return !!settings?.shadow && shadows.length > 0; } function BorderToolsPanel({ resetAllFilter, onChange, value, panelId, children, label }) { const dropdownMenuProps = useToolsPanelDropdownMenuProps(); const resetAll = () => { const updatedValue = resetAllFilter(value); onChange(updatedValue); }; return /* @__PURE__ */ jsx( ToolsPanel, { label, resetAll, panelId, dropdownMenuProps, children } ); } var DEFAULT_CONTROLS = { radius: true, color: true, width: true, shadow: true }; function BorderPanel({ as: Wrapper = BorderToolsPanel, value, onChange, inheritedValue = value, settings, panelId, name, defaultControls = DEFAULT_CONTROLS }) { const colors = useColorsPerOrigin(settings); const decodeValue = useCallback( (rawValue) => getValueFromVariable({ settings }, "", rawValue), [settings] ); const encodeColorValue = (colorValue) => { const allColors = colors.flatMap( ({ colors: originColors }) => originColors ); const colorObject = allColors.find( ({ color }) => color === colorValue ); return colorObject ? "var:preset|color|" + colorObject.slug : colorValue; }; const border = useMemo(() => { if (hasSplitBorders(inheritedValue?.border)) { const borderValue = { ...inheritedValue?.border }; ["top", "right", "bottom", "left"].forEach((side) => { borderValue[side] = { ...borderValue[side], color: decodeValue(borderValue[side]?.color) }; }); return borderValue; } return { ...inheritedValue?.border, color: inheritedValue?.border?.color ? decodeValue(inheritedValue?.border?.color) : void 0 }; }, [inheritedValue?.border, decodeValue]); const setBorder = (newBorder) => onChange({ ...value, border: newBorder }); const showBorderColor = useHasBorderColorControl(settings); const showBorderStyle = useHasBorderStyleControl(settings); const showBorderWidth = useHasBorderWidthControl(settings); const showBorderRadius = useHasBorderRadiusControl(settings); const borderRadiusValues = useMemo(() => { if (typeof inheritedValue?.border?.radius !== "object") { return decodeValue(inheritedValue?.border?.radius); } return { topLeft: decodeValue(inheritedValue?.border?.radius?.topLeft), topRight: decodeValue(inheritedValue?.border?.radius?.topRight), bottomLeft: decodeValue( inheritedValue?.border?.radius?.bottomLeft ), bottomRight: decodeValue( inheritedValue?.border?.radius?.bottomRight ) }; }, [inheritedValue?.border?.radius, decodeValue]); const setBorderRadius = (newBorderRadius) => setBorder({ ...border, radius: newBorderRadius }); const hasBorderRadius = () => { const borderValues = value?.border?.radius; if (typeof borderValues === "object") { return Object.entries(borderValues).some(Boolean); } return !!borderValues; }; const hasShadowControl = useHasShadowControl(settings); const shadow = decodeValue(inheritedValue?.shadow); const shadowPresets = settings?.shadow?.presets ?? {}; const mergedShadowPresets = shadowPresets.custom ?? shadowPresets.theme ?? shadowPresets.default ?? []; const setShadow = (newValue) => { const slug = mergedShadowPresets?.find( ({ shadow: shadowName }) => shadowName === newValue )?.slug; onChange( setImmutably( value, ["shadow"], slug ? `var:preset|shadow|${slug}` : newValue || void 0 ) ); }; const hasShadow = () => !!value?.shadow; const resetShadow = () => setShadow(void 0); const resetBorder = () => { if (hasBorderRadius()) { return setBorder({ radius: value?.border?.radius }); } setBorder(void 0); }; const onBorderChange = (newBorder) => { const updatedBorder = { ...newBorder }; if (hasSplitBorders(updatedBorder)) { ["top", "right", "bottom", "left"].forEach((side) => { if (updatedBorder[side]) { updatedBorder[side] = { ...updatedBorder[side], color: encodeColorValue(updatedBorder[side]?.color) }; } }); } else if (updatedBorder) { updatedBorder.color = encodeColorValue(updatedBorder.color); } setBorder({ radius: border?.radius, ...updatedBorder }); }; const resetAllFilter = useCallback((previousValue) => { return { ...previousValue, border: void 0, shadow: void 0 }; }, []); const showBorderByDefault = defaultControls?.color || defaultControls?.width; const hasBorderControl = showBorderColor || showBorderStyle || showBorderWidth || showBorderRadius; const label = useBorderPanelLabel({ blockName: name, hasShadowControl, hasBorderControl }); return /* @__PURE__ */ jsxs( Wrapper, { resetAllFilter, value, onChange, panelId, label, children: [ (showBorderWidth || showBorderColor) && /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => isDefinedBorder(value?.border), label: __("Border"), onDeselect: () => resetBorder(), isShownByDefault: showBorderByDefault, panelId, children: /* @__PURE__ */ jsx( BorderBoxControl, { colors, enableAlpha: true, enableStyle: showBorderStyle, onChange: onBorderChange, popoverOffset: 40, popoverPlacement: "left-start", value: border, __experimentalIsRenderedInSidebar: true, size: "__unstable-large", hideLabelFromVision: !hasShadowControl, label: __("Border") } ) } ), showBorderRadius && /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: hasBorderRadius, label: __("Radius"), onDeselect: () => setBorderRadius(void 0), isShownByDefault: defaultControls.radius, panelId, children: /* @__PURE__ */ jsx( BorderRadiusControl, { presets: settings?.border?.radiusSizes, values: borderRadiusValues, onChange: (newValue) => { setBorderRadius(newValue || void 0); } } ) } ), hasShadowControl && /* @__PURE__ */ jsxs( ToolsPanelItem, { label: __("Shadow"), hasValue: hasShadow, onDeselect: resetShadow, isShownByDefault: defaultControls.shadow, panelId, children: [ hasBorderControl ? /* @__PURE__ */ jsx(BaseControl.VisualLabel, { as: "legend", children: __("Shadow") }) : null, /* @__PURE__ */ jsx( ShadowPopover, { shadow, onShadowChange: setShadow, settings } ) ] } ) ] } ); } export { BorderPanel as default, useHasBorderPanel, useHasBorderPanelControls }; //# sourceMappingURL=border-panel.js.map