@wordpress/block-editor
Version:
321 lines (317 loc) • 10.8 kB
JavaScript
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
;