UNPKG

@wordpress/block-editor

Version:
200 lines (192 loc) 6.71 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _blocks = require("@wordpress/blocks"); var _components = require("@wordpress/components"); var _data = require("@wordpress/data"); var _element = require("@wordpress/element"); var _compose = require("@wordpress/compose"); var _draggableChip = _interopRequireDefault(require("./draggable-chip")); var _useScrollWhenDragging = _interopRequireDefault(require("./use-scroll-when-dragging")); var _store = require("../../store"); var _useBlockRefs = require("../block-list/use-block-props/use-block-refs"); var _useBlockDropZone = require("../use-block-drop-zone"); var _jsxRuntime = require("react/jsx-runtime"); /** * WordPress dependencies */ /** * Internal dependencies */ const BlockDraggable = ({ appendToOwnerDocument, children, clientIds, cloneClassname, elementId, onDragStart, onDragEnd, fadeWhenDisabled = false, dragComponent }) => { const { srcRootClientId, isDraggable, icon, visibleInserter, getBlockType } = (0, _data.useSelect)(select => { const { canMoveBlocks, getBlockRootClientId, getBlockName, getBlockAttributes, isBlockInsertionPointVisible } = select(_store.store); const { getBlockType: _getBlockType, getActiveBlockVariation } = select(_blocks.store); const rootClientId = getBlockRootClientId(clientIds[0]); const blockName = getBlockName(clientIds[0]); const variation = getActiveBlockVariation(blockName, getBlockAttributes(clientIds[0])); return { srcRootClientId: rootClientId, isDraggable: canMoveBlocks(clientIds), icon: variation?.icon || _getBlockType(blockName)?.icon, visibleInserter: isBlockInsertionPointVisible(), getBlockType: _getBlockType }; }, [clientIds]); const isDraggingRef = (0, _element.useRef)(false); const [startScrolling, scrollOnDragOver, stopScrolling] = (0, _useScrollWhenDragging.default)(); const { getAllowedBlocks, getBlockNamesByClientId, getBlockRootClientId } = (0, _data.useSelect)(_store.store); const { startDraggingBlocks, stopDraggingBlocks } = (0, _data.useDispatch)(_store.store); // Stop dragging blocks if the block draggable is unmounted. (0, _element.useEffect)(() => { return () => { if (isDraggingRef.current) { stopDraggingBlocks(); } }; }, []); // Find the root of the editor iframe. const blockEl = (0, _useBlockRefs.useBlockElement)(clientIds[0]); const editorRoot = blockEl?.closest('body'); /* * Add a dragover event listener to the editor root to track the blocks being dragged over. * The listener has to be inside the editor iframe otherwise the target isn't accessible. */ (0, _element.useEffect)(() => { if (!editorRoot || !fadeWhenDisabled) { return; } const onDragOver = event => { if (!event.target.closest('[data-block]')) { return; } const draggedBlockNames = getBlockNamesByClientId(clientIds); const targetClientId = event.target.closest('[data-block]').getAttribute('data-block'); const allowedBlocks = getAllowedBlocks(targetClientId); const targetBlockName = getBlockNamesByClientId([targetClientId])[0]; /* * Check if the target is valid to drop in. * If the target's allowedBlocks is an empty array, * it isn't a container block, in which case we check * its parent's validity instead. */ let dropTargetValid; if (allowedBlocks?.length === 0) { const targetRootClientId = getBlockRootClientId(targetClientId); const targetRootBlockName = getBlockNamesByClientId([targetRootClientId])[0]; const rootAllowedBlocks = getAllowedBlocks(targetRootClientId); dropTargetValid = (0, _useBlockDropZone.isDropTargetValid)(getBlockType, rootAllowedBlocks, draggedBlockNames, targetRootBlockName); } else { dropTargetValid = (0, _useBlockDropZone.isDropTargetValid)(getBlockType, allowedBlocks, draggedBlockNames, targetBlockName); } /* * Update the body class to reflect if drop target is valid. * This has to be done on the document body because the draggable * chip is rendered outside of the editor iframe. */ if (!dropTargetValid && !visibleInserter) { window?.document?.body?.classList?.add('block-draggable-invalid-drag-token'); } else { window?.document?.body?.classList?.remove('block-draggable-invalid-drag-token'); } }; const throttledOnDragOver = (0, _compose.throttle)(onDragOver, 200); editorRoot.addEventListener('dragover', throttledOnDragOver); return () => { editorRoot.removeEventListener('dragover', throttledOnDragOver); }; }, [clientIds, editorRoot, fadeWhenDisabled, getAllowedBlocks, getBlockNamesByClientId, getBlockRootClientId, getBlockType, visibleInserter]); if (!isDraggable) { return children({ draggable: false }); } const transferData = { type: 'block', srcClientIds: clientIds, srcRootClientId }; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Draggable, { appendToOwnerDocument: appendToOwnerDocument, cloneClassname: cloneClassname, __experimentalTransferDataType: "wp-blocks", transferData: transferData, onDragStart: event => { // Defer hiding the dragged source element to the next // frame to enable dragging. window.requestAnimationFrame(() => { startDraggingBlocks(clientIds); isDraggingRef.current = true; startScrolling(event); if (onDragStart) { onDragStart(); } }); }, onDragOver: scrollOnDragOver, onDragEnd: () => { stopDraggingBlocks(); isDraggingRef.current = false; stopScrolling(); if (onDragEnd) { onDragEnd(); } }, __experimentalDragComponent: // Check against `undefined` so that `null` can be used to disable // the default drag component. dragComponent !== undefined ? dragComponent : /*#__PURE__*/(0, _jsxRuntime.jsx)(_draggableChip.default, { count: clientIds.length, icon: icon, fadeWhenDisabled: true }), elementId: elementId, children: ({ onDraggableStart, onDraggableEnd }) => { return children({ draggable: true, onDragStart: onDraggableStart, onDragEnd: onDraggableEnd }); } }); }; var _default = exports.default = BlockDraggable; //# sourceMappingURL=index.js.map