UNPKG

@wordpress/block-editor

Version:
321 lines (317 loc) 10.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.GridVisualizer = GridVisualizer; var _clsx = _interopRequireDefault(require("clsx")); var _element = require("@wordpress/element"); var _data = require("@wordpress/data"); var _compose = require("@wordpress/compose"); var _useBlockRefs = require("../block-list/use-block-props/use-block-refs"); var _cover = _interopRequireDefault(require("../block-popover/cover")); var _utils = require("./utils"); var _store = require("../../store"); var _useGetNumberOfBlocksBeforeCell = require("./use-get-number-of-blocks-before-cell"); var _buttonBlockAppender = _interopRequireDefault(require("../button-block-appender")); var _lockUnlock = require("../../lock-unlock"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function GridVisualizer({ clientId, contentRef, parentLayout }) { const isDistractionFree = (0, _data.useSelect)(select => select(_store.store).getSettings().isDistractionFree, []); const gridElement = (0, _useBlockRefs.useBlockElement)(clientId); if (isDistractionFree || !gridElement) { return null; } const isManualGrid = parentLayout?.isManualPlacement && window.__experimentalEnableGridInteractivity; return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVisualizerGrid, { gridClientId: clientId, gridElement: gridElement, isManualGrid: isManualGrid, ref: contentRef }); } const GridVisualizerGrid = (0, _element.forwardRef)(({ gridClientId, gridElement, isManualGrid }, ref) => { const [gridInfo, setGridInfo] = (0, _element.useState)(() => (0, _utils.getGridInfo)(gridElement)); const [isDroppingAllowed, setIsDroppingAllowed] = (0, _element.useState)(false); (0, _element.useEffect)(() => { const resizeCallback = () => setGridInfo((0, _utils.getGridInfo)(gridElement)); // Both border-box and content-box are observed as they may change // independently. This requires two observers because a single one // can’t be made to monitor both on the same element. const borderBoxSpy = new window.ResizeObserver(resizeCallback); borderBoxSpy.observe(gridElement, { box: 'border-box' }); const contentBoxSpy = new window.ResizeObserver(resizeCallback); contentBoxSpy.observe(gridElement); return () => { borderBoxSpy.disconnect(); contentBoxSpy.disconnect(); }; }, [gridElement]); (0, _element.useEffect)(() => { function onGlobalDrag() { setIsDroppingAllowed(true); } function onGlobalDragEnd() { setIsDroppingAllowed(false); } document.addEventListener('drag', onGlobalDrag); document.addEventListener('dragend', onGlobalDragEnd); return () => { document.removeEventListener('drag', onGlobalDrag); document.removeEventListener('dragend', onGlobalDragEnd); }; }, []); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_cover.default, { className: (0, _clsx.default)('block-editor-grid-visualizer', { 'is-dropping-allowed': isDroppingAllowed }), clientId: gridClientId, __unstablePopoverSlot: "__unstable-block-tools-after", children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { ref: ref, className: "block-editor-grid-visualizer__grid", style: gridInfo.style, children: isManualGrid ? /*#__PURE__*/(0, _jsxRuntime.jsx)(ManualGridVisualizer, { gridClientId: gridClientId, gridInfo: gridInfo }) : Array.from({ length: gridInfo.numItems }, (_, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVisualizerCell, { color: gridInfo.currentColor }, i)) }) }); }); function ManualGridVisualizer({ gridClientId, gridInfo }) { const [highlightedRect, setHighlightedRect] = (0, _element.useState)(null); const gridItemStyles = (0, _data.useSelect)(select => { const { getBlockOrder, getBlockStyles } = (0, _lockUnlock.unlock)(select(_store.store)); const blockOrder = getBlockOrder(gridClientId); return getBlockStyles(blockOrder); }, [gridClientId]); const occupiedRects = (0, _element.useMemo)(() => { const rects = []; for (const style of Object.values(gridItemStyles)) { var _style$layout; const { columnStart, rowStart, columnSpan = 1, rowSpan = 1 } = (_style$layout = style?.layout) !== null && _style$layout !== void 0 ? _style$layout : {}; if (!columnStart || !rowStart) { continue; } rects.push(new _utils.GridRect({ columnStart, rowStart, columnSpan, rowSpan })); } return rects; }, [gridItemStyles]); return (0, _utils.range)(1, gridInfo.numRows).map(row => (0, _utils.range)(1, gridInfo.numColumns).map(column => { var _highlightedRect$cont; const isCellOccupied = occupiedRects.some(rect => rect.contains(column, row)); const isHighlighted = (_highlightedRect$cont = highlightedRect?.contains(column, row)) !== null && _highlightedRect$cont !== void 0 ? _highlightedRect$cont : false; return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVisualizerCell, { color: gridInfo.currentColor, className: isHighlighted && 'is-highlighted', children: isCellOccupied ? /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVisualizerDropZone, { column: column, row: row, gridClientId: gridClientId, gridInfo: gridInfo, setHighlightedRect: setHighlightedRect }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVisualizerAppender, { column: column, row: row, gridClientId: gridClientId, gridInfo: gridInfo, setHighlightedRect: setHighlightedRect }) }, `${row}-${column}`); })); } function GridVisualizerCell({ color, children, className }) { return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: (0, _clsx.default)('block-editor-grid-visualizer__cell', className), style: { boxShadow: `inset 0 0 0 1px color-mix(in srgb, ${color} 20%, #0000)`, color }, children: children }); } function useGridVisualizerDropZone(column, row, gridClientId, gridInfo, setHighlightedRect) { const { getBlockAttributes, getBlockRootClientId, canInsertBlockType, getBlockName } = (0, _data.useSelect)(_store.store); const { updateBlockAttributes, moveBlocksToPosition, __unstableMarkNextChangeAsNotPersistent } = (0, _data.useDispatch)(_store.store); const getNumberOfBlocksBeforeCell = (0, _useGetNumberOfBlocksBeforeCell.useGetNumberOfBlocksBeforeCell)(gridClientId, gridInfo.numColumns); return useDropZoneWithValidation({ validateDrag(srcClientId) { const blockName = getBlockName(srcClientId); if (!canInsertBlockType(blockName, gridClientId)) { return false; } const attributes = getBlockAttributes(srcClientId); const rect = new _utils.GridRect({ columnStart: column, rowStart: row, columnSpan: attributes.style?.layout?.columnSpan, rowSpan: attributes.style?.layout?.rowSpan }); const isInBounds = new _utils.GridRect({ columnSpan: gridInfo.numColumns, rowSpan: gridInfo.numRows }).containsRect(rect); return isInBounds; }, onDragEnter(srcClientId) { const attributes = getBlockAttributes(srcClientId); setHighlightedRect(new _utils.GridRect({ columnStart: column, rowStart: row, columnSpan: attributes.style?.layout?.columnSpan, rowSpan: attributes.style?.layout?.rowSpan })); }, onDragLeave() { // onDragEnter can be called before onDragLeave if the user moves // their mouse quickly, so only clear the highlight if it was set // by this cell. setHighlightedRect(prevHighlightedRect => prevHighlightedRect?.columnStart === column && prevHighlightedRect?.rowStart === row ? null : prevHighlightedRect); }, onDrop(srcClientId) { setHighlightedRect(null); const attributes = getBlockAttributes(srcClientId); updateBlockAttributes(srcClientId, { style: { ...attributes.style, layout: { ...attributes.style?.layout, columnStart: column, rowStart: row } } }); __unstableMarkNextChangeAsNotPersistent(); moveBlocksToPosition([srcClientId], getBlockRootClientId(srcClientId), gridClientId, getNumberOfBlocksBeforeCell(column, row)); } }); } function GridVisualizerDropZone({ column, row, gridClientId, gridInfo, setHighlightedRect }) { return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { className: "block-editor-grid-visualizer__drop-zone", ref: useGridVisualizerDropZone(column, row, gridClientId, gridInfo, setHighlightedRect) }); } function GridVisualizerAppender({ column, row, gridClientId, gridInfo, setHighlightedRect }) { const { updateBlockAttributes, moveBlocksToPosition, __unstableMarkNextChangeAsNotPersistent } = (0, _data.useDispatch)(_store.store); const getNumberOfBlocksBeforeCell = (0, _useGetNumberOfBlocksBeforeCell.useGetNumberOfBlocksBeforeCell)(gridClientId, gridInfo.numColumns); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_buttonBlockAppender.default, { rootClientId: gridClientId, className: "block-editor-grid-visualizer__appender", ref: useGridVisualizerDropZone(column, row, gridClientId, gridInfo, setHighlightedRect), style: { color: gridInfo.currentColor }, onSelect: block => { if (!block) { return; } updateBlockAttributes(block.clientId, { style: { layout: { columnStart: column, rowStart: row } } }); __unstableMarkNextChangeAsNotPersistent(); moveBlocksToPosition([block.clientId], gridClientId, gridClientId, getNumberOfBlocksBeforeCell(column, row)); } }); } function useDropZoneWithValidation({ validateDrag, onDragEnter, onDragLeave, onDrop }) { const { getDraggedBlockClientIds } = (0, _data.useSelect)(_store.store); return (0, _compose.__experimentalUseDropZone)({ onDragEnter() { const [srcClientId] = getDraggedBlockClientIds(); if (srcClientId && validateDrag(srcClientId)) { onDragEnter(srcClientId); } }, onDragLeave() { onDragLeave(); }, onDrop() { const [srcClientId] = getDraggedBlockClientIds(); if (srcClientId && validateDrag(srcClientId)) { onDrop(srcClientId); } } }); } //# sourceMappingURL=grid-visualizer.js.map