@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
135 lines (131 loc) • 7.09 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { shouldBeSticky } from '../../pm-plugins/utils/drag-handle-positions';
import { dragHandleGap, topPositionAdjustment } from '../consts';
export var getAbsoluteSurfacePlacement = function getAbsoluteSurfacePlacement(_ref) {
var _offsetParentRect$lef, _offsetParentRect$top;
var offsetParentRect = _ref.offsetParentRect,
offsetParentScrollLeft = _ref.offsetParentScrollLeft,
offsetParentScrollTop = _ref.offsetParentScrollTop,
placement = _ref.placement;
return _objectSpread(_objectSpread({}, placement), {}, {
left: placement.left - ((_offsetParentRect$lef = offsetParentRect === null || offsetParentRect === void 0 ? void 0 : offsetParentRect.left) !== null && _offsetParentRect$lef !== void 0 ? _offsetParentRect$lef : 0) + offsetParentScrollLeft,
top: placement.top - ((_offsetParentRect$top = offsetParentRect === null || offsetParentRect === void 0 ? void 0 : offsetParentRect.top) !== null && _offsetParentRect$top !== void 0 ? _offsetParentRect$top : 0) + offsetParentScrollTop
});
};
/**
* Positions the surface beside the legacy drag-handle slot, on either the left or right edge
* of the target node. Node-type-specific gap/top-adjustment maths (layouts, tables, media, cards,
* extensions, etc.) live in one place so left/right edge cases can't drift out of sync.
*
* The left side grows away from the node without knowing its own width, so it needs
* `translateX(-100%)` to anchor its right edge at `nodeRect.left` and extend backward. The right
* side grows in the normal box-flow direction (away from the node, into the margin), so the gap
* can be folded straight into `left` with no transform needed.
*/
export var getSurfacePlacement = function getSurfacePlacement(_ref2) {
var layout = _ref2.layout,
nodeRect = _ref2.nodeRect,
nodeType = _ref2.nodeType,
nodeTypeWithLevel = _ref2.nodeTypeWithLevel,
parentNodeType = _ref2.parentNodeType,
side = _ref2.side;
if (nodeType === 'layoutColumn') {
// nodeRect.left + width/2 === nodeRect.right - width/2 — side-independent.
return {
left: nodeRect.left + nodeRect.width / 2,
top: nodeRect.top,
transform: 'translate(-50%, -50%)'
};
}
var gap = dragHandleGap(nodeType, parentNodeType);
var top = nodeRect.top + topPositionAdjustment(nodeTypeWithLevel, layout);
var height = shouldBeSticky(nodeType) ? nodeRect.height : undefined;
return side === 'right' ? {
left: nodeRect.right + gap,
top: top,
transform: '',
height: height
} : {
left: nodeRect.left,
top: top,
transform: "translateX(calc(-100% - ".concat(gap, "px))"),
height: height
};
};
/**
* The insets to apply to a surface wrapper, plus whether that wrapper spans its target node.
*
* Two kinds of placement produce this. A measured one resolves to pixel numbers from a
* `getBoundingClientRect` snapshot, so it is only as fresh as the last render and needs observers
* to keep it honest. An anchored one resolves to `anchor()` functions that the browser re-evaluates
* on every layout change, so it stays attached to its node with nothing re-rendering.
*
* `isSticky` is carried alongside the style rather than read back out of it because the two variants
* express the same stretch differently — a measured `height` versus an anchored `bottom`.
*/
/**
* Adapts a measured placement to the shape the surface components consume. Sticky-eligible node
* types are the ones `getSurfacePlacement` gave a `height` to.
*/
export var toMeasuredSurfaceWrapperPlacement = function toMeasuredSurfaceWrapperPlacement(placement) {
return {
isSticky: placement.height !== undefined,
style: {
height: placement.height,
left: placement.left,
top: placement.top,
transform: placement.transform
}
};
};
/**
* Where a surface goes when its anchor stops resolving, as the fallback argument to the block-axis
* `anchor()` calls below.
*
* An anchor is invalid once its element stops generating a box e.g. (`display: none`) / removed node
* Currently, anchor fallback is not unstable with some of the position-visibility options, so here
* we manually set a fallback of -9999 so that it will render offscreen out of the viewport
* without causing extra overflows
*/
var INVALID_ANCHOR_OFFSCREEN_PX = 9999;
var INVALID_ANCHOR_FALLBACK_TOP = "-".concat(INVALID_ANCHOR_OFFSCREEN_PX, "px");
var INVALID_ANCHOR_FALLBACK_BOTTOM = "".concat(INVALID_ANCHOR_OFFSCREEN_PX, "px");
export var getAnchoredSurfacePlacement = function getAnchoredSurfacePlacement(_ref3) {
var anchorName = _ref3.anchorName,
layout = _ref3.layout,
nodeType = _ref3.nodeType,
nodeTypeWithLevel = _ref3.nodeTypeWithLevel,
parentNodeType = _ref3.parentNodeType,
side = _ref3.side;
if (nodeType === 'layoutColumn') {
// The column's horizontal midpoint, matching the measured `nodeRect.left + width / 2` and the
// legacy drag handle's own layout-column formula. Side-independent.
return {
isSticky: false,
style: {
left: "calc((anchor(".concat(anchorName, " left) + anchor(").concat(anchorName, " right)) / 2)"),
positionAnchor: anchorName,
top: "anchor(".concat(anchorName, " top, ").concat(INVALID_ANCHOR_FALLBACK_TOP, ")"),
transform: 'translate(-50%, -50%)'
}
};
}
var gap = dragHandleGap(nodeType, parentNodeType);
var isSticky = shouldBeSticky(nodeType);
return {
isSticky: isSticky,
style: _objectSpread(_objectSpread({}, isSticky ? {
bottom: "anchor(".concat(anchorName, " bottom, ").concat(INVALID_ANCHOR_FALLBACK_BOTTOM, ")")
} : {}), {}, {
left: side === 'right' ? "calc(anchor(".concat(anchorName, " right) + ").concat(gap, "px)") : "anchor(".concat(anchorName, " left)"),
positionAnchor: anchorName,
top: "calc(anchor(".concat(anchorName, " top, ").concat(INVALID_ANCHOR_FALLBACK_TOP, ") + ").concat(topPositionAdjustment(nodeTypeWithLevel, layout), "px)"),
// The left side grows away from the node without knowing its own width, so it pulls itself
// back past its own box and the gap. The right side grows into the margin, so the gap is
// already folded into `left` above.
transform: side === 'right' ? '' : "translateX(calc(-100% - ".concat(gap, "px))")
})
};
};