UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

234 lines (224 loc) 10.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _adfSchema = require("@atlaskit/adf-schema"); var _analytics = require("@atlaskit/editor-common/analytics"); var _editorTables = require("@atlaskit/editor-tables"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _TableNodeViewBase = _interopRequireDefault(require("./TableNodeViewBase")); function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } var DEFAULT_COL_SPAN = 1; var DEFAULT_ROW_SPAN = 1; /** * For performance reasons we do this in the background - it shouldn't block the main thread */ function delayUntilIdle(cb) { if (typeof window === 'undefined') { return; } // eslint-disable-next-line compat/compat if (window.requestIdleCallback !== undefined) { // eslint-disable-next-line compat/compat return window.requestIdleCallback(function () { return cb(); }, { timeout: 500 }); } return window.requestAnimationFrame(function () { return cb(); }); } // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp var cssVariablePattern = /^VAR\(--.*\)$/; var getCellDomAttrsForTableMenuUpdates = function getCellDomAttrsForTableMenuUpdates(node) { var attrs = (0, _adfSchema.getCellDomAttrs)(node); if ((0, _expValEquals.expValEquals)('platform_editor_table_menu_updates', 'isEnabled', true) && node.attrs.valign) { attrs['data-valign'] = node.attrs.valign; } return attrs; }; var TableCell = exports.default = /*#__PURE__*/function (_TableNodeView) { function TableCell(node, view, getPos, eventDispatcher, editorAnalyticsAPI) { var _this; (0, _classCallCheck2.default)(this, TableCell); _this = _callSuper(this, TableCell, [node, view, getPos, eventDispatcher]); /** Cached edge state to avoid redundant DOM writes. */ (0, _defineProperty2.default)(_this, "prevReachesTop", false); (0, _defineProperty2.default)(_this, "prevReachesBottom", false); (0, _defineProperty2.default)(_this, "prevReachesLeft", false); (0, _defineProperty2.default)(_this, "prevReachesRight", false); (0, _defineProperty2.default)(_this, "destroy", function () { if (_this.delayHandle && typeof window !== 'undefined') { var _window, _window$cancelIdleCal, _window2, _window2$cancelAnimat; // eslint-disable-next-line compat/compat (_window = window) === null || _window === void 0 || (_window$cancelIdleCal = _window.cancelIdleCallback) === null || _window$cancelIdleCal === void 0 || _window$cancelIdleCal.call(_window, _this.delayHandle); (_window2 = window) === null || _window2 === void 0 || (_window2$cancelAnimat = _window2.cancelAnimationFrame) === null || _window2$cancelAnimat === void 0 || _window2$cancelAnimat.call(_window2, _this.delayHandle); } }); if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true)) { _this.updateTableEdgeAttrs(node); } // CONFCLOUD-78239: Previously we had a bug which tried to invert the heading colour of a table // Obviously design tokens can't be inverted and so it would result in `VAR(--DS-BACKGROUND-ACCENT-GRAY-SUBTLEST, #F4F5F7)` // which is not a valid CSS variable. // // We should follow-up and remove this in TODO-xx in 6 months once we're confident // that this has fixed most of the cases in the wild. // // This is a workaround to fix those cases on the fly. Note it is super specific on purpose // so that it just fixes the heading token (other tokens should be unaffected) // At some point in the future if (cssVariablePattern.test(node.attrs.background)) { _this.delayHandle = delayUntilIdle(function () { var pos = getPos(); if (pos) { var tr = view.state.tr; tr.setNodeAttribute(pos, 'background', node.attrs.background.toLowerCase()) // Ensures dispatch does not contribute to undo history (otherwise user requires multiple undo's to revert table) .setMeta('addToHistory', false); editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({ action: _analytics.TABLE_ACTION.TABLE_CELL_BACKGROUND_FIXED, actionSubject: _analytics.ACTION_SUBJECT.TABLE, actionSubjectId: null, eventType: _analytics.EVENT_TYPE.TRACK })(tr); view.dispatch(tr); } }); } return _this; } (0, _inherits2.default)(TableCell, _TableNodeView); return (0, _createClass2.default)(TableCell, [{ key: "update", value: function update(node) { var didUpdate = this.updateNodeView(node); if (didUpdate) { this.node = node; } return didUpdate; } /** * Detects whether this cell visually reaches the bottom or right edge of the table * (accounting for rowspan/colspan) and sets data attributes so CSS can apply * rounded corners and transparent borders to merged cells that span to the table edges. */ }, { key: "updateTableEdgeAttrs", value: function updateTableEdgeAttrs(node) { var pos = this.getPos(); if (pos === undefined) { return; } try { var resolvedPos = this.view.state.doc.resolve(pos); // Cell → row → table: depth-1 is the table, depth is the row var tableDepth = resolvedPos.depth - 1; var rowDepth = resolvedPos.depth; if (tableDepth < 0 || rowDepth < 0) { return; } var tableNode = resolvedPos.node(tableDepth); if (tableNode.type.name !== 'table') { return; } var tableMap = _editorTables.TableMap.get(tableNode); var cellStartInTable = pos - resolvedPos.start(tableDepth); var cellRect = tableMap.findCell(cellStartInTable); var reachesTop = cellRect.top === 0; var reachesBottom = cellRect.bottom >= tableMap.height; var reachesLeft = cellRect.left === 0; var reachesRight = cellRect.right >= tableMap.width; // Only touch DOM attributes that actually changed if (reachesTop !== this.prevReachesTop) { this.prevReachesTop = reachesTop; this.setDataAttr('data-reaches-top', reachesTop); } if (reachesBottom !== this.prevReachesBottom) { this.prevReachesBottom = reachesBottom; this.setDataAttr('data-reaches-bottom', reachesBottom); } if (reachesLeft !== this.prevReachesLeft) { this.prevReachesLeft = reachesLeft; this.setDataAttr('data-reaches-left', reachesLeft); } if (reachesRight !== this.prevReachesRight) { this.prevReachesRight = reachesRight; this.setDataAttr('data-reaches-right', reachesRight); } } catch (_unused) { // Position may be stale during document mutations; silently ignore. } } }, { key: "setDataAttr", value: function setDataAttr(attr, value) { if (value) { this.dom.setAttribute(attr, 'true'); } else { this.dom.removeAttribute(attr); } } }, { key: "updateNodeView", value: function updateNodeView(node) { var _this2 = this; if (this.node.type !== node.type) { return false; } var attrs = getCellDomAttrsForTableMenuUpdates(this.node); var nextAttrs = getCellDomAttrsForTableMenuUpdates(node); var _getCellAttrs = (0, _adfSchema.getCellAttrs)(this.dom), colspan = _getCellAttrs.colspan, rowspan = _getCellAttrs.rowspan; // need to rerender when colspan/rowspan in dom are different from the node attrs // this can happen when undoing merge cells if (colspan !== (node.attrs.colspan || DEFAULT_COL_SPAN) || rowspan !== (node.attrs.rowspan || DEFAULT_ROW_SPAN)) { return false; } // added + changed attributes var addedAttrs = Object.entries(nextAttrs).filter(function (_ref) { var _ref2 = (0, _slicedToArray2.default)(_ref, 2), key = _ref2[0], value = _ref2[1]; return attrs[key] !== value; }); var removedAttrs = Object.keys(attrs).filter(function (key) { return !nextAttrs.hasOwnProperty(key); }); if (addedAttrs.length || removedAttrs.length) { addedAttrs.forEach(function (_ref3) { var _ref4 = (0, _slicedToArray2.default)(_ref3, 2), key = _ref4[0], value = _ref4[1]; return _this2.dom.setAttribute(key, value || ''); }); removedAttrs.forEach(function (key) { return _this2.dom.removeAttribute(key); }); if ((0, _expValEquals.expValEquals)('platform_editor_table_q4_loveability', 'isEnabled', true)) { this.updateTableEdgeAttrs(node); } return true; } // Return true to not re-render this node view if (this.node.sameMarkup(node)) { return true; } return false; } }]); }(_TableNodeViewBase.default);