UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

119 lines (118 loc) 4.79 kB
/** * A plugin for handle table custom widths * Has login to scan the document, add width value to table's width attribute when necessary * Also holds resizing state to hide / show table controls */ import { SetAttrsStep } from '@atlaskit/adf-schema/steps'; import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { isReplaceDocOperation } from '@atlaskit/editor-common/utils/document'; import { PluginKey } from '@atlaskit/editor-prosemirror/state'; import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorWideLayoutWidth } from '@atlaskit/editor-shared-styles'; import { TABLE_MAX_WIDTH } from './table-resizing/utils/consts'; import { ALIGN_START } from './utils/alignment'; export const pluginKey = new PluginKey('tableWidthPlugin'); const createPlugin = (dispatch, dispatchAnalyticsEvent, fullWidthEnabled, isTableScalingEnabled, isTableAlignmentEnabled, isCommentEditor) => { return new SafePlugin({ key: pluginKey, state: { init() { return { resizing: false, tableLocalId: '', tableRef: null }; }, apply(tr, pluginState) { const meta = tr.getMeta(pluginKey); if (meta) { const keys = Object.keys(meta); const changed = keys.some(key => { return pluginState[key] !== meta[key]; }); if (changed) { const newState = { ...pluginState, ...meta }; dispatch(pluginKey, newState); return newState; } } return pluginState; } }, appendTransaction: (transactions, oldState, newState) => { // When document first load in Confluence, initially it is an empty document // and Collab service triggers a transaction to replace the empty document with the real document that should be rendered. // what we need to do is to add width attr to all tables in the real document // isReplaceDocumentOperation is checking if the transaction is the one that replace the empty document with the real document const isReplaceDocumentOperation = isReplaceDocOperation(transactions, oldState); const referentialityTr = transactions.find(tr => tr.getMeta('referentialityTableInserted')); const shouldPatchTableWidth = fullWidthEnabled && isTableScalingEnabled; const shouldPatchTableAlignment = fullWidthEnabled && isTableAlignmentEnabled; if (!isReplaceDocumentOperation && (!shouldPatchTableWidth && !shouldPatchTableAlignment || !referentialityTr)) { return null; } const { table } = newState.schema.nodes; const tr = newState.tr; if (isReplaceDocumentOperation && !isCommentEditor) { newState.doc.forEach((node, offset) => { if (node.type === table) { const width = node.attrs.width; const layout = node.attrs.layout; if (!width && layout) { let tableWidthCal; if (fullWidthEnabled) { tableWidthCal = akEditorFullWidthLayoutWidth; } else { switch (layout) { case 'wide': tableWidthCal = akEditorWideLayoutWidth; break; case 'full-width': tableWidthCal = akEditorFullWidthLayoutWidth; break; // when in fix-width appearance, no need to assign value to table width attr // as when table is created, width attr is null by default, table rendered using layout attr default: tableWidthCal = akEditorDefaultLayoutWidth; break; } } const { width, ...rest } = node.attrs; if (tableWidthCal) { tr.step(new SetAttrsStep(offset, { width: tableWidthCal, ...rest })); } } } }); } if (referentialityTr) { referentialityTr.steps.forEach(step => { step.getMap().forEach((_, __, newStart, newEnd) => { newState.doc.nodesBetween(newStart, newEnd, (node, pos) => { if (node.type === table) { if (shouldPatchTableWidth && node.attrs.width !== TABLE_MAX_WIDTH) { tr.setNodeAttribute(pos, 'width', TABLE_MAX_WIDTH); } if (shouldPatchTableAlignment) { tr.setNodeAttribute(pos, 'layout', ALIGN_START); } } }); }); }); } return tr; } }); }; export { createPlugin };