@atlaskit/editor-plugin-block-menu
Version:
BlockMenu plugin for @atlaskit/editor-core
146 lines (140 loc) • 6.65 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import { BLOCK_MENU_TEST_ID } from '@atlaskit/editor-common/block-menu';
import { popupWithNestedElement } from '@atlaskit/editor-common/experiences';
/**
* Checks if the given element or any of its ancestors is a drag handle element.
*
* @param element - The DOM element to check.
* @returns True if the element is a drag handle, false otherwise.
*/
export var isDragHandleElement = function isDragHandleElement(element) {
return !!(element !== null && element !== void 0 && element.closest('[data-editor-block-ctrl-drag-handle]'));
};
/**
* Checks if the block menu is currently visible within the provided popups target element.
*
* @param popupsTarget - The container element for popups.
* @returns True if the block menu is visible, false otherwise.
*/
export var isBlockMenuVisible = function isBlockMenuVisible(popupsTarget) {
if (!popupsTarget) {
return false;
}
return popupWithNestedElement(popupsTarget, "[data-testid=\"".concat(BLOCK_MENU_TEST_ID, "\"]")) !== null;
};
var isBlockMenuAddedInMutation = function isBlockMenuAddedInMutation(_ref) {
var type = _ref.type,
addedNodes = _ref.addedNodes;
return type === 'childList' && _toConsumableArray(addedNodes).some(isBlockMenuWithinNode);
};
var isBlockMenuWithinNode = function isBlockMenuWithinNode(node) {
return popupWithNestedElement(node, "[data-testid=\"".concat(BLOCK_MENU_TEST_ID, "\"]")) !== null;
};
/**
* Handles DOM mutations to determine if the block menu was opened
*
* This function looks for mutations that indicate the block menu
* has been added to the DOM.
*
* @param mutations - The list of DOM mutations to evaluate
* @returns An ExperienceCheckResult indicating success if the menu was opened, otherwise undefined
*/
export var handleMenuOpenDomMutation = function handleMenuOpenDomMutation(_ref2) {
var mutations = _ref2.mutations;
// Look for a mutation that added the block menu
var _iterator = _createForOfIteratorHelper(mutations),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var mutation = _step.value;
if (isBlockMenuAddedInMutation(mutation)) {
return {
status: 'success'
};
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return undefined;
};
/**
* Handles DOM mutations to determine if a move action was performed
*
* Move actions typically produce two mutations: one where nodes are removed
* from their original location, and another where the same number of nodes are
* added to a new location. This function checks for that pattern.
*
* @param mutations - The list of DOM mutations to evaluate
* @returns An ExperienceCheckResult indicating success if a move was detected, otherwise undefined
*/
export var handleMoveDomMutation = function handleMoveDomMutation(_ref3) {
var mutations = _ref3.mutations;
var removeMutation = mutations.find(function (m) {
return m.type === 'childList' && m.removedNodes.length > 0;
});
var addMutation = mutations.find(function (m) {
return m.type === 'childList' && m.addedNodes.length > 0;
});
if (removeMutation && addMutation && removeMutation.removedNodes.length === addMutation.addedNodes.length) {
return {
status: 'success'
};
}
return undefined;
};
/**
* Handles DOM mutations to determine if a delete action was performed
*
* Delete actions typically produce a single mutation where nodes are removed
* from the DOM without any corresponding additions. This function checks for
* that specific pattern.
*
* @param mutations - The list of DOM mutations to evaluate
* @returns An ExperienceCheckResult indicating success if a delete was detected, otherwise undefined
*/
export var handleDeleteDomMutation = function handleDeleteDomMutation(_ref4) {
var mutations = _ref4.mutations;
// Delete action produces a single childList mutation with only removedNodes
var childListMutations = mutations.filter(function (m) {
return m.type === 'childList';
});
// Check for at least one mutation with removedNodes but no addedNodes
if (childListMutations.some(function (m) {
return m.removedNodes.length > 0 && m.addedNodes.length === 0;
})) {
return {
status: 'success'
};
}
return undefined;
};
/**
* Handles DOM mutations to determine if a transform action was performed.
*
* Transforms replace one block type with another (e.g. paragraph → heading),
* producing childList mutations with both removed (old node) and added (new node).
*
* @param options.mutations - The list of DOM mutation records
* @returns An ExperienceCheckResult indicating success if a transform was detected, otherwise undefined
*/
export var handleTransformDomMutation = function handleTransformDomMutation(_ref5) {
var mutations = _ref5.mutations;
var hasRemovedNodes = mutations.some(function (m) {
return m.type === 'childList' && m.removedNodes.length > 0;
});
var hasAddedNodes = mutations.some(function (m) {
return m.type === 'childList' && m.addedNodes.length > 0;
});
if (hasRemovedNodes && hasAddedNodes) {
return {
status: 'success'
};
}
return undefined;
};