UNPKG

@wordpress/block-editor

Version:
247 lines (212 loc) 8.24 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = InsertionPoint; exports.InsertionPointOpenRef = void 0; var _element = require("@wordpress/element"); var _classnames = _interopRequireDefault(require("classnames")); var _data = require("@wordpress/data"); var _components = require("@wordpress/components"); var _i18n = require("@wordpress/i18n"); var _inserter = _interopRequireDefault(require("../inserter")); var _store = require("../../store"); var _useBlockRefs = require("../block-list/use-block-props/use-block-refs"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const InsertionPointOpenRef = (0, _element.createContext)(); exports.InsertionPointOpenRef = InsertionPointOpenRef; function InsertionPointPopover() { const { selectBlock } = (0, _data.useDispatch)(_store.store); const openRef = (0, _element.useContext)(InsertionPointOpenRef); const ref = (0, _element.useRef)(); const { orientation, isHidden, previousClientId, nextClientId, rootClientId, isInserterShown } = (0, _data.useSelect)(select => { var _getBlockListSettings; const { getBlockOrder, getBlockListSettings, getMultiSelectedBlockClientIds, getSelectedBlockClientId, hasMultiSelection, getSettings, getBlockInsertionPoint } = select(_store.store); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder(insertionPoint.rootClientId); const targetClientId = order[insertionPoint.index - 1]; const targetRootClientId = insertionPoint.rootClientId; const blockOrder = getBlockOrder(targetRootClientId); if (!blockOrder.length) { return {}; } const previous = targetClientId ? targetClientId : blockOrder[blockOrder.length - 1]; const isLast = previous === blockOrder[blockOrder.length - 1]; const next = isLast ? null : blockOrder[blockOrder.indexOf(previous) + 1]; const { hasReducedUI } = getSettings(); const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); const selectedBlockClientId = getSelectedBlockClientId(); const blockOrientation = ((_getBlockListSettings = getBlockListSettings(targetRootClientId)) === null || _getBlockListSettings === void 0 ? void 0 : _getBlockListSettings.orientation) || 'vertical'; return { previousClientId: previous, nextClientId: next, isHidden: hasReducedUI || (hasMultiSelection() ? next && multiSelectedBlockClientIds.includes(next) : next && blockOrientation === 'vertical' && next === selectedBlockClientId), orientation: blockOrientation, clientId: targetClientId, rootClientId: targetRootClientId, isInserterShown: insertionPoint === null || insertionPoint === void 0 ? void 0 : insertionPoint.__unstableWithInserter }; }, []); const previousElement = (0, _useBlockRefs.__unstableUseBlockElement)(previousClientId); const nextElement = (0, _useBlockRefs.__unstableUseBlockElement)(nextClientId); const style = (0, _element.useMemo)(() => { if (!previousElement) { return {}; } const previousRect = previousElement.getBoundingClientRect(); const nextRect = nextElement ? nextElement.getBoundingClientRect() : null; if (orientation === 'vertical') { return { width: previousElement.offsetWidth, height: nextRect ? nextRect.top - previousRect.bottom : 0 }; } let width = 0; if (nextElement) { width = (0, _i18n.isRTL)() ? previousRect.left - nextRect.right : nextRect.left - previousRect.right; } return { width, height: previousElement.offsetHeight }; }, [previousElement, nextElement]); const getAnchorRect = (0, _element.useCallback)(() => { const previousRect = previousElement.getBoundingClientRect(); const nextRect = nextElement ? nextElement.getBoundingClientRect() : null; if (orientation === 'vertical') { if ((0, _i18n.isRTL)()) { return { top: previousRect.bottom, left: previousRect.right, right: previousRect.left, bottom: nextRect ? nextRect.top : previousRect.bottom }; } return { top: previousRect.bottom, left: previousRect.left, right: previousRect.right, bottom: nextRect ? nextRect.top : previousRect.bottom }; } if ((0, _i18n.isRTL)()) { return { top: previousRect.top, left: nextRect ? nextRect.right : previousRect.left, right: previousRect.left, bottom: previousRect.bottom }; } return { top: previousRect.top, left: previousRect.right, right: nextRect ? nextRect.left : previousRect.right, bottom: previousRect.bottom }; }, [previousElement, nextElement]); if (!previousElement) { return null; } const className = (0, _classnames.default)('block-editor-block-list__insertion-point', 'is-' + orientation); function onClick(event) { if (event.target === ref.current && nextClientId) { selectBlock(nextClientId, -1); } } function onFocus(event) { // Only handle click on the wrapper specifically, and not an event // bubbled from the inserter itself. if (event.target !== ref.current) { openRef.current = true; } } // Only show the inserter when there's a `nextElement` (a block after the // insertion point). At the end of the block list the trailing appender // should serve the purpose of inserting blocks. const showInsertionPointInserter = !isHidden && nextElement && isInserterShown; // Show the indicator if the insertion point inserter is visible, or if // the `showInsertionPoint` state is `true`. The latter is generally true // when hovering blocks for insertion in the block library. const showInsertionPointIndicator = showInsertionPointInserter || !isHidden; /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ // While ideally it would be enough to capture the // bubbling focus event from the Inserter, due to the // characteristics of click focusing of `button`s in // Firefox and Safari, it is not reliable. // // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus return (0, _element.createElement)(_components.Popover, { noArrow: true, animate: false, getAnchorRect: getAnchorRect, focusOnMount: false, className: "block-editor-block-list__insertion-point-popover", __unstableSlotName: "block-toolbar" }, (0, _element.createElement)("div", { ref: ref, tabIndex: -1, onClick: onClick, onFocus: onFocus, className: (0, _classnames.default)(className, { 'is-with-inserter': showInsertionPointInserter }), style: style }, showInsertionPointIndicator && (0, _element.createElement)("div", { className: "block-editor-block-list__insertion-point-indicator" }), showInsertionPointInserter && (0, _element.createElement)("div", { className: (0, _classnames.default)('block-editor-block-list__insertion-point-inserter') }, (0, _element.createElement)(_inserter.default, { position: "bottom center", clientId: nextClientId, rootClientId: rootClientId, __experimentalIsQuick: true, onToggle: isOpen => { openRef.current = isOpen; }, onSelectOrClose: () => { openRef.current = false; } })))); /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ } function InsertionPoint({ children }) { const isVisible = (0, _data.useSelect)(select => { const { isMultiSelecting, isBlockInsertionPointVisible } = select(_store.store); return isBlockInsertionPointVisible() && !isMultiSelecting(); }, []); return (0, _element.createElement)(InsertionPointOpenRef.Provider, { value: (0, _element.useRef)(false) }, isVisible && (0, _element.createElement)(InsertionPointPopover, null), children); } //# sourceMappingURL=insertion-point.js.map