UNPKG

@wordpress/block-editor

Version:
346 lines (345 loc) 10.6 kB
// packages/block-editor/src/components/inserter/menu.js import clsx from "clsx"; import { forwardRef, useState, useCallback, useMemo, useRef, useLayoutEffect } from "@wordpress/element"; import { VisuallyHidden, SearchControl, Popover } from "@wordpress/components"; import { __ } from "@wordpress/i18n"; import { useDebouncedInput, useViewportMatch } from "@wordpress/compose"; import { useSelect } from "@wordpress/data"; import Tips from "./tips"; import InserterPreviewPanel from "./preview-panel"; import BlockTypesTab from "./block-types-tab"; import BlockPatternsTab from "./block-patterns-tab"; import { PatternCategoryPreviews } from "./block-patterns-tab/pattern-category-previews"; import { MediaTab, MediaCategoryPanel } from "./media-tab"; import InserterSearchResults from "./search-results"; import useInsertionPoint from "./hooks/use-insertion-point"; import { store as blockEditorStore } from "../../store"; import TabbedSidebar from "../tabbed-sidebar"; import { useZoomOut } from "../../hooks/use-zoom-out"; import { unlock } from "../../lock-unlock"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var NOOP = () => { }; function InserterMenu({ rootClientId, clientId, isAppender, __experimentalInsertionIndex, onSelect, showInserterHelpPanel, showMostUsedBlocks, __experimentalFilterValue = "", shouldFocusBlock = true, onPatternCategorySelection, onClose, __experimentalInitialTab, __experimentalInitialCategory }, ref) { const { isZoomOutMode, hasSectionRootClientId } = useSelect((select) => { const { isZoomOut, getSectionRootClientId } = unlock( select(blockEditorStore) ); return { isZoomOutMode: isZoomOut(), hasSectionRootClientId: !!getSectionRootClientId() }; }, []); const [filterValue, setFilterValue, delayedFilterValue] = useDebouncedInput(__experimentalFilterValue); const [hoveredItem, setHoveredItem] = useState(null); const [selectedPatternCategory, setSelectedPatternCategory] = useState( __experimentalInitialCategory ); const [patternFilter, setPatternFilter] = useState("all"); const [selectedMediaCategory, setSelectedMediaCategory] = useState(null); const isLargeViewport = useViewportMatch("large"); function getInitialTab() { if (__experimentalInitialTab) { return __experimentalInitialTab; } if (isZoomOutMode) { return "patterns"; } return "blocks"; } const [selectedTab, setSelectedTab] = useState(getInitialTab()); const shouldUseZoomOut = hasSectionRootClientId && (selectedTab === "patterns" || selectedTab === "media"); useZoomOut(shouldUseZoomOut && isLargeViewport); const [destinationRootClientId, onInsertBlocks, onToggleInsertionPoint] = useInsertionPoint({ rootClientId, clientId, isAppender, insertionIndex: __experimentalInsertionIndex, shouldFocusBlock }); const blockTypesTabRef = useRef(); const onInsert = useCallback( (blocks, meta, shouldForceFocusBlock, _rootClientId) => { onInsertBlocks( blocks, meta, shouldForceFocusBlock, _rootClientId ); onSelect(blocks); window.requestAnimationFrame(() => { if (!shouldFocusBlock && !blockTypesTabRef.current?.contains( ref.current.ownerDocument.activeElement )) { blockTypesTabRef.current?.querySelector("button").focus(); } }); }, [onInsertBlocks, onSelect, shouldFocusBlock] ); const onInsertPattern = useCallback( (blocks, patternName, ...args) => { onToggleInsertionPoint(false); onInsertBlocks(blocks, { patternName }, ...args); onSelect(); }, [onInsertBlocks, onSelect] ); const onHover = useCallback( (item) => { onToggleInsertionPoint(item); setHoveredItem(item); }, [onToggleInsertionPoint, setHoveredItem] ); const onClickPatternCategory = useCallback( (patternCategory, filter) => { setSelectedPatternCategory(patternCategory); setPatternFilter(filter); onPatternCategorySelection?.(); }, [setSelectedPatternCategory, onPatternCategorySelection] ); const showPatternPanel = selectedTab === "patterns" && !delayedFilterValue && !!selectedPatternCategory; const showMediaPanel = selectedTab === "media" && !!selectedMediaCategory; const inserterSearch = useMemo(() => { if (selectedTab === "media") { return null; } return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( SearchControl, { __nextHasNoMarginBottom: true, className: "block-editor-inserter__search", onChange: (value) => { if (hoveredItem) { setHoveredItem(null); } setFilterValue(value); }, value: filterValue, label: __("Search"), placeholder: __("Search") } ), !!delayedFilterValue && /* @__PURE__ */ jsx( InserterSearchResults, { filterValue: delayedFilterValue, onSelect, onHover, rootClientId, clientId, isAppender, __experimentalInsertionIndex, showBlockDirectory: true, shouldFocusBlock, prioritizePatterns: selectedTab === "patterns" } ) ] }); }, [ selectedTab, hoveredItem, setHoveredItem, setFilterValue, filterValue, delayedFilterValue, onSelect, onHover, shouldFocusBlock, clientId, rootClientId, __experimentalInsertionIndex, isAppender ]); const blocksTab = useMemo(() => { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("div", { className: "block-editor-inserter__block-list", children: /* @__PURE__ */ jsx( BlockTypesTab, { ref: blockTypesTabRef, rootClientId: destinationRootClientId, onInsert, onHover, showMostUsedBlocks } ) }), showInserterHelpPanel && /* @__PURE__ */ jsxs("div", { className: "block-editor-inserter__tips", children: [ /* @__PURE__ */ jsx(VisuallyHidden, { as: "h2", children: __("A tip for using the block editor") }), /* @__PURE__ */ jsx(Tips, {}) ] }) ] }); }, [ destinationRootClientId, onInsert, onHover, showMostUsedBlocks, showInserterHelpPanel ]); const patternsTab = useMemo(() => { return /* @__PURE__ */ jsx( BlockPatternsTab, { rootClientId: destinationRootClientId, onInsert: onInsertPattern, onSelectCategory: onClickPatternCategory, selectedCategory: selectedPatternCategory, children: showPatternPanel && /* @__PURE__ */ jsx( PatternCategoryPreviews, { rootClientId: destinationRootClientId, onInsert: onInsertPattern, category: selectedPatternCategory, patternFilter, showTitlesAsTooltip: true } ) } ); }, [ destinationRootClientId, onInsertPattern, onClickPatternCategory, patternFilter, selectedPatternCategory, showPatternPanel ]); const mediaTab = useMemo(() => { return /* @__PURE__ */ jsx( MediaTab, { rootClientId: destinationRootClientId, selectedCategory: selectedMediaCategory, onSelectCategory: setSelectedMediaCategory, onInsert, children: showMediaPanel && /* @__PURE__ */ jsx( MediaCategoryPanel, { rootClientId: destinationRootClientId, onInsert, category: selectedMediaCategory } ) } ); }, [ destinationRootClientId, onInsert, selectedMediaCategory, setSelectedMediaCategory, showMediaPanel ]); const handleSetSelectedTab = (value) => { if (value !== "patterns") { setSelectedPatternCategory(null); } setSelectedTab(value); }; const tabsRef = useRef(); useLayoutEffect(() => { if (tabsRef.current) { window.requestAnimationFrame(() => { tabsRef.current.querySelector('[role="tab"][aria-selected="true"]')?.focus(); }); } }, []); return /* @__PURE__ */ jsxs( "div", { className: clsx("block-editor-inserter__menu", { "show-panel": showPatternPanel || showMediaPanel, "is-zoom-out": isZoomOutMode }), ref, children: [ /* @__PURE__ */ jsx("div", { className: "block-editor-inserter__main-area", children: /* @__PURE__ */ jsx( TabbedSidebar, { ref: tabsRef, onSelect: handleSetSelectedTab, onClose, selectedTab, closeButtonLabel: __("Close Block Inserter"), tabs: [ { name: "blocks", title: __("Blocks"), panel: /* @__PURE__ */ jsxs(Fragment, { children: [ inserterSearch, selectedTab === "blocks" && !delayedFilterValue && blocksTab ] }) }, { name: "patterns", title: __("Patterns"), panel: /* @__PURE__ */ jsxs(Fragment, { children: [ inserterSearch, selectedTab === "patterns" && !delayedFilterValue && patternsTab ] }) }, { name: "media", title: __("Media"), panel: /* @__PURE__ */ jsxs(Fragment, { children: [ inserterSearch, mediaTab ] }) } ] } ) }), showInserterHelpPanel && hoveredItem && /* @__PURE__ */ jsx( Popover, { className: "block-editor-inserter__preview-container__popover", placement: "right-start", offset: 16, focusOnMount: false, animate: false, children: /* @__PURE__ */ jsx(InserterPreviewPanel, { item: hoveredItem }) } ) ] } ); } var PrivateInserterMenu = forwardRef(InserterMenu); function PublicInserterMenu(props, ref) { return /* @__PURE__ */ jsx( PrivateInserterMenu, { ...props, onPatternCategorySelection: NOOP, ref } ); } var menu_default = forwardRef(PublicInserterMenu); export { PrivateInserterMenu, menu_default as default }; //# sourceMappingURL=menu.js.map