UNPKG

@wordpress/block-editor

Version:
256 lines (252 loc) 8.71 kB
/** * WordPress dependencies */ 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'; /** * Internal dependencies */ import BorderRadiusControl from '../border-radius-control'; import { useColorsPerOrigin } from './hooks'; import { getValueFromVariable, useToolsPanelDropdownMenuProps } from './utils'; import { setImmutably } from '../../utils/object'; import { useBorderPanelLabel } from '../../hooks/border'; import { ShadowPopover, useShadowPresets } from './shadow-panel-components'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export function useHasBorderPanel(settings) { const controls = Object.values(useHasBorderPanelControls(settings)); return controls.some(Boolean); } export 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: label, resetAll: resetAll, panelId: panelId, dropdownMenuProps: dropdownMenuProps, children: children }); } const DEFAULT_CONTROLS = { radius: true, color: true, width: true, shadow: true }; export default function BorderPanel({ as: Wrapper = BorderToolsPanel, value, onChange, inheritedValue = value, settings, panelId, name, defaultControls = DEFAULT_CONTROLS }) { var _settings$shadow$pres, _ref, _ref2, _shadowPresets$custom; 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) : undefined }; }, [inheritedValue?.border, decodeValue]); const setBorder = newBorder => onChange({ ...value, border: newBorder }); const showBorderColor = useHasBorderColorControl(settings); const showBorderStyle = useHasBorderStyleControl(settings); const showBorderWidth = useHasBorderWidthControl(settings); // Border radius. const showBorderRadius = useHasBorderRadiusControl(settings); const borderRadiusValues = decodeValue(border?.radius); 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); // Shadow const shadow = decodeValue(inheritedValue?.shadow); const shadowPresets = (_settings$shadow$pres = settings?.shadow?.presets) !== null && _settings$shadow$pres !== void 0 ? _settings$shadow$pres : {}; const mergedShadowPresets = (_ref = (_ref2 = (_shadowPresets$custom = shadowPresets.custom) !== null && _shadowPresets$custom !== void 0 ? _shadowPresets$custom : shadowPresets.theme) !== null && _ref2 !== void 0 ? _ref2 : shadowPresets.default) !== null && _ref !== void 0 ? _ref : []; const setShadow = newValue => { const slug = mergedShadowPresets?.find(({ shadow: shadowName }) => shadowName === newValue)?.slug; onChange(setImmutably(value, ['shadow'], slug ? `var:preset|shadow|${slug}` : newValue || undefined)); }; const hasShadow = () => !!value?.shadow; const resetShadow = () => setShadow(undefined); const resetBorder = () => { if (hasBorderRadius()) { return setBorder({ radius: value?.border?.radius }); } setBorder(undefined); }; const onBorderChange = newBorder => { // Ensure we have a visible border style when a border width or // color is being selected. 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); } // As radius is maintained separately to color, style, and width // maintain its value. Undefined values here will be cleaned when // global styles are saved. setBorder({ radius: border?.radius, ...updatedBorder }); }; const resetAllFilter = useCallback(previousValue => { return { ...previousValue, border: undefined, shadow: undefined }; }, []); const showBorderByDefault = defaultControls?.color || defaultControls?.width; const hasBorderControl = showBorderColor || showBorderStyle || showBorderWidth || showBorderRadius; const label = useBorderPanelLabel({ blockName: name, hasShadowControl, hasBorderControl }); return /*#__PURE__*/_jsxs(Wrapper, { resetAllFilter: resetAllFilter, value: value, onChange: onChange, panelId: panelId, label: label, children: [(showBorderWidth || showBorderColor) && /*#__PURE__*/_jsx(ToolsPanelItem, { hasValue: () => isDefinedBorder(value?.border), label: __('Border'), onDeselect: () => resetBorder(), isShownByDefault: showBorderByDefault, panelId: panelId, children: /*#__PURE__*/_jsx(BorderBoxControl, { colors: 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(undefined), isShownByDefault: defaultControls.radius, panelId: panelId, children: /*#__PURE__*/_jsx(BorderRadiusControl, { values: borderRadiusValues, onChange: newValue => { setBorderRadius(newValue || undefined); } }) }), hasShadowControl && /*#__PURE__*/_jsxs(ToolsPanelItem, { label: __('Shadow'), hasValue: hasShadow, onDeselect: resetShadow, isShownByDefault: defaultControls.shadow, panelId: panelId, children: [hasBorderControl ? /*#__PURE__*/_jsx(BaseControl.VisualLabel, { as: "legend", children: __('Shadow') }) : null, /*#__PURE__*/_jsx(ShadowPopover, { shadow: shadow, onShadowChange: setShadow, settings: settings })] })] }); } //# sourceMappingURL=border-panel.js.map