@wordpress/block-editor
Version:
200 lines (192 loc) • 6.71 kB
JavaScript
;
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