UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

308 lines (303 loc) 15.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET = exports.EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP = exports.DropTarget = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); 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 _hooks = require("@atlaskit/editor-common/hooks"); var _box = require("@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box"); var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter"); var _constants = require("@atlaskit/theme/constants"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _experiments = require("@atlaskit/tmp-editor-statsig/experiments"); 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 _inlineDropTarget = require("../pm-plugins/utils/inline-drop-target"); var _consts = require("./consts"); var _inlineDropTarget2 = require("./inline-drop-target"); /** * @jsxRuntime classic * @jsx jsx */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports var DEFAULT_DROP_INDICATOR_WIDTH = 760; var EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH = '--editor-block-controls-drop-indicator-width'; var EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN = '--editor-block-controls-drop-target-leftMargin'; var EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX = '--editor-block-controls-drop-target-zindex'; var EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET = exports.EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET = '--editor-block-controls-drop-indicator-offset'; var EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP = exports.EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP = '--editor-block-controls-drop-indicator-gap'; var styleDropTarget = (0, _react2.css)({ marginLeft: "calc(-1 * var(".concat(EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, ", 0))"), paddingLeft: "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, ", 0)"), position: 'absolute', left: '0', display: 'block', zIndex: "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, ", 110)"), transform: "translateY(var(".concat(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET, ", 0))") }); var styleDropIndicator = (0, _react2.css)({ height: '100%', margin: '0 auto', position: 'relative', width: "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, ", 100%)"), display: 'none' }); var styleDropIndicatorVisible = (0, _react2.css)({ display: 'block' }); var nestedDropIndicatorStyle = (0, _react2.css)({ position: 'relative' }); var dropZoneStyles = (0, _react2.css)({ margin: 0, position: 'absolute', width: '100%', zIndex: 110, minHeight: '4px' }); var nestedDropZoneStyle = (0, _react2.css)({ left: '4px', right: '4px', width: 'unset' }); var enableDropZone = ['paragraph', 'mediaSingle', 'heading', 'codeBlock', 'decisionList', 'bulletList', 'orderedList', 'taskList', 'extension', 'blockCard']; var enableDropZoneNext = ['paragraph', 'mediaSingle', 'heading', 'codeBlock', 'decisionList', 'bulletList', 'orderedList', 'taskList', 'extension', 'blockCard', 'syncBlock']; var getEnableDropZone = function getEnableDropZone() { if ((0, _experiments.editorExperiment)('platform_synced_block_patch_6', true, { exposure: true })) { return enableDropZoneNext; } return enableDropZone; }; // This z index is used in container like layout var fullHeightStyleAdjustZIndexStyle = (0, _react2.css)({ zIndex: 0 }); var HoverZone = function HoverZone(_ref) { var _onDragEnter = _ref.onDragEnter, onDragLeave = _ref.onDragLeave, onDrop = _ref.onDrop, node = _ref.node, pos = _ref.pos, parent = _ref.parent, editorWidth = _ref.editorWidth, anchorRectCache = _ref.anchorRectCache, position = _ref.position, isNestedDropTarget = _ref.isNestedDropTarget, dropTargetStyle = _ref.dropTargetStyle, api = _ref.api; var ref = (0, _react.useRef)(null); var isRemainingheight = dropTargetStyle === 'remainingHeight'; var anchorName = (0, _react.useMemo)(function () { if ((0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) { if (node && typeof pos === 'number') { var posOffset = position === 'upper' ? -node.nodeSize : 0; return (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(node, pos + posOffset)) || ''; } return ''; } return node ? (0, _decorationsCommon.getNodeAnchor)(node) : ''; }, [api, node, pos, position]); var _useActiveAnchorTrack = (0, _activeAnchorTracker.useActiveAnchorTracker)(anchorName), _useActiveAnchorTrack2 = (0, _slicedToArray2.default)(_useActiveAnchorTrack, 2), _isActive = _useActiveAnchorTrack2[0], setActiveAnchor = _useActiveAnchorTrack2[1]; var isInsideBodiedSyncBlock = parent && parent.type.name === 'bodiedSyncBlock' && (0, _experiments.editorExperiment)('platform_synced_block', true) && (0, _experiments.editorExperiment)('platform_synced_block_patch_6', true, { exposure: true }); (0, _react.useEffect)(function () { if (ref.current) { return (0, _adapter.dropTargetForElements)({ element: ref.current, onDragEnter: function onDragEnter() { if ((!isNestedDropTarget || isInsideBodiedSyncBlock) && (0, _experiments.editorExperiment)('advanced_layouts', true)) { setActiveAnchor(); } _onDragEnter(); }, onDragLeave: onDragLeave, onDrop: onDrop }); } }, [isNestedDropTarget, isInsideBodiedSyncBlock, _onDragEnter, onDragLeave, onDrop, setActiveAnchor]); var hoverZoneUpperStyle = (0, _react.useMemo)(function () { var heightStyleOffset = "var(--editor-block-controls-drop-indicator-gap, 0)/2"; var transformOffset = "var(".concat(EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET, ", 0)"); var heightStyle = anchorName && getEnableDropZone().includes((node === null || node === void 0 ? void 0 : node.type.name) || '') ? (0, _anchorUtils.isAnchorSupported)() ? "calc(anchor-size(".concat(anchorName, " height)/2 + ").concat(heightStyleOffset, ")") : "calc(".concat(((anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getHeight(anchorName)) || 0) / 2, "px + ").concat(heightStyleOffset, ")") : '4px'; var transform = position === 'upper' ? "translateY(calc(-100% + ".concat(transformOffset, "))") : "translateY(".concat(transformOffset, ")"); return (0, _react2.css)({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values height: heightStyle, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values transform: transform, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values maxWidth: "".concat(editorWidth || 0, "px") }); }, [anchorName, anchorRectCache, editorWidth, node === null || node === void 0 ? void 0 : node.type.name, position]); /** * 1. Above the last empty line * 2. Below the last element * * Both cases will take the remaining height of the the container */ var heightStyle = (0, _react.useMemo)(function () { // only apply upper drop zone if (isRemainingheight && position === 'upper') { // previous node var _anchorName = node ? (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(node, pos || -1)) || '' : (0, _decorationsCommon.getNodeAnchor)(node) : ''; var top = 'unset'; if (_anchorName) { var enabledDropZone = getEnableDropZone().includes((node === null || node === void 0 ? void 0 : node.type.name) || ''); if ((0, _anchorUtils.isAnchorSupported)()) { top = enabledDropZone ? "calc(anchor(".concat(_anchorName, " 50%))") : "calc(anchor(".concat(_anchorName, " bottom) - 4px)"); } else if (anchorRectCache) { var preNodeTopPos = anchorRectCache.getTop(_anchorName) || 0; var prevNodeHeight = anchorRectCache.getHeight(_anchorName) || 0; top = enabledDropZone ? "calc(".concat(preNodeTopPos, "px + ").concat(prevNodeHeight / 2, "px)") : "calc(".concat(preNodeTopPos, "px + ").concat(prevNodeHeight, "px - 4px)"); } else { // Should not happen return null; } } else { // first empty paragraph top = '4px'; } return (0, _react2.css)({ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values top: top, bottom: '4px', height: 'unset', zIndex: 10, transform: 'none' }); } return null; }, [anchorRectCache, api, isRemainingheight, node, pos, position]); var isFullHeightInLayout = isRemainingheight && (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutColumn'; return (0, _react2.jsx)("div", { ref: ref // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop , className: "drop-target-hover-zone-".concat(position), "data-testid": "drop-target-zone-".concat(position) // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage , css: [dropZoneStyles, isNestedDropTarget && nestedDropZoneStyle, // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage hoverZoneUpperStyle, // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage heightStyle, isFullHeightInLayout && fullHeightStyleAdjustZIndexStyle] }); }; var DropTarget = exports.DropTarget = function DropTarget(props) { var _api$blockControls; var api = props.api, getPos = props.getPos, prevNode = props.prevNode, nextNode = props.nextNode, parentNode = props.parentNode, formatMessage = props.formatMessage, anchorRectCache = props.anchorRectCache, _props$dropTargetStyl = props.dropTargetStyle, dropTargetStyle = _props$dropTargetStyl === void 0 ? 'default' : _props$dropTargetStyl, isSameLayout = props.isSameLayout; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), isDraggedOver = _useState2[0], setIsDraggedOver = _useState2[1]; var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['width'], function (states) { var _states$widthState; return { lineLength: ((_states$widthState = states.widthState) === null || _states$widthState === void 0 ? void 0 : _states$widthState.lineLength) || DEFAULT_DROP_INDICATOR_WIDTH }; }), lineLength = _useSharedPluginState.lineLength; var isNestedDropTarget = (parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) !== 'doc'; var _ref2 = (api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {}, activeNode = _ref2.activeNode; var onDrop = function onDrop() { if (!activeNode) { return; } var pos = getPos(); if (activeNode && pos !== undefined) { var _api$core, _api$blockControls2; var start = activeNode.pos; api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.moveNode(start, pos, undefined, formatMessage)); } }; var dynamicStyle = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({ width: isNestedDropTarget ? 'unset' : '100%' }, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH, isNestedDropTarget ? '100%' : "".concat(lineLength || DEFAULT_DROP_INDICATOR_WIDTH, "px")), EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN, isNestedDropTarget ? (0, _consts.getNestedNodeLeftPaddingMargin)(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0'), EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX, _constants.layers.navigation()); var isShowInlineDropTarget = (0, _inlineDropTarget.shouldAllowInlineDropTarget)(isNestedDropTarget, nextNode, isSameLayout, activeNode, parentNode); return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(HoverZone // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , { onDragEnter: function onDragEnter() { return setIsDraggedOver(true); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onDragLeave: function onDragLeave() { return setIsDraggedOver(false); }, onDrop: onDrop, node: prevNode, pos: getPos(), editorWidth: lineLength, anchorRectCache: anchorRectCache, position: "upper", isNestedDropTarget: isNestedDropTarget, dropTargetStyle: dropTargetStyle, api: api }), (0, _react2.jsx)("div", { // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage css: [styleDropTarget, isNestedDropTarget && nestedDropIndicatorStyle] // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop , style: dynamicStyle, "data-testid": "block-ctrl-drop-target" }, (0, _react2.jsx)("div", { css: [styleDropIndicator, isDraggedOver && styleDropIndicatorVisible], "data-testid": "block-ctrl-drop-indicator" }, (0, _react2.jsx)(_box.DropIndicator, { edge: "bottom" }))), dropTargetStyle !== 'remainingHeight' && (0, _react2.jsx)(HoverZone // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , { onDragEnter: function onDragEnter() { return setIsDraggedOver(true); } // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , onDragLeave: function onDragLeave() { return setIsDraggedOver(false); }, onDrop: onDrop, node: nextNode, pos: getPos(), parent: parentNode, editorWidth: lineLength, anchorRectCache: anchorRectCache, position: "lower", isNestedDropTarget: isNestedDropTarget, api: api }), isShowInlineDropTarget && (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_inlineDropTarget2.InlineDropTarget // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , (0, _extends2.default)({}, props, { position: "left" })), (0, _react2.jsx)(_inlineDropTarget2.InlineDropTarget // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , (0, _extends2.default)({}, props, { position: "right" })))); };