UNPKG

@wordpress/interface

Version:

Interface module for WordPress. The package contains shared functionality across the modern JavaScript-based WordPress screens.

283 lines (282 loc) 8.91 kB
// packages/interface/src/components/complementary-area/index.js import clsx from "clsx"; import { Button, Panel, Slot, Fill, __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence } from "@wordpress/components"; import { useDispatch, useSelect } from "@wordpress/data"; import { __ } from "@wordpress/i18n"; import { check, starEmpty, starFilled } from "@wordpress/icons"; import { useEffect, useRef, useState } from "@wordpress/element"; import { store as viewportStore } from "@wordpress/viewport"; import { store as preferencesStore } from "@wordpress/preferences"; import { useReducedMotion, useViewportMatch, usePrevious } from "@wordpress/compose"; import { usePluginContext } from "@wordpress/plugins"; import ComplementaryAreaHeader from "../complementary-area-header/index.mjs"; import ComplementaryAreaMoreMenuItem from "../complementary-area-more-menu-item/index.mjs"; import ComplementaryAreaToggle from "../complementary-area-toggle/index.mjs"; import PinnedItems from "../pinned-items/index.mjs"; import { store as interfaceStore } from "../../store/index.mjs"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var ANIMATION_DURATION = 0.3; function ComplementaryAreaSlot({ scope, ...props }) { return /* @__PURE__ */ jsx(Slot, { name: `ComplementaryArea/${scope}`, ...props }); } var SIDEBAR_WIDTH = 280; var variants = { open: { width: SIDEBAR_WIDTH }, closed: { width: 0 }, mobileOpen: { width: "100vw" } }; function ComplementaryAreaFill({ activeArea, isActive, scope, children, className, id }) { const disableMotion = useReducedMotion(); const isMobileViewport = useViewportMatch("medium", "<"); const previousActiveArea = usePrevious(activeArea); const previousIsActive = usePrevious(isActive); const [, setState] = useState({}); useEffect(() => { setState({}); }, [isActive]); const transition = { type: "tween", duration: disableMotion || isMobileViewport || !!previousActiveArea && !!activeArea && activeArea !== previousActiveArea ? 0 : ANIMATION_DURATION, ease: [0.6, 0, 0.4, 1] }; return /* @__PURE__ */ jsx(Fill, { name: `ComplementaryArea/${scope}`, children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: (previousIsActive || isActive) && /* @__PURE__ */ jsx( motion.div, { variants, initial: "closed", animate: isMobileViewport ? "mobileOpen" : "open", exit: "closed", transition, className: "interface-complementary-area__fill", children: /* @__PURE__ */ jsx( "div", { id, className, style: { width: isMobileViewport ? "100vw" : SIDEBAR_WIDTH }, children } ) } ) }) }); } function useAdjustComplementaryListener(scope, identifier, activeArea, isActive, isSmall) { const previousIsSmallRef = useRef(false); const shouldOpenWhenNotSmallRef = useRef(false); const { enableComplementaryArea, disableComplementaryArea } = useDispatch(interfaceStore); useEffect(() => { if (isActive && isSmall && !previousIsSmallRef.current) { disableComplementaryArea(scope); shouldOpenWhenNotSmallRef.current = true; } else if ( // If there is a flag indicating the complementary area should be // enabled when we go from small to big window size and we are going // from a small to big window size. shouldOpenWhenNotSmallRef.current && !isSmall && previousIsSmallRef.current ) { shouldOpenWhenNotSmallRef.current = false; enableComplementaryArea(scope, identifier); } else if ( // If the flag is indicating the current complementary should be // reopened but another complementary area becomes active, remove // the flag. shouldOpenWhenNotSmallRef.current && activeArea && activeArea !== identifier ) { shouldOpenWhenNotSmallRef.current = false; } if (isSmall !== previousIsSmallRef.current) { previousIsSmallRef.current = isSmall; } }, [ isActive, isSmall, scope, identifier, activeArea, disableComplementaryArea, enableComplementaryArea ]); } function ComplementaryArea({ children, className, closeLabel = __("Close plugin"), identifier: identifierProp, header, headerClassName, icon: iconProp, isPinnable = true, panelClassName, scope, name, title, toggleShortcut, isActiveByDefault }) { const context = usePluginContext(); const icon = iconProp || context.icon; const identifier = identifierProp || `${context.name}/${name}`; const [isReady, setIsReady] = useState(false); const { isLoading, isActive, isPinned, activeArea, isSmall, isLarge, showIconLabels } = useSelect( (select) => { const { getActiveComplementaryArea, isComplementaryAreaLoading, isItemPinned } = select(interfaceStore); const { get } = select(preferencesStore); const _activeArea = getActiveComplementaryArea(scope); return { isLoading: isComplementaryAreaLoading(scope), isActive: _activeArea === identifier, isPinned: isItemPinned(scope, identifier), activeArea: _activeArea, isSmall: select(viewportStore).isViewportMatch("< medium"), isLarge: select(viewportStore).isViewportMatch("large"), showIconLabels: get("core", "showIconLabels") }; }, [identifier, scope] ); const isMobileViewport = useViewportMatch("medium", "<"); useAdjustComplementaryListener( scope, identifier, activeArea, isActive, isSmall ); const { enableComplementaryArea, disableComplementaryArea, pinItem, unpinItem } = useDispatch(interfaceStore); useEffect(() => { if (isActiveByDefault && activeArea === void 0 && !isSmall) { enableComplementaryArea(scope, identifier); } else if (activeArea === void 0 && isSmall) { disableComplementaryArea(scope, identifier); } setIsReady(true); }, [ activeArea, isActiveByDefault, scope, identifier, isSmall, enableComplementaryArea, disableComplementaryArea ]); if (!isReady) { return; } return /* @__PURE__ */ jsxs(Fragment, { children: [ isPinnable && /* @__PURE__ */ jsx(PinnedItems, { scope, children: isPinned && /* @__PURE__ */ jsx( ComplementaryAreaToggle, { scope, identifier, isPressed: isActive && (!showIconLabels || isLarge), "aria-expanded": isActive, "aria-disabled": isLoading, label: title, icon: showIconLabels ? check : icon, showTooltip: !showIconLabels, variant: showIconLabels ? "tertiary" : void 0, size: "compact", shortcut: toggleShortcut } ) }), name && isPinnable && /* @__PURE__ */ jsx( ComplementaryAreaMoreMenuItem, { target: name, scope, icon, identifier, children: title } ), /* @__PURE__ */ jsxs( ComplementaryAreaFill, { activeArea, isActive, className: clsx("interface-complementary-area", className), scope, id: identifier.replace("/", ":"), children: [ /* @__PURE__ */ jsx( ComplementaryAreaHeader, { className: headerClassName, closeLabel, onClose: () => disableComplementaryArea(scope), toggleButtonProps: { label: closeLabel, size: "compact", shortcut: toggleShortcut, scope, identifier }, children: header || /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("h2", { className: "interface-complementary-area-header__title", children: title }), isPinnable && !isMobileViewport && /* @__PURE__ */ jsx( Button, { className: "interface-complementary-area__pin-unpin-item", icon: isPinned ? starFilled : starEmpty, label: isPinned ? __("Unpin from toolbar") : __("Pin to toolbar"), onClick: () => (isPinned ? unpinItem : pinItem)( scope, identifier ), isPressed: isPinned, "aria-expanded": isPinned, size: "compact" } ) ] }) } ), /* @__PURE__ */ jsx(Panel, { className: panelClassName, children }) ] } ) ] }); } ComplementaryArea.Slot = ComplementaryAreaSlot; var complementary_area_default = ComplementaryArea; export { complementary_area_default as default }; //# sourceMappingURL=index.mjs.map