UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

250 lines (247 loc) 12.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.DropTargetLayoutNativeAnchorSupport = exports.DropTargetLayout = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = require("react"); var _react2 = require("@emotion/react"); var _editorSharedStyles = require("@atlaskit/editor-shared-styles"); var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box"); var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _decorationsCommon = require("../pm-plugins/decorations-common"); var _activeAnchorTracker = require("../pm-plugins/utils/active-anchor-tracker"); var _anchorUtils = require("../pm-plugins/utils/anchor-utils"); var _updateSelection = require("../pm-plugins/utils/update-selection"); var _domAttrName = require("./utils/dom-attr-name"); /** * @jsxRuntime classic * @jsx jsx */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports // 8px gap + 16px on left and right var DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH = 40; var dropTargetLayoutStyle = (0, _react2.css)({ height: '100%', width: "".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px"), transform: 'translateX(-50%)', zIndex: 120, position: 'relative', display: 'flex', justifyContent: 'center' }); var dropTargetLayoutHintStyle = (0, _react2.css)({ height: '100%', position: 'relative', borderRight: "var(--ds-border-width, 1px)".concat(" dashed ", "var(--ds-border-focused, #4688EC)"), width: 0 }); var DropTargetLayout = exports.DropTargetLayout = function DropTargetLayout(props) { var _ref$current, _api$blockControls; var api = props.api, getPos = props.getPos, parent = props.parent, anchorRectCache = props.anchorRectCache; var ref = (0, _react.useRef)(null); var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), isDraggedOver = _useState2[0], setIsDraggedOver = _useState2[1]; var anchorName = (0, _decorationsCommon.getNodeAnchor)(parent); var nextNodeAnchorName = (_ref$current = ref.current) === null || _ref$current === void 0 || (_ref$current = _ref$current.parentElement) === null || _ref$current === void 0 || (_ref$current = _ref$current.nextElementSibling) === null || _ref$current === void 0 ? void 0 : _ref$current.getAttribute((0, _domAttrName.getAnchorAttrName)()); var height = '100%'; if (nextNodeAnchorName) { if ((0, _anchorUtils.isAnchorSupported)()) { height = "anchor-size(".concat(nextNodeAnchorName, " height)"); } else if (anchorRectCache) { var layoutColumnRect = anchorRectCache.getRect(nextNodeAnchorName); height = "".concat((layoutColumnRect === null || layoutColumnRect === void 0 ? void 0 : layoutColumnRect.height) || 0, "px"); } } var dropTargetStackLayoutHintStyle = (0, _react2.css)((0, _defineProperty2.default)({}, "@container layout-area (max-width:".concat(_editorSharedStyles.layoutBreakpointWidth.MEDIUM - 1, "px)"), { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values height: height, marginTop: "var(--ds-space-050, 4px)" })); var _useActiveAnchorTrack = (0, _activeAnchorTracker.useActiveAnchorTracker)(anchorName), _useActiveAnchorTrack2 = (0, _slicedToArray2.default)(_useActiveAnchorTrack, 1), isActiveAnchor = _useActiveAnchorTrack2[0]; var _ref = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {}, activeNode = _ref.activeNode; var onDrop = (0, _react.useCallback)(function () { if (!activeNode) { return; } var to = getPos(); var mappedTo; if (to !== undefined) { var _api$core, _api$core2; var from = activeNode.pos; api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) { var _api$blockControls2; var tr = _ref2.tr; api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.moveToLayout(from, to)({ tr: tr }); var insertColumnStep = (0, _updateSelection.getInsertLayoutStep)(tr); mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from; return tr; }); api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref3) { var tr = _ref3.tr; if (mappedTo !== undefined) { (0, _updateSelection.updateSelection)(tr, mappedTo); } return tr; }); } }, [api, getPos, activeNode]); (0, _react.useEffect)(function () { if (ref.current) { return (0, _adapter.dropTargetForElements)({ element: ref.current, onDragEnter: function onDragEnter() { setIsDraggedOver(true); }, onDragLeave: function onDragLeave() { setIsDraggedOver(false); }, onDrop: onDrop }); } }, [onDrop]); if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType) === 'layoutSection') { return null; } return (0, _react2.jsx)("div", { ref: ref // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage , css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle], "data-testid": "block-ctrl-drop-indicator" }, isDraggedOver ? (0, _react2.jsx)(_box.DropIndicator, { edge: "right", gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px") }) : (isActiveAnchor || (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) && (0, _react2.jsx)("div", { "data-testid": "block-ctrl-drop-hint", css: dropTargetLayoutHintStyle })); }; var DropTargetLayoutNativeAnchorSupport = exports.DropTargetLayoutNativeAnchorSupport = function DropTargetLayoutNativeAnchorSupport(props) { var _api$blockControls3; var api = props.api, getPos = props.getPos, parent = props.parent, anchorRectCache = props.anchorRectCache; var ref = (0, _react.useRef)(null); var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), isDraggedOver = _useState4[0], setIsDraggedOver = _useState4[1]; var anchorName = (0, _decorationsCommon.getNodeAnchor)(parent); var _useState5 = (0, _react.useState)(null), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), nextNodeAnchorName = _useState6[0], setNextNodeAnchorName = _useState6[1]; var readNextNodeAnchor = (0, _react.useCallback)(function () { var _ref$current2, _nextElementSibling$g; var nextElementSibling = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 || (_ref$current2 = _ref$current2.parentElement) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.nextElementSibling; var attrName = (0, _domAttrName.getAnchorAttrName)(); var nextAnchorName = (_nextElementSibling$g = nextElementSibling === null || nextElementSibling === void 0 ? void 0 : nextElementSibling.getAttribute(attrName)) !== null && _nextElementSibling$g !== void 0 ? _nextElementSibling$g : null; setNextNodeAnchorName(function (prev) { return prev === nextAnchorName ? prev : nextAnchorName; }); }, []); var height = (0, _react.useMemo)(function () { if (nextNodeAnchorName) { if ((0, _anchorUtils.isAnchorSupported)()) { return "anchor-size(".concat(nextNodeAnchorName, " height)"); } else if (anchorRectCache) { var layoutColumnRect = anchorRectCache.getRect(nextNodeAnchorName); return "".concat((layoutColumnRect === null || layoutColumnRect === void 0 ? void 0 : layoutColumnRect.height) || 0, "px"); } } // Stacked mode fallback: minimal height to avoid oversized hint on first render return '0px'; }, [nextNodeAnchorName, anchorRectCache]); (0, _react.useLayoutEffect)(function () { var raf = requestAnimationFrame(function () { readNextNodeAnchor(); }); return function () { return cancelAnimationFrame(raf); }; }, [readNextNodeAnchor]); var dropTargetStackLayoutHintStyle = (0, _react2.css)((0, _defineProperty2.default)({}, "@container layout-area (max-width:".concat(_editorSharedStyles.layoutBreakpointWidth.MEDIUM - 1, "px)"), { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values height: height, marginTop: "var(--ds-space-050, 4px)" })); var _useActiveAnchorTrack3 = (0, _activeAnchorTracker.useActiveAnchorTracker)(anchorName), _useActiveAnchorTrack4 = (0, _slicedToArray2.default)(_useActiveAnchorTrack3, 1), isActiveAnchor = _useActiveAnchorTrack4[0]; var _ref4 = (api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.sharedState.currentState()) || {}, activeNode = _ref4.activeNode; var onDrop = (0, _react.useCallback)(function () { if (!activeNode) { return; } var to = getPos(); var mappedTo; if (to !== undefined) { var _api$core3, _api$core4; var from = activeNode.pos; api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref5) { var _api$blockControls4; var tr = _ref5.tr; api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 || _api$blockControls4.moveToLayout(from, to)({ tr: tr }); var insertColumnStep = (0, _updateSelection.getInsertLayoutStep)(tr); mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from; return tr; }); api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref6) { var tr = _ref6.tr; if (mappedTo !== undefined) { (0, _updateSelection.updateSelection)(tr, mappedTo); } return tr; }); } }, [api, getPos, activeNode]); (0, _react.useEffect)(function () { if (ref.current) { return (0, _adapter.dropTargetForElements)({ element: ref.current, onDragEnter: function onDragEnter() { setIsDraggedOver(true); readNextNodeAnchor(); }, onDragLeave: function onDragLeave() { setIsDraggedOver(false); }, onDrop: onDrop }); } }, [onDrop, readNextNodeAnchor]); if ((activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType) === 'layoutSection') { return null; } return (0, _react2.jsx)("div", { ref: ref // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage , css: [dropTargetLayoutStyle, dropTargetStackLayoutHintStyle], "data-testid": "block-ctrl-drop-indicator" }, isDraggedOver ? (0, _react2.jsx)(_box.DropIndicator, { edge: "right", gap: "-".concat(DROP_TARGET_LAYOUT_DROP_ZONE_WIDTH, "px") }) : (isActiveAnchor || (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) && (0, _react2.jsx)("div", { "data-testid": "block-ctrl-drop-hint", css: dropTargetLayoutHintStyle })); };