UNPKG

@gechiui/block-editor

Version:
344 lines (305 loc) 10.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.InsertionPointOpenRef = void 0; exports.default = InsertionPoint; var _element = require("@gechiui/element"); var _classnames = _interopRequireDefault(require("classnames")); var _data = require("@gechiui/data"); var _components = require("@gechiui/components"); var _compose = require("@gechiui/compose"); var _i18n = require("@gechiui/i18n"); var _inserter = _interopRequireDefault(require("../inserter")); var _store = require("../../store"); var _useBlockRefs = require("../block-list/use-block-props/use-block-refs"); var _usePopoverScroll = require("./use-popover-scroll"); /** * External dependencies */ /** * GeChiUI dependencies */ /** * Internal dependencies */ const InsertionPointOpenRef = (0, _element.createContext)(); exports.InsertionPointOpenRef = InsertionPointOpenRef; function InsertionPointPopover(_ref) { let { __unstablePopoverSlot, __unstableContentRef } = _ref; const { selectBlock } = (0, _data.useDispatch)(_store.store); const openRef = (0, _element.useContext)(InsertionPointOpenRef); const ref = (0, _element.useRef)(); const { orientation, previousClientId, nextClientId, rootClientId, isInserterShown } = (0, _data.useSelect)(select => { var _getBlockListSettings; const { getBlockOrder, getBlockListSettings, getBlockInsertionPoint, isBlockBeingDragged, getPreviousBlockClientId, getNextBlockClientId } = select(_store.store); const insertionPoint = getBlockInsertionPoint(); const order = getBlockOrder(insertionPoint.rootClientId); if (!order.length) { return {}; } let _previousClientId = order[insertionPoint.index - 1]; let _nextClientId = order[insertionPoint.index]; while (isBlockBeingDragged(_previousClientId)) { _previousClientId = getPreviousBlockClientId(_previousClientId); } while (isBlockBeingDragged(_nextClientId)) { _nextClientId = getNextBlockClientId(_nextClientId); } return { previousClientId: _previousClientId, nextClientId: _nextClientId, orientation: ((_getBlockListSettings = getBlockListSettings(insertionPoint.rootClientId)) === null || _getBlockListSettings === void 0 ? void 0 : _getBlockListSettings.orientation) || 'vertical', rootClientId: insertionPoint.rootClientId, isInserterShown: insertionPoint === null || insertionPoint === void 0 ? void 0 : insertionPoint.__unstableWithInserter }; }, []); const previousElement = (0, _useBlockRefs.__unstableUseBlockElement)(previousClientId); const nextElement = (0, _useBlockRefs.__unstableUseBlockElement)(nextClientId); const isVertical = orientation === 'vertical'; const style = (0, _element.useMemo)(() => { if (!previousElement && !nextElement) { return {}; } const previousRect = previousElement ? previousElement.getBoundingClientRect() : null; const nextRect = nextElement ? nextElement.getBoundingClientRect() : null; if (isVertical) { return { width: previousElement ? previousElement.offsetWidth : nextElement.offsetWidth, height: nextRect && previousRect ? nextRect.top - previousRect.bottom : 0 }; } let width = 0; if (previousRect && nextRect) { width = (0, _i18n.isRTL)() ? previousRect.left - nextRect.right : nextRect.left - previousRect.right; } return { width, height: previousElement ? previousElement.offsetHeight : nextElement.offsetHeight }; }, [previousElement, nextElement]); const getAnchorRect = (0, _element.useCallback)(() => { if (!previousElement && !nextElement) { return {}; } const { ownerDocument } = previousElement || nextElement; const previousRect = previousElement ? previousElement.getBoundingClientRect() : null; const nextRect = nextElement ? nextElement.getBoundingClientRect() : null; if (isVertical) { if ((0, _i18n.isRTL)()) { return { top: previousRect ? previousRect.bottom : nextRect.top, left: previousRect ? previousRect.right : nextRect.right, right: previousRect ? previousRect.left : nextRect.left, bottom: nextRect ? nextRect.top : previousRect.bottom, ownerDocument }; } return { top: previousRect ? previousRect.bottom : nextRect.top, left: previousRect ? previousRect.left : nextRect.left, right: previousRect ? previousRect.right : nextRect.right, bottom: nextRect ? nextRect.top : previousRect.bottom, ownerDocument }; } if ((0, _i18n.isRTL)()) { return { top: previousRect ? previousRect.top : nextRect.top, left: previousRect ? previousRect.left : nextRect.right, right: nextRect ? nextRect.right : previousRect.left, bottom: previousRect ? previousRect.bottom : nextRect.bottom, ownerDocument }; } return { top: previousRect ? previousRect.top : nextRect.top, left: previousRect ? previousRect.right : nextRect.left, right: nextRect ? nextRect.left : previousRect.right, bottom: previousRect ? previousRect.bottom : nextRect.bottom, ownerDocument }; }, [previousElement, nextElement]); const popoverScrollRef = (0, _usePopoverScroll.usePopoverScroll)(__unstableContentRef); const disableMotion = (0, _compose.useReducedMotion)(); 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 in-between inserter between blocks, so when there's a // previous and a next element. const showInsertionPointInserter = previousElement && nextElement && isInserterShown; // Define animation variants for the line element. const horizontalLine = { start: { width: 0, top: '50%', bottom: '50%', x: 0 }, rest: { width: 4, top: 0, bottom: 0, x: -2 }, hover: { width: 4, top: 0, bottom: 0, x: -2 } }; const verticalLine = { start: { height: 0, left: '50%', right: '50%', y: 0 }, rest: { height: 4, left: 0, right: 0, y: -2 }, hover: { height: 4, left: 0, right: 0, y: -2 } }; const lineVariants = { // Initial position starts from the center and invisible. start: { ...(!isVertical ? horizontalLine.start : verticalLine.start), opacity: 0 }, // The line expands to fill the container. If the inserter is visible it // is delayed so it appears orchestrated. rest: { ...(!isVertical ? horizontalLine.rest : verticalLine.rest), opacity: 1, borderRadius: '2px', transition: { delay: showInsertionPointInserter ? 0.4 : 0 } }, hover: { ...(!isVertical ? horizontalLine.hover : verticalLine.hover), opacity: 1, borderRadius: '2px', transition: { delay: 0.4 } } }; const inserterVariants = { start: { scale: disableMotion ? 1 : 0 }, rest: { scale: 1, transition: { delay: 0.2 } } }; /* 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, { ref: popoverScrollRef, noArrow: true, animate: false, getAnchorRect: getAnchorRect, focusOnMount: false, className: "block-editor-block-list__insertion-point-popover" // Render in the old slot if needed for backward compatibility, // otherwise render in place (not in the the default popover slot). , __unstableSlotName: __unstablePopoverSlot || null // Forces a remount of the popover when its position changes // This makes sure the popover doesn't animate from its previous position. , key: nextClientId + '--' + rootClientId }, (0, _element.createElement)(_components.__unstableMotion.div, { layout: !disableMotion, initial: disableMotion ? 'rest' : 'start', animate: "rest", whileHover: "hover", whileTap: "pressed", exit: "start", ref: ref, tabIndex: -1, onClick: onClick, onFocus: onFocus, className: (0, _classnames.default)(className, { 'is-with-inserter': showInsertionPointInserter }), style: style }, (0, _element.createElement)(_components.__unstableMotion.div, { variants: lineVariants, className: "block-editor-block-list__insertion-point-indicator" }), showInsertionPointInserter && (0, _element.createElement)(_components.__unstableMotion.div, { variants: inserterVariants, 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(_ref2) { let { children, __unstablePopoverSlot, __unstableContentRef } = _ref2; const isVisible = (0, _data.useSelect)(select => { return select(_store.store).isBlockInsertionPointVisible(); }, []); return (0, _element.createElement)(InsertionPointOpenRef.Provider, { value: (0, _element.useRef)(false) }, isVisible && (0, _element.createElement)(InsertionPointPopover, { __unstablePopoverSlot: __unstablePopoverSlot, __unstableContentRef: __unstableContentRef }), children); } //# sourceMappingURL=insertion-point.js.map