UNPKG

@wordpress/block-editor

Version:
200 lines (191 loc) 6.34 kB
import { createElement, Fragment } from "@wordpress/element"; /** * External dependencies */ import classnames from 'classnames'; /** * WordPress dependencies */ import { __experimentalTreeGridCell as TreeGridCell, __experimentalTreeGridItem as TreeGridItem, MenuGroup, MenuItem } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { moreVertical } from '@wordpress/icons'; import { useState, useRef, useEffect } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** * Internal dependencies */ import BlockNavigationLeaf from './leaf'; import { BlockMoverUpButton, BlockMoverDownButton } from '../block-mover/button'; import BlockNavigationBlockContents from './block-contents'; import BlockSettingsDropdown from '../block-settings-menu/block-settings-dropdown'; import { useBlockNavigationContext } from './context'; import { store as blockEditorStore } from '../../store'; export default function BlockNavigationBlock({ block, isSelected, isBranchSelected, isLastOfSelectedBranch, onClick, position, level, rowCount, siblingBlockCount, showBlockMovers, path }) { const cellRef = useRef(null); const [isHovered, setIsHovered] = useState(false); const { clientId } = block; const { isDragging, blockParents } = useSelect(select => { const { isBlockBeingDragged, isAncestorBeingDragged, getBlockParents } = select(blockEditorStore); return { isDragging: isBlockBeingDragged(clientId) || isAncestorBeingDragged(clientId), blockParents: getBlockParents(clientId) }; }, [clientId]); const { selectBlock: selectEditorBlock, toggleBlockHighlight } = useDispatch(blockEditorStore); const hasSiblings = siblingBlockCount > 0; const hasRenderedMovers = showBlockMovers && hasSiblings; const moverCellClassName = classnames('block-editor-block-navigation-block__mover-cell', { 'is-visible': isHovered }); const { __experimentalFeatures: withExperimentalFeatures, __experimentalPersistentListViewFeatures: withExperimentalPersistentListViewFeatures, isTreeGridMounted } = useBlockNavigationContext(); const blockNavigationBlockSettingsClassName = classnames('block-editor-block-navigation-block__menu-cell', { 'is-visible': isHovered }); // If BlockNavigation has experimental features related to the Persistent List View, // only focus the selected list item on mount; otherwise the list would always // try to steal the focus from the editor canvas. useEffect(() => { if (withExperimentalPersistentListViewFeatures && !isTreeGridMounted && isSelected) { cellRef.current.focus(); } }, []); // If BlockNavigation has experimental features (such as drag and drop) enabled, // leave the focus handling as it was before, to avoid accidental regressions. useEffect(() => { if (withExperimentalFeatures && isSelected) { cellRef.current.focus(); } }, [withExperimentalFeatures, isSelected]); const highlightBlock = withExperimentalPersistentListViewFeatures ? toggleBlockHighlight : () => {}; const onMouseEnter = () => { setIsHovered(true); highlightBlock(clientId, true); }; const onMouseLeave = () => { setIsHovered(false); highlightBlock(clientId, false); }; const classes = classnames({ 'is-selected': isSelected, 'is-branch-selected': withExperimentalPersistentListViewFeatures && isBranchSelected, 'is-last-of-selected-branch': withExperimentalPersistentListViewFeatures && isLastOfSelectedBranch, 'is-dragging': isDragging }); return createElement(BlockNavigationLeaf, { className: classes, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onFocus: onMouseEnter, onBlur: onMouseLeave, level: level, position: position, rowCount: rowCount, path: path, id: `block-navigation-block-${clientId}`, "data-block": clientId }, createElement(TreeGridCell, { className: "block-editor-block-navigation-block__contents-cell", colSpan: hasRenderedMovers ? undefined : 2, ref: cellRef }, ({ ref, tabIndex, onFocus }) => createElement("div", { className: "block-editor-block-navigation-block__contents-container" }, createElement(BlockNavigationBlockContents, { block: block, onClick: () => onClick(block.clientId), isSelected: isSelected, position: position, siblingBlockCount: siblingBlockCount, level: level, ref: ref, tabIndex: tabIndex, onFocus: onFocus }))), hasRenderedMovers && createElement(Fragment, null, createElement(TreeGridCell, { className: moverCellClassName, withoutGridItem: true }, createElement(TreeGridItem, null, ({ ref, tabIndex, onFocus }) => createElement(BlockMoverUpButton, { orientation: "vertical", clientIds: [clientId], ref: ref, tabIndex: tabIndex, onFocus: onFocus })), createElement(TreeGridItem, null, ({ ref, tabIndex, onFocus }) => createElement(BlockMoverDownButton, { orientation: "vertical", clientIds: [clientId], ref: ref, tabIndex: tabIndex, onFocus: onFocus })))), withExperimentalFeatures && createElement(TreeGridCell, { className: blockNavigationBlockSettingsClassName }, ({ ref, tabIndex, onFocus }) => createElement(BlockSettingsDropdown, { clientIds: [clientId], icon: moreVertical, toggleProps: { ref, tabIndex, onFocus }, disableOpenOnArrowDown: true, __experimentalSelectBlock: onClick }, ({ onClose }) => createElement(MenuGroup, null, createElement(MenuItem, { onClick: async () => { if (blockParents.length) { // If the block to select is inside a dropdown, we need to open the dropdown. // Otherwise focus won't transfer to the block. for (const parent of blockParents) { await selectEditorBlock(parent); } } else { // If clientId is already selected, it won't be focused (see block-wrapper.js) // This removes the selection first to ensure the focus will always switch. await selectEditorBlock(null); } await selectEditorBlock(clientId); onClose(); } }, __('Go to block')))))); } //# sourceMappingURL=block.js.map