UNPKG

@wordpress/block-library

Version:
537 lines (536 loc) 17.4 kB
import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import clsx from "clsx"; import { useBlockProps, InspectorControls, RichText, __experimentalUseBorderProps as useBorderProps, __experimentalUseColorProps as useColorProps, getTypographyClassesAndStyles as useTypographyProps, store as blockEditorStore, __experimentalGetElementClassName, useSettings } from "@wordpress/block-editor"; import { useDispatch, useSelect } from "@wordpress/data"; import { useEffect, useRef } from "@wordpress/element"; import { SelectControl, ToggleControl, ResizableBox, __experimentalUseCustomUnits as useCustomUnits, __experimentalUnitControl as UnitControl, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, __experimentalVStack as VStack } from "@wordpress/components"; import { useInstanceId } from "@wordpress/compose"; import { Icon, search } from "@wordpress/icons"; import { __, sprintf } from "@wordpress/i18n"; import { __unstableStripHTML as stripHTML } from "@wordpress/dom"; import { PC_WIDTH_DEFAULT, PX_WIDTH_DEFAULT, MIN_WIDTH, isPercentageUnit } from "./utils.js"; import { useToolsPanelDropdownMenuProps } from "../utils/hooks"; const DEFAULT_INNER_PADDING = "4px"; const PERCENTAGE_WIDTHS = [25, 50, 75, 100]; function SearchEdit({ className, attributes, setAttributes, toggleSelection, isSelected, clientId }) { const { label, showLabel, placeholder, width, widthUnit, align, buttonText, buttonPosition, buttonUseIcon, isSearchFieldHidden, style } = attributes; const wasJustInsertedIntoNavigationBlock = useSelect( (select) => { const { getBlockParentsByBlockName, wasBlockJustInserted } = select(blockEditorStore); return !!getBlockParentsByBlockName(clientId, "core/navigation")?.length && wasBlockJustInserted(clientId); }, [clientId] ); const { __unstableMarkNextChangeAsNotPersistent } = useDispatch(blockEditorStore); useEffect(() => { if (wasJustInsertedIntoNavigationBlock) { __unstableMarkNextChangeAsNotPersistent(); setAttributes({ showLabel: false, buttonUseIcon: true, buttonPosition: "button-inside" }); } }, [ __unstableMarkNextChangeAsNotPersistent, wasJustInsertedIntoNavigationBlock, setAttributes ]); const borderRadius = style?.border?.radius; let borderProps = useBorderProps(attributes); if (typeof borderRadius === "number") { borderProps = { ...borderProps, style: { ...borderProps.style, borderRadius: `${borderRadius}px` } }; } const colorProps = useColorProps(attributes); const [fluidTypographySettings, layout] = useSettings( "typography.fluid", "layout" ); const typographyProps = useTypographyProps(attributes, { typography: { fluid: fluidTypographySettings }, layout: { wideSize: layout?.wideSize } }); const unitControlInstanceId = useInstanceId(UnitControl); const unitControlInputId = `wp-block-search__width-${unitControlInstanceId}`; const isButtonPositionInside = "button-inside" === buttonPosition; const isButtonPositionOutside = "button-outside" === buttonPosition; const hasNoButton = "no-button" === buttonPosition; const hasOnlyButton = "button-only" === buttonPosition; const searchFieldRef = useRef(); const buttonRef = useRef(); const units = useCustomUnits({ availableUnits: ["%", "px"], defaultValues: { "%": PC_WIDTH_DEFAULT, px: PX_WIDTH_DEFAULT } }); useEffect(() => { if (hasOnlyButton && !isSelected) { setAttributes({ isSearchFieldHidden: true }); } }, [hasOnlyButton, isSelected, setAttributes]); useEffect(() => { if (!hasOnlyButton || !isSelected) { return; } setAttributes({ isSearchFieldHidden: false }); }, [hasOnlyButton, isSelected, setAttributes, width]); const getBlockClassNames = () => { return clsx( className, isButtonPositionInside ? "wp-block-search__button-inside" : void 0, isButtonPositionOutside ? "wp-block-search__button-outside" : void 0, hasNoButton ? "wp-block-search__no-button" : void 0, hasOnlyButton ? "wp-block-search__button-only" : void 0, !buttonUseIcon && !hasNoButton ? "wp-block-search__text-button" : void 0, buttonUseIcon && !hasNoButton ? "wp-block-search__icon-button" : void 0, hasOnlyButton && isSearchFieldHidden ? "wp-block-search__searchfield-hidden" : void 0 ); }; const buttonPositionControls = [ { label: __("Button outside"), value: "button-outside" }, { label: __("Button inside"), value: "button-inside" }, { label: __("No button"), value: "no-button" }, { label: __("Button only"), value: "button-only" } ]; const getResizableSides = () => { if (hasOnlyButton) { return {}; } return { right: align !== "right", left: align === "right" }; }; const renderTextField = () => { const textFieldClasses = clsx( "wp-block-search__input", isButtonPositionInside ? void 0 : borderProps.className, typographyProps.className ); const textFieldStyles = { ...isButtonPositionInside ? { borderRadius: borderProps.style?.borderRadius, borderTopLeftRadius: borderProps.style?.borderTopLeftRadius, borderTopRightRadius: borderProps.style?.borderTopRightRadius, borderBottomLeftRadius: borderProps.style?.borderBottomLeftRadius, borderBottomRightRadius: borderProps.style?.borderBottomRightRadius } : borderProps.style, ...typographyProps.style, textDecoration: void 0 }; return /* @__PURE__ */ jsx( "input", { type: "search", className: textFieldClasses, style: textFieldStyles, "aria-label": __("Optional placeholder text"), placeholder: placeholder ? void 0 : __("Optional placeholder\u2026"), value: placeholder, onChange: (event) => setAttributes({ placeholder: event.target.value }), ref: searchFieldRef } ); }; const renderButton = () => { const buttonClasses = clsx( "wp-block-search__button", colorProps.className, typographyProps.className, isButtonPositionInside ? void 0 : borderProps.className, buttonUseIcon ? "has-icon" : void 0, __experimentalGetElementClassName("button") ); const buttonStyles = { ...colorProps.style, ...typographyProps.style, ...isButtonPositionInside ? { borderRadius: borderProps.style?.borderRadius, borderTopLeftRadius: borderProps.style?.borderTopLeftRadius, borderTopRightRadius: borderProps.style?.borderTopRightRadius, borderBottomLeftRadius: borderProps.style?.borderBottomLeftRadius, borderBottomRightRadius: borderProps.style?.borderBottomRightRadius } : borderProps.style }; const handleButtonClick = () => { if (hasOnlyButton) { setAttributes({ isSearchFieldHidden: !isSearchFieldHidden }); } }; return /* @__PURE__ */ jsxs(Fragment, { children: [ buttonUseIcon && /* @__PURE__ */ jsx( "button", { type: "button", className: buttonClasses, style: buttonStyles, "aria-label": buttonText ? stripHTML(buttonText) : __("Search"), onClick: handleButtonClick, ref: buttonRef, children: /* @__PURE__ */ jsx(Icon, { icon: search }) } ), !buttonUseIcon && /* @__PURE__ */ jsx( RichText, { identifier: "buttonText", className: buttonClasses, style: buttonStyles, "aria-label": __("Button text"), placeholder: __("Add button text\u2026"), withoutInteractiveFormatting: true, value: buttonText, onChange: (html) => setAttributes({ buttonText: html }), onClick: handleButtonClick } ) ] }); }; const dropdownMenuProps = useToolsPanelDropdownMenuProps(); const controls = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(InspectorControls, { children: /* @__PURE__ */ jsxs( ToolsPanel, { label: __("Settings"), resetAll: () => { setAttributes({ width: void 0, widthUnit: void 0, showLabel: true, buttonUseIcon: false, buttonPosition: "button-outside", isSearchFieldHidden: false }); }, dropdownMenuProps, children: [ /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => !showLabel, label: __("Show label"), onDeselect: () => { setAttributes({ showLabel: true }); }, isShownByDefault: true, children: /* @__PURE__ */ jsx( ToggleControl, { __nextHasNoMarginBottom: true, checked: showLabel, label: __("Show label"), onChange: (value) => setAttributes({ showLabel: value }) } ) } ), /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => buttonPosition !== "button-outside", label: __("Button position"), onDeselect: () => { setAttributes({ buttonPosition: "button-outside", isSearchFieldHidden: false }); }, isShownByDefault: true, children: /* @__PURE__ */ jsx( SelectControl, { value: buttonPosition, __next40pxDefaultSize: true, __nextHasNoMarginBottom: true, label: __("Button position"), onChange: (value) => { setAttributes({ buttonPosition: value, isSearchFieldHidden: value === "button-only" }); }, options: buttonPositionControls } ) } ), buttonPosition !== "no-button" && /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => !!buttonUseIcon, label: __("Use button with icon"), onDeselect: () => { setAttributes({ buttonUseIcon: false }); }, isShownByDefault: true, children: /* @__PURE__ */ jsx( ToggleControl, { __nextHasNoMarginBottom: true, checked: buttonUseIcon, label: __("Use button with icon"), onChange: (value) => setAttributes({ buttonUseIcon: value }) } ) } ), /* @__PURE__ */ jsx( ToolsPanelItem, { hasValue: () => !!width, label: __("Width"), onDeselect: () => { setAttributes({ width: void 0, widthUnit: void 0 }); }, isShownByDefault: true, children: /* @__PURE__ */ jsxs(VStack, { children: [ /* @__PURE__ */ jsx( UnitControl, { __next40pxDefaultSize: true, label: __("Width"), id: unitControlInputId, min: isPercentageUnit(widthUnit) ? 0 : MIN_WIDTH, max: isPercentageUnit(widthUnit) ? 100 : void 0, step: 1, onChange: (newWidth) => { const parsedNewWidth = newWidth === "" ? void 0 : parseInt(newWidth, 10); setAttributes({ width: parsedNewWidth }); }, onUnitChange: (newUnit) => { setAttributes({ width: "%" === newUnit ? PC_WIDTH_DEFAULT : PX_WIDTH_DEFAULT, widthUnit: newUnit }); }, __unstableInputWidth: "80px", value: `${width}${widthUnit}`, units } ), /* @__PURE__ */ jsx( ToggleGroupControl, { label: __("Percentage Width"), value: PERCENTAGE_WIDTHS.includes(width) && widthUnit === "%" ? width : void 0, hideLabelFromVision: true, onChange: (newWidth) => { setAttributes({ width: newWidth, widthUnit: "%" }); }, isBlock: true, __next40pxDefaultSize: true, __nextHasNoMarginBottom: true, children: PERCENTAGE_WIDTHS.map((widthValue) => { return /* @__PURE__ */ jsx( ToggleGroupControlOption, { value: widthValue, label: sprintf( /* translators: %d: Percentage value. */ __("%d%%"), widthValue ) }, widthValue ); }) } ) ] }) } ) ] } ) }) }); const isNonZeroBorderRadius = (radius) => radius !== void 0 && parseInt(radius, 10) !== 0; const padBorderRadius = (radius) => isNonZeroBorderRadius(radius) ? `calc(${radius} + ${DEFAULT_INNER_PADDING})` : void 0; const getWrapperStyles = () => { const styles = isButtonPositionInside ? borderProps.style : { borderRadius: borderProps.style?.borderRadius, borderTopLeftRadius: borderProps.style?.borderTopLeftRadius, borderTopRightRadius: borderProps.style?.borderTopRightRadius, borderBottomLeftRadius: borderProps.style?.borderBottomLeftRadius, borderBottomRightRadius: borderProps.style?.borderBottomRightRadius }; if (isButtonPositionInside) { if (typeof borderRadius === "object") { const { borderTopLeftRadius, borderTopRightRadius, borderBottomLeftRadius, borderBottomRightRadius } = borderProps.style; return { ...styles, borderTopLeftRadius: padBorderRadius(borderTopLeftRadius), borderTopRightRadius: padBorderRadius(borderTopRightRadius), borderBottomLeftRadius: padBorderRadius( borderBottomLeftRadius ), borderBottomRightRadius: padBorderRadius( borderBottomRightRadius ) }; } const radius = Number.isInteger(borderRadius) ? `${borderRadius}px` : borderRadius; styles.borderRadius = `calc(${radius} + ${DEFAULT_INNER_PADDING})`; } return styles; }; const blockProps = useBlockProps({ className: getBlockClassNames(), style: { ...typographyProps.style, // Input opts out of text decoration. textDecoration: void 0 } }); const labelClassnames = clsx( "wp-block-search__label", typographyProps.className ); return /* @__PURE__ */ jsxs("div", { ...blockProps, children: [ controls, showLabel && /* @__PURE__ */ jsx( RichText, { identifier: "label", className: labelClassnames, "aria-label": __("Label text"), placeholder: __("Add label\u2026"), withoutInteractiveFormatting: true, value: label, onChange: (html) => setAttributes({ label: html }), style: typographyProps.style } ), /* @__PURE__ */ jsxs( ResizableBox, { size: { width: width === void 0 ? "auto" : `${width}${widthUnit}`, height: "auto" }, className: clsx( "wp-block-search__inside-wrapper", isButtonPositionInside ? borderProps.className : void 0 ), style: getWrapperStyles(), minWidth: MIN_WIDTH, enable: getResizableSides(), onResizeStart: (event, direction, elt) => { setAttributes({ width: parseInt(elt.offsetWidth, 10), widthUnit: "px" }); toggleSelection(false); }, onResizeStop: (event, direction, elt, delta) => { setAttributes({ width: parseInt(width + delta.width, 10) }); toggleSelection(true); }, showHandle: isSelected, children: [ (isButtonPositionInside || isButtonPositionOutside || hasOnlyButton) && /* @__PURE__ */ jsxs(Fragment, { children: [ renderTextField(), renderButton() ] }), hasNoButton && renderTextField() ] } ) ] }); } export { SearchEdit as default }; //# sourceMappingURL=edit.js.map