UNPKG

@wordpress/block-editor

Version:
183 lines (163 loc) 7 kB
import { createElement, Fragment } from "@wordpress/element"; /** * WordPress dependencies */ import { useMemo, useState, useCallback, useRef, useEffect } from '@wordpress/element'; import { _x, __ } from '@wordpress/i18n'; import { useAsyncList, useViewportMatch } from '@wordpress/compose'; import { __experimentalItemGroup as ItemGroup, __experimentalItem as Item, __experimentalHStack as HStack, FlexBlock, Button } from '@wordpress/components'; import { Icon, chevronRight } from '@wordpress/icons'; import { focus } from '@wordpress/dom'; /** * Internal dependencies */ import usePatternsState from './hooks/use-patterns-state'; import BlockPatternList from '../block-patterns-list'; import PatternsExplorerModal from './block-patterns-explorer/explorer'; import MobileTabNavigation from './mobile-tab-navigation'; const noop = () => {}; // Preferred order of pattern categories. Any other categories should // be at the bottom without any re-ordering. const patternCategoriesOrder = ['featured', 'posts', 'text', 'gallery', 'call-to-action', 'banner', 'header', 'footer']; function usePatternsCategories(rootClientId) { const [allPatterns, allCategories] = usePatternsState(undefined, rootClientId); const hasRegisteredCategory = useCallback(pattern => { if (!pattern.categories || !pattern.categories.length) { return false; } return pattern.categories.some(cat => allCategories.some(category => category.name === cat)); }, [allCategories]); // Remove any empty categories. const populatedCategories = useMemo(() => { const categories = allCategories.filter(category => allPatterns.some(pattern => pattern.categories?.includes(category.name))).sort(({ name: aName }, { name: bName }) => { // Sort categories according to `patternCategoriesOrder`. let aIndex = patternCategoriesOrder.indexOf(aName); let bIndex = patternCategoriesOrder.indexOf(bName); // All other categories should come after that. if (aIndex < 0) aIndex = patternCategoriesOrder.length; if (bIndex < 0) bIndex = patternCategoriesOrder.length; return aIndex - bIndex; }); if (allPatterns.some(pattern => !hasRegisteredCategory(pattern)) && !categories.find(category => category.name === 'uncategorized')) { categories.push({ name: 'uncategorized', label: _x('Uncategorized') }); } return categories; }, [allPatterns, allCategories]); return populatedCategories; } export function BlockPatternsCategoryDialog({ rootClientId, onInsert, onHover, category, showTitlesAsTooltip }) { const container = useRef(); useEffect(() => { const timeout = setTimeout(() => { const [firstTabbable] = focus.tabbable.find(container.current); firstTabbable?.focus(); }); return () => clearTimeout(timeout); }, [category]); return createElement("div", { ref: container, className: "block-editor-inserter__patterns-category-dialog" }, createElement(BlockPatternsCategoryPanel, { rootClientId: rootClientId, onInsert: onInsert, onHover: onHover, category: category, showTitlesAsTooltip: showTitlesAsTooltip })); } export function BlockPatternsCategoryPanel({ rootClientId, onInsert, onHover = noop, category, showTitlesAsTooltip }) { const [allPatterns,, onClick] = usePatternsState(onInsert, rootClientId); const availableCategories = usePatternsCategories(rootClientId); const currentCategoryPatterns = useMemo(() => allPatterns.filter(pattern => { var _pattern$categories$f; if (category.name !== 'uncategorized') { return pattern.categories?.includes(category.name); } // The uncategorized category should show all the patterns without any category // or with no available category. const availablePatternCategories = (_pattern$categories$f = pattern.categories?.filter(cat => availableCategories.find(availableCategory => availableCategory.name === cat))) !== null && _pattern$categories$f !== void 0 ? _pattern$categories$f : []; return availablePatternCategories.length === 0; }), [allPatterns, category]); const currentShownPatterns = useAsyncList(currentCategoryPatterns); // Hide block pattern preview on unmount. useEffect(() => () => onHover(null), []); if (!currentCategoryPatterns.length) { return null; } return createElement("div", { className: "block-editor-inserter__patterns-category-panel" }, createElement("div", { className: "block-editor-inserter__patterns-category-panel-title" }, category.label), createElement("p", null, category.description), createElement(BlockPatternList, { shownPatterns: currentShownPatterns, blockPatterns: currentCategoryPatterns, onClickPattern: onClick, onHover: onHover, label: category.label, orientation: "vertical", category: category.label, isDraggable: true, showTitlesAsTooltip: showTitlesAsTooltip })); } function BlockPatternsTabs({ onSelectCategory, selectedCategory, onInsert, rootClientId }) { const [showPatternsExplorer, setShowPatternsExplorer] = useState(false); const categories = usePatternsCategories(rootClientId); const initialCategory = selectedCategory || categories[0]; const isMobile = useViewportMatch('medium', '<'); return createElement(Fragment, null, !isMobile && createElement("div", { className: "block-editor-inserter__block-patterns-tabs-container" }, createElement("nav", { "aria-label": __('Block pattern categories') }, createElement(ItemGroup, { role: "list", className: "block-editor-inserter__block-patterns-tabs" }, categories.map(category => createElement(Item, { role: "listitem", key: category.name, onClick: () => onSelectCategory(category), className: category === selectedCategory ? 'block-editor-inserter__patterns-category block-editor-inserter__patterns-selected-category' : 'block-editor-inserter__patterns-category', "aria-label": category.label, "aria-current": category === selectedCategory ? 'true' : undefined }, createElement(HStack, null, createElement(FlexBlock, null, category.label), createElement(Icon, { icon: chevronRight })))), createElement("div", { role: "listitem" }, createElement(Button, { className: "block-editor-inserter__patterns-explore-button", onClick: () => setShowPatternsExplorer(true), variant: "secondary" }, __('Explore all patterns')))))), isMobile && createElement(MobileTabNavigation, { categories: categories }, category => createElement(BlockPatternsCategoryPanel, { onInsert: onInsert, rootClientId: rootClientId, category: category, showTitlesAsTooltip: false })), showPatternsExplorer && createElement(PatternsExplorerModal, { initialCategory: initialCategory, patternCategories: categories, onModalClose: () => setShowPatternsExplorer(false) })); } export default BlockPatternsTabs; //# sourceMappingURL=block-patterns-tab.js.map