UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

77 lines (76 loc) 3.63 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid import uuid from 'uuid'; import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { isCSSAnchorSupported, isCSSAttrAnchorSupported } from '@atlaskit/editor-common/styles'; import { PluginKey } from '@atlaskit/editor-prosemirror/state'; import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view'; import { fg } from '@atlaskit/platform-feature-flags'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; class ObjHash { static getForNode(node) { if (this.cache.has(node)) { return this.cache.get(node) || ''; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid const uniqueId = uuid(); this.cache.set(node, uniqueId); return uniqueId; } } _defineProperty(ObjHash, "cache", new WeakMap()); const getNodeAnchor = node => { const handleId = ObjHash.getForNode(node); return `--table-${node.type.name}-${handleId}`; }; const createTableAnchorDecorations = state => { const decs = []; let headerRowId; state.doc.nodesBetween(0, state.doc.content.size, (node, pos, parent, index) => { var _parent$attrs; const isTableHeader = node.type.name === 'tableHeader'; const isTableRow = node.type.name === 'tableRow'; const isParentTableRow = (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableRow'; const isParentTableHeaderRow = (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableRow' && headerRowId && (parent === null || parent === void 0 ? void 0 : (_parent$attrs = parent.attrs) === null || _parent$attrs === void 0 ? void 0 : _parent$attrs.localId) === headerRowId; const shouldAddDecorationToHeader = expValEquals('platform_editor_table_sticky_header_patch_9', 'isEnabled', true) ? isParentTableHeaderRow && isTableHeader : isTableHeader; const isFirstRow = isTableRow && index === 0; if (isFirstRow) { headerRowId = node.attrs.localId; } // only apply to header cells and the first row of a table, for performance reasons if (isFirstRow || shouldAddDecorationToHeader) { const anchorName = getNodeAnchor(node); const shouldAddAnchorNameInDecoration = !isCSSAttrAnchorSupported() && isCSSAnchorSupported() && fg('platform_editor_table_sticky_header_patch_8'); const attributes = { 'data-node-anchor': anchorName, style: `anchor-name: ${anchorName};` }; decs.push(Decoration.node(pos, pos + node.nodeSize, shouldAddAnchorNameInDecoration ? attributes : { 'data-node-anchor': anchorName })); } // only decend if there is a possible table row or table header node after the current node, for performance reasons return expValEquals('platform_editor_table_sticky_header_patch_9', 'isEnabled', true) ? !(isTableHeader || isParentTableHeaderRow) : !(isTableHeader || isParentTableRow); }); return DecorationSet.create(state.doc, decs); }; export const pluginKey = new PluginKey('tableAnchorNamesPlugin'); export const createPlugin = () => { return new SafePlugin({ state: { init: (_config, state) => { return createTableAnchorDecorations(state); }, apply: (tr, decorationSet, _, newState) => { if (tr.docChanged) { return createTableAnchorDecorations(newState); } return decorationSet; } }, key: pluginKey, props: { decorations: state => pluginKey.getState(state) || DecorationSet.empty } }); };