UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

859 lines (837 loc) 67.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); 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 _defineProperty3 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _classnames2 = _interopRequireDefault(require("classnames")); var _memoizeOne = _interopRequireDefault(require("memoize-one")); var _rafSchd = _interopRequireDefault(require("raf-schd")); var _reactIntlNext = require("react-intl-next"); var _analytics = require("@atlaskit/editor-common/analytics"); var _browser = require("@atlaskit/editor-common/browser"); var _collab = require("@atlaskit/editor-common/collab"); var _nesting = require("@atlaskit/editor-common/nesting"); var _nodeVisibility = require("@atlaskit/editor-common/node-visibility"); var _nodeWidth = require("@atlaskit/editor-common/node-width"); var _styles = require("@atlaskit/editor-common/styles"); var _utils = require("@atlaskit/editor-common/utils"); var _editorSharedStyles = require("@atlaskit/editor-shared-styles"); var _utils2 = require("@atlaskit/editor-tables/utils"); var _platformFeatureFlags = require("@atlaskit/platform-feature-flags"); var _combine = require("@atlaskit/pragmatic-drag-and-drop/combine"); var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals"); var _commands = require("../pm-plugins/commands"); var _autoscrollers = require("../pm-plugins/drag-and-drop/utils/autoscrollers"); var _pluginKey = require("../pm-plugins/sticky-headers/plugin-key"); var _util = require("../pm-plugins/sticky-headers/util"); var _tableAnalytics = require("../pm-plugins/table-analytics"); var _colgroup = require("../pm-plugins/table-resizing/utils/colgroup"); var _consts = require("../pm-plugins/table-resizing/utils/consts"); var _dom = require("../pm-plugins/table-resizing/utils/dom"); var _misc = require("../pm-plugins/table-resizing/utils/misc"); var _resizeState = require("../pm-plugins/table-resizing/utils/resize-state"); var _scaleTable = require("../pm-plugins/table-resizing/utils/scale-table"); var _nodes = require("../pm-plugins/utils/nodes"); var _table = require("../pm-plugins/utils/table"); var _types = require("../types"); var _eventHandlers = require("../ui/event-handlers"); var _TableFloatingColumnControls = _interopRequireDefault(require("../ui/TableFloatingColumnControls")); var _TableFloatingControls = _interopRequireDefault(require("../ui/TableFloatingControls")); var _ExternalDropTargets = require("./ExternalDropTargets"); var _OverflowShadowsObserver = require("./OverflowShadowsObserver"); var _TableContainer = require("./TableContainer"); var _TableStickyScrollbar = require("./TableStickyScrollbar"); 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; } 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) { (0, _defineProperty3.default)(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; } 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; })(); } // Ignored via go/ees005 // eslint-disable-next-line import/no-named-as-default // When table is inserted via paste, keyboard shortcut or quickInsert, // componentDidUpdate is called multiple times. The isOverflowing value is correct only on the last update. // To make sure we capture the last update, we use setTimeout. var initialOverflowCaptureTimeroutDelay = 300; // This is a hard switch for controlling whether the overflow analytics should be dispatched. There has been 6months of data // already collected which we could use but have not. This has been disabled rather then removed entirely in the event that // the current collected data becomes stale and we want to start collecting fresh data again in future. // PLEASE NOTE: that the current way this alaytics has been configured WILL cause reflows to occur. This is why the has been disabled. var isOverflowAnalyticsEnabled = false; // Prevent unnecessary parentWidth updates when table is nested inside of a node that is nested itself. var NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLD = 2; var NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MAX_THRESHOLD = 20; // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required // @deprecated Please use TableComponentNext instead // eslint-disable-next-line @repo/internal/react/no-class-components var TableComponent = /*#__PURE__*/function (_React$Component) { function TableComponent(props) { var _this; (0, _classCallCheck2.default)(this, TableComponent); _this = _callSuper(this, TableComponent, [props]); (0, _defineProperty3.default)(_this, "state", (0, _defineProperty3.default)((0, _defineProperty3.default)((0, _defineProperty3.default)((0, _defineProperty3.default)((0, _defineProperty3.default)({ scroll: 0, parentWidth: undefined }, _types.ShadowEvent.SHOW_BEFORE_SHADOW, false), _types.ShadowEvent.SHOW_AFTER_SHADOW, false), "tableWrapperWidth", undefined), "tableWrapperHeight", undefined), "windowResized", false)); (0, _defineProperty3.default)(_this, "handleMouseOut", function (event) { if (!(0, _eventHandlers.isTableInFocus)(_this.props.view)) { return false; } return (0, _eventHandlers.handleMouseOut)(_this.props.view, event); }); (0, _defineProperty3.default)(_this, "handleMouseOver", function (event) { if (!(0, _eventHandlers.isTableInFocus)(_this.props.view)) { return false; } return (0, _eventHandlers.withCellTracking)(_eventHandlers.handleMouseOver)(_this.props.view, event); }); (0, _defineProperty3.default)(_this, "handleMouseEnter", function () { var node = _this.props.getNode(); var pos = _this.props.getPos(); var tr = _this.props.view.state.tr; var tableId = node.attrs.localId; tr.setMeta('mouseEnterTable', [tableId, node, pos]); _this.props.view.dispatch(tr); }); (0, _defineProperty3.default)(_this, "updateShadowState", function (shadowKey, value) { if (_this.state[shadowKey] === value) { return; } _this.setState((0, _defineProperty3.default)({}, shadowKey, value)); }); (0, _defineProperty3.default)(_this, "createShadowSentinels", function (table) { if (table) { var shadowSentinelLeft = document.createElement('span'); shadowSentinelLeft.className = _types.TableCssClassName.TABLE_SHADOW_SENTINEL_LEFT; var shadowSentinelRight = document.createElement('span'); shadowSentinelRight.className = _types.TableCssClassName.TABLE_SHADOW_SENTINEL_RIGHT; table.prepend(shadowSentinelLeft); table.prepend(shadowSentinelRight); } }); (0, _defineProperty3.default)(_this, "onStickyState", function (state) { var pos = _this.props.getPos(); if (!(0, _utils.isValidPosition)(pos, _this.props.view.state)) { return; } var stickyHeader = (0, _util.findStickyHeaderForTable)(state, pos); if (stickyHeader !== _this.state.stickyHeader) { _this.setState({ stickyHeader: stickyHeader }); if (_this.overflowShadowsObserver) { _this.overflowShadowsObserver.updateStickyShadows(); } } }); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any (0, _defineProperty3.default)(_this, "prevTableState", null); (0, _defineProperty3.default)(_this, "handleScroll", function (event) { if (!_this.wrapper || event.target !== _this.wrapper) { return; } if (_this.stickyScrollbar) { _this.stickyScrollbar.scrollLeft(_this.wrapper.scrollLeft); } if (_this.table) { // sync sticky header row to table scroll var headers = _this.table.querySelectorAll('tr[data-header-row]'); for (var i = 0; i < headers.length; i++) { // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting var header = headers[i]; header.scrollLeft = _this.wrapper.scrollLeft; header.style.marginRight = '2px'; } } _this.setState((0, _defineProperty3.default)({}, _types.ShadowEvent.SHOW_BEFORE_SHADOW, _this.wrapper.scrollLeft !== 0)); }); (0, _defineProperty3.default)(_this, "handleTableResizing", function () { var _this$props = _this.props, getNode = _this$props.getNode, containerWidth = _this$props.containerWidth, options = _this$props.options, allowTableResizing = _this$props.allowTableResizing; // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var prevNode = _this.node; var node = getNode(); var prevAttrs = prevNode.attrs; var isNested = (0, _nodes.isTableNested)(_this.props.view.state, _this.props.getPos()); var parentWidth = _this.getParentNodeWidth(); if (isNested && (0, _nodes.isTableNestedInMoreThanOneNode)(_this.props.view.state, _this.props.getPos())) { var resizeObsWrapperWidth = _this.wrapperWidth || 0; var wrapperWidthDiffBetweenRerenders = Math.abs(resizeObsWrapperWidth - (_this.state.parentWidth || 0)); var isOusideOfThreshold = wrapperWidthDiffBetweenRerenders <= NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLD || wrapperWidthDiffBetweenRerenders > NESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MAX_THRESHOLD; // 1. Check isOusideOfThreshold is added to prevent undersired state update. // When table is nested in the extenstion and the table column is being resized, // space available within extension can change and cause undesirable state update. // MIN_THRESNESTED_TABLE_IN_NESTED_PARENT_WIDTH_DIFF_MIN_THRESHOLDHOLD value is required // as the resizeObsWrapperWidth can differ between page reloads by 2px. // 2. Check resizeObsWrapperWidth > 1 is added to prevent parentWidth update when table unmounts. // When a is nested table in a nested expand and the expand collabses, the table unmounts and // resizeObsWrapperWidth becomes 1. parentWidth = isOusideOfThreshold && resizeObsWrapperWidth > 1 ? resizeObsWrapperWidth : _this.state.parentWidth; } var parentWidthChanged = parentWidth && parentWidth !== _this.state.parentWidth; var layoutSize = _this.tableNodeLayoutSize(node, containerWidth.width, options); var hasNumberedColumnChanged = prevAttrs.isNumberColumnEnabled !== node.attrs.isNumberColumnEnabled; var noOfColumnsChanged = (0, _nodes.tablesHaveDifferentNoOfColumns)(node, prevNode); if ( // We need to react if our parent changes // Scales the cols widths relative to the new parent width. parentWidthChanged || // Enabling / disabling this feature reduces or adds size to the table. hasNumberedColumnChanged || // This last check is also to cater for dynamic text sizing changing the 'default' layout width // Usually happens on window resize. layoutSize !== _this.layoutSize || noOfColumnsChanged) { var shouldScaleTable = (!allowTableResizing || allowTableResizing && isNested) && !hasNumberedColumnChanged && !noOfColumnsChanged; // If column has been inserted/deleted avoid multi dispatch if (shouldScaleTable) { _this.scaleTable({ parentWidth: parentWidth }, hasNumberedColumnChanged); } // only when table resizing is enabled and toggle numbered column to run scaleTable if (allowTableResizing && hasNumberedColumnChanged) { if (!(0, _colgroup.hasTableBeenResized)(prevNode)) { _this.scaleTable({ parentWidth: node.attrs.width }, true); } } _this.updateParentWidth(parentWidth); } _this.node = node; _this.containerWidth = containerWidth; _this.layoutSize = layoutSize; }); // Function gets called when table is nested. (0, _defineProperty3.default)(_this, "scaleTable", function (scaleOptions) { var isUserTriggered = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var _this$props2 = _this.props, view = _this$props2.view, getNode = _this$props2.getNode, getPos = _this$props2.getPos, containerWidth = _this$props2.containerWidth, options = _this$props2.options; var node = getNode(); var state = view.state, dispatch = view.dispatch; var pos = getPos(); if (typeof pos !== 'number' || !(0, _utils.isValidPosition)(pos, state)) { return; } var domAtPos = view.domAtPos.bind(view); var width = containerWidth.width; _this.scaleTableDebounced.cancel(); var tr = (0, _scaleTable.scaleTable)(_this.table, _objectSpread(_objectSpread({}, scaleOptions), {}, { node: node, prevNode: _this.node || node, start: pos + 1, containerWidth: width, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion previousContainerWidth: _this.containerWidth.width || width }, options), domAtPos, _this.props.pluginInjectionApi, false, // isTableScalingEnabled doesn't change the behavior of nested tables false // shouldUseIncreasedScalingPercent set to false for nested tables )(state.tr); if (!isUserTriggered) { (0, _collab.tintDirtyTransaction)(tr); if ((0, _platformFeatureFlags.fg)('platform_editor_fix_table_resizing_undo')) { // Avoid adding this transaction separately to the history as these are automatic updates // as a consequence of another action tr.setMeta('addToHistory', false); } } dispatch(tr); }); (0, _defineProperty3.default)(_this, "setTimerToSendInitialOverflowCaptured", function (isOverflowing) { var _this$state; var _this$props3 = _this.props, dispatchAnalyticsEvent = _this$props3.dispatchAnalyticsEvent, containerWidth = _this$props3.containerWidth, allowTableResizing = _this$props3.allowTableResizing; var parentWidth = ((_this$state = _this.state) === null || _this$state === void 0 ? void 0 : _this$state.parentWidth) || 0; _this.initialOverflowCaptureTimerId = setTimeout(function () { dispatchAnalyticsEvent({ action: _analytics.TABLE_ACTION.INITIAL_OVERFLOW_CAPTURED, actionSubject: _analytics.ACTION_SUBJECT.TABLE, actionSubjectId: null, eventType: _analytics.EVENT_TYPE.TRACK, attributes: { editorWidth: containerWidth.width || 0, isOverflowing: isOverflowing, tableResizingEnabled: allowTableResizing || false, width: _this.node.attrs.width || 0, parentWidth: parentWidth } }); _this.isInitialOverflowSent = true; }, initialOverflowCaptureTimeroutDelay); }); (0, _defineProperty3.default)(_this, "handleAutoSize", function () { if (_this.table) { var _this$props4 = _this.props, view = _this$props4.view, getNode = _this$props4.getNode, getPos = _this$props4.getPos, containerWidth = _this$props4.containerWidth; var node = getNode(); var pos = getPos(); if (!(0, _utils.isValidPosition)(pos, view.state)) { return; } (0, _commands.autoSizeTable)(view, node, _this.table, pos, { containerWidth: containerWidth.width }); } }); (0, _defineProperty3.default)(_this, "handleWindowResize", function () { var _this$props5 = _this.props, getNode = _this$props5.getNode, containerWidth = _this$props5.containerWidth; var node = getNode(); var layoutSize = _this.tableNodeLayoutSize(node); if (containerWidth.width > layoutSize) { return; } var parentWidth = _this.getParentNodeWidth(); _this.scaleTableDebounced({ parentWidth: parentWidth }); }); // This is a new handler for window resize events that sets the windowResized state immediately // This is needed to update colgroup on window resize, to enforce the table scaling (0, _defineProperty3.default)(_this, "handleWindowResizeNew", function () { // Set resizing to true immediately if (!_this.state.windowResized) { _this.setState({ windowResized: true }); } }); (0, _defineProperty3.default)(_this, "getParentNodeWidth", function () { var _this$props6 = _this.props, getPos = _this$props6.getPos, containerWidth = _this$props6.containerWidth, options = _this$props6.options, state = _this$props6.view.state; var pos = getPos(); if (!(0, _utils.isValidPosition)(pos, state)) { return; } var parentNodeWith = (0, _nodeWidth.getParentNodeWidth)(pos, state, containerWidth, options && options.isFullWidthModeEnabled); return parentNodeWith; }); (0, _defineProperty3.default)(_this, "updateParentWidth", function (width) { _this.setState({ parentWidth: width }); }); (0, _defineProperty3.default)(_this, "tableNodeLayoutSize", function (node, containerWidth, options) { return (0, _misc.getLayoutSize)(node.attrs.layout, containerWidth || _this.props.containerWidth.width, options || _this.props.options || {}); }); (0, _defineProperty3.default)(_this, "shouldUpdateColgroup", function (params) { var _this$props$options, _this$props$options2; var isWindowResized = params.isWindowResized, isWidthChanged = params.isWidthChanged, isTableWidthChanged = params.isTableWidthChanged, isColumnsDistributed = params.isColumnsDistributed, isTableResizedFullWidth = params.isTableResizedFullWidth, isTableDisplayModeChanged = params.isTableDisplayModeChanged, isNumberColumnChanged = params.isNumberColumnChanged, isNumberOfColumnsChanged = params.isNumberOfColumnsChanged, isFullWidthModeAndLineLengthChanged = params.isFullWidthModeAndLineLengthChanged; var isFullPageEditor = !((_this$props$options = _this.props.options) !== null && _this$props$options !== void 0 && _this$props$options.isCommentEditor) && !((_this$props$options2 = _this.props.options) !== null && _this$props$options2 !== void 0 && _this$props$options2.isChromelessEditor); if (isFullPageEditor) { return !!isWindowResized || isColumnsDistributed || !!isTableResizedFullWidth || isTableDisplayModeChanged || isNumberColumnChanged || isNumberOfColumnsChanged || !!isFullWidthModeAndLineLengthChanged; } return isWidthChanged || isTableWidthChanged || isColumnsDistributed || !!isTableResizedFullWidth || isTableDisplayModeChanged || isNumberColumnChanged || isNumberOfColumnsChanged || !!isFullWidthModeAndLineLengthChanged; }); (0, _defineProperty3.default)(_this, "scaleTableDebounced", (0, _rafSchd.default)(_this.scaleTable)); (0, _defineProperty3.default)(_this, "handleTableResizingDebounced", (0, _rafSchd.default)(_this.handleTableResizing)); (0, _defineProperty3.default)(_this, "handleScrollDebounced", (0, _rafSchd.default)(_this.handleScroll)); (0, _defineProperty3.default)(_this, "handleAutoSizeDebounced", (0, _rafSchd.default)(_this.handleAutoSize)); (0, _defineProperty3.default)(_this, "handleWindowResizeDebounced", (0, _rafSchd.default)(_this.handleWindowResize)); (0, _defineProperty3.default)(_this, "handleWindowResizeNewDebounced", (0, _rafSchd.default)(_this.handleWindowResizeNew)); (0, _defineProperty3.default)(_this, "updateShadowStateDebounced", (0, _rafSchd.default)(_this.updateShadowState)); var _options = props.options, _containerWidth = props.containerWidth, _getNode = props.getNode; _this.node = _getNode(); _this.containerWidth = _containerWidth; var tablePos = props.getPos(); _this.isNestedInTable = tablePos ? (0, _nesting.getParentOfTypeCount)(props.view.state.schema.nodes.table)(props.view.state.doc.resolve(tablePos)) > 0 : false; _this.isInitialOverflowSent = false; if (!_this.updateColGroupFromFullWidthChange) { _this.updateColGroupFromFullWidthChange = (_options === null || _options === void 0 ? void 0 : _options.isFullWidthModeEnabled) && !(_options !== null && _options !== void 0 && _options.wasFullWidthModeEnabled); } // store table size using previous full-width mode so can detect if it has changed. var isFullWidthModeEnabled = _options ? _options.wasFullWidthModeEnabled : false; _this.layoutSize = _this.tableNodeLayoutSize(_this.node, _containerWidth.width, { isFullWidthModeEnabled: isFullWidthModeEnabled }); _this.resizeObserver = new ResizeObserver(function (entries) { var _iterator = _createForOfIteratorHelper(entries), _step; try { var _loop = function _loop() { var entry = _step.value; _this.setState(function (prev) { var _entry$contentRect, _entry$contentRect2; return (prev === null || prev === void 0 ? void 0 : prev.tableWrapperWidth) === ((_entry$contentRect = entry.contentRect) === null || _entry$contentRect === void 0 ? void 0 : _entry$contentRect.width) && (prev === null || prev === void 0 ? void 0 : prev.tableWrapperHeight) === ((_entry$contentRect2 = entry.contentRect) === null || _entry$contentRect2 === void 0 ? void 0 : _entry$contentRect2.height) ? prev : _objectSpread(_objectSpread({}, prev), {}, { tableWrapperWidth: entry.contentRect.width, tableWrapperHeight: entry.contentRect.height }); }); }; for (_iterator.s(); !(_step = _iterator.n()).done;) { _loop(); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } }); // Disable inline table editing and resizing controls in Firefox // https://github.com/ProseMirror/prosemirror/issues/432 if ('execCommand' in document) { ['enableObjectResizing', 'enableInlineTableEditing'].forEach(function (cmd) { if (document.queryCommandSupported(cmd)) { document.execCommand(cmd, false, 'false'); } }); } return _this; } (0, _inherits2.default)(TableComponent, _React$Component); return (0, _createClass2.default)(TableComponent, [{ key: "componentDidMount", value: function componentDidMount() { var _this2 = this; var _nodeVisibilityManage = (0, _nodeVisibility.nodeVisibilityManager)(this.props.view.dom), observe = _nodeVisibilityManage.observe; if (this.table) { this.nodeVisibilityObserverCleanupFn = observe({ element: this.table, onFirstVisible: function onFirstVisible() { _this2.initialiseEventListenersAfterMount(); // force width calculation - missed resize event under firefox when // table is nested within bodied extension if (_this2.wrapper) { var _this2$wrapper; _this2.wrapperWidth = (_this2$wrapper = _this2.wrapper) === null || _this2$wrapper === void 0 ? void 0 : _this2$wrapper.clientWidth; } } }); // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners window.addEventListener('resize', this.handleWindowResizeNewDebounced); } } }, { key: "initialiseEventListenersAfterMount", value: function initialiseEventListenersAfterMount() { var _this$table, _this$table2, _this$table3, _this3 = this; var _this$props7 = this.props, allowColumnResizing = _this$props7.allowColumnResizing, allowTableResizing = _this$props7.allowTableResizing, eventDispatcher = _this$props7.eventDispatcher, isDragAndDropEnabled = _this$props7.isDragAndDropEnabled, getNode = _this$props7.getNode; var browser = (0, _expValEquals.expValEquals)('platform_editor_hydratable_ui', 'isEnabled', true) ? (0, _browser.getBrowserInfo)() : _browser.browser; var isIE11 = browser.ie_version === 11; // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table = this.table) === null || _this$table === void 0 || _this$table.addEventListener('mouseenter', this.handleMouseEnter); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table2 = this.table) === null || _this$table2 === void 0 || _this$table2.addEventListener('mouseout', this.handleMouseOut); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table3 = this.table) === null || _this$table3 === void 0 || _this$table3.addEventListener('mouseover', this.handleMouseOver); if (this.wrapper) { this.wrapperReisizeObserver = new ResizeObserver(function (entries) { var _iterator2 = _createForOfIteratorHelper(entries), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _entry$contentRect3; var entry = _step2.value; _this3.wrapperWidth = (_entry$contentRect3 = entry.contentRect) === null || _entry$contentRect3 === void 0 ? void 0 : _entry$contentRect3.width; } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } }); this.wrapperReisizeObserver.observe(this.wrapper); } if (allowColumnResizing && this.wrapper && !isIE11) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this.wrapper.addEventListener('scroll', this.handleScrollDebounced, { passive: true }); if (this.table && !this.isNestedInTable) { this.stickyScrollbar = new _TableStickyScrollbar.TableStickyScrollbar(this.wrapper, this.props.view); } if (isDragAndDropEnabled) { this.dragAndDropCleanupFn = _combine.combine.apply(void 0, (0, _toConsumableArray2.default)((0, _autoscrollers.autoScrollerFactory)({ tableWrapper: this.wrapper, getNode: getNode }))); } } if (allowColumnResizing) { /** * We no longer use `containerWidth` as a variable to determine an update for table resizing (avoids unnecessary updates). * Instead we use the resize event to only trigger updates when necessary. */ if (!allowTableResizing) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners window.addEventListener('resize', this.handleWindowResizeDebounced); } this.handleTableResizingDebounced(); } var currentStickyState = _pluginKey.pluginKey.getState(this.props.view.state); if (currentStickyState) { this.onStickyState(currentStickyState); } // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any eventDispatcher.on(_pluginKey.pluginKey.key, this.onStickyState); if (isOverflowAnalyticsEnabled) { var initialIsOveflowing = this.state[_types.ShadowEvent.SHOW_BEFORE_SHADOW] || this.state[_types.ShadowEvent.SHOW_AFTER_SHADOW]; this.setTimerToSendInitialOverflowCaptured(initialIsOveflowing); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this$resizeObserver, _this$wrapperReisizeO, _this$table4, _this$table5, _this$table6; var _this$props8 = this.props, allowColumnResizing = _this$props8.allowColumnResizing, allowTableResizing = _this$props8.allowTableResizing, eventDispatcher = _this$props8.eventDispatcher, isDragAndDropEnabled = _this$props8.isDragAndDropEnabled, view = _this$props8.view, isInDanger = _this$props8.isInDanger; var browser = (0, _expValEquals.expValEquals)('platform_editor_hydratable_ui', 'isEnabled', true) ? (0, _browser.getBrowserInfo)() : _browser.browser; var isIE11 = browser.ie_version === 11; if (this.wrapper && !isIE11) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this.wrapper.removeEventListener('scroll', this.handleScrollDebounced); } if (isDragAndDropEnabled && this.dragAndDropCleanupFn) { this.dragAndDropCleanupFn(); } if (this.nodeVisibilityObserverCleanupFn) { this.nodeVisibilityObserverCleanupFn(); } (_this$resizeObserver = this.resizeObserver) === null || _this$resizeObserver === void 0 || _this$resizeObserver.disconnect(); (_this$wrapperReisizeO = this.wrapperReisizeObserver) === null || _this$wrapperReisizeO === void 0 || _this$wrapperReisizeO.disconnect(); if (this.stickyScrollbar) { this.stickyScrollbar.dispose(); } this.handleScrollDebounced.cancel(); this.scaleTableDebounced.cancel(); this.handleTableResizingDebounced.cancel(); this.handleAutoSizeDebounced.cancel(); if (!allowTableResizing) { this.handleWindowResizeDebounced.cancel(); } this.handleWindowResizeNewDebounced.cancel(); if ((0, _expValEquals.expValEquals)('platform_editor_table_drag_handle_hover', 'isEnabled', true)) { if (isInDanger) { (0, _commands.clearHoverSelection)()(view.state, view.dispatch); } } if (!allowTableResizing && allowColumnResizing) { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners window.removeEventListener('resize', this.handleWindowResizeDebounced); } // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners window.removeEventListener('resize', this.handleWindowResizeNewDebounced); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table4 = this.table) === null || _this$table4 === void 0 || _this$table4.removeEventListener('mouseenter', this.handleMouseEnter); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table5 = this.table) === null || _this$table5 === void 0 || _this$table5.removeEventListener('mouseout', this.handleMouseOut); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners this === null || this === void 0 || (_this$table6 = this.table) === null || _this$table6 === void 0 || _this$table6.removeEventListener('mouseover', this.handleMouseOver); if (this.overflowShadowsObserver) { this.overflowShadowsObserver.dispose(); } // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any eventDispatcher.off(_pluginKey.pluginKey.key, this.onStickyState); if (this.initialOverflowCaptureTimerId) { clearTimeout(this.initialOverflowCaptureTimerId); } } }, { key: "removeInlineTableWidth", value: // Should be called only when table node width is reset to undefined in Comment Editor // Maybe replaced by handleColgroupUpdates as we implement new table's support in Comment Editor. function removeInlineTableWidth() { var _this$props9 = this.props, isResizing = _this$props9.isResizing, getNode = _this$props9.getNode, view = _this$props9.view, getPos = _this$props9.getPos; if (!this.table) { return; } var tableNode = getNode(); var newTableWidth = tableNode.attrs.width; var start = getPos() || 0; var depth = view.state.doc.resolve(start).depth; if (depth !== 0) { return; } if (!isResizing && newTableWidth === null) { this.table.style.width = ''; } } }, { key: "handleColgroupUpdates", value: function handleColgroupUpdates() { var _this$containerWidth, _this4 = this; var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var _this$props0 = this.props, getNode = _this$props0.getNode, containerWidth = _this$props0.containerWidth, isResizing = _this$props0.isResizing, view = _this$props0.view, getPos = _this$props0.getPos, getEditorFeatureFlags = _this$props0.getEditorFeatureFlags, options = _this$props0.options; if (!this.table) { return; } // Remove any widths styles after resizing preview is completed this.table.style.width = ''; var tableNode = getNode(); var start = getPos() || 0; var depth = view.state.doc.resolve(start).depth; if (depth !== 0) { return; } var tableNodeWidth = (0, _nodeWidth.getTableContainerWidth)(tableNode); var isTableResizedFullWidth = tableNodeWidth === 1800 && this.wasResizing && !isResizing; // Needed for undo / redo var isTableWidthChanged = tableNodeWidth !== this.tableNodeWidth; var tableRenderWidth = options !== null && options !== void 0 && options.isCommentEditor ? containerWidth.width - (_consts.TABLE_OFFSET_IN_COMMENT_EDITOR + 1) // should be the same as this.table.parentElement?.clientWidth - 1, subtract 1 to avoid overflow : containerWidth.width - _consts.TABLE_EDITOR_MARGIN; tableNodeWidth = options !== null && options !== void 0 && options.isCommentEditor && !tableNode.attrs.width ? tableRenderWidth : tableNodeWidth; var isTableSquashed = tableRenderWidth < tableNodeWidth; var isNumberColumnChanged = tableNode.attrs.isNumberColumnEnabled !== this.node.attrs.isNumberColumnEnabled; var isNumberOfColumnsChanged = (0, _nodes.tablesHaveDifferentNoOfColumns)(tableNode, this.node); var containerWidthValue = containerWidth.width, containerLineLength = containerWidth.lineLength; var isLineLengthChanged = ((_this$containerWidth = this.containerWidth) === null || _this$containerWidth === void 0 ? void 0 : _this$containerWidth.lineLength) !== containerLineLength; var isFullWidthModeAndLineLengthChanged = this.updateColGroupFromFullWidthChange && isLineLengthChanged; var maybeScale = isTableSquashed || isTableWidthChanged || isTableResizedFullWidth && !(options !== null && options !== void 0 && options.isCommentEditor) || isNumberColumnChanged || isNumberOfColumnsChanged || this.state.windowResized; if (force || maybeScale || isFullWidthModeAndLineLengthChanged) { var _this$containerWidth2, _this$props$options3, _this$props$options4, _this$props$options5; var isWidthChanged = ((_this$containerWidth2 = this.containerWidth) === null || _this$containerWidth2 === void 0 ? void 0 : _this$containerWidth2.width) !== containerWidthValue; var wasTableResized = (0, _colgroup.hasTableBeenResized)(this.node); var isTableResized = (0, _colgroup.hasTableBeenResized)(tableNode); var isColumnsDistributed = wasTableResized && !isTableResized; var isTableDisplayModeChanged = this.node.attrs.displayMode !== tableNode.attrs.displayMode; var shouldUpdateColgroup = this.shouldUpdateColgroup({ isWindowResized: this.state.windowResized, isWidthChanged: isWidthChanged, isTableWidthChanged: isTableWidthChanged, isColumnsDistributed: isColumnsDistributed, isTableResizedFullWidth: isTableResizedFullWidth, isTableDisplayModeChanged: isTableDisplayModeChanged, isNumberColumnChanged: isNumberColumnChanged, isNumberOfColumnsChanged: isNumberOfColumnsChanged, isFullWidthModeAndLineLengthChanged: isFullWidthModeAndLineLengthChanged }); var _getEditorFeatureFlag = getEditorFeatureFlags(), _getEditorFeatureFlag2 = _getEditorFeatureFlag.tableWithFixedColumnWidthsOption, tableWithFixedColumnWidthsOption = _getEditorFeatureFlag2 === void 0 ? false : _getEditorFeatureFlag2; var isTableScalingWithFixedColumnWidthsOptionEnabled = !!((_this$props$options3 = this.props.options) !== null && _this$props$options3 !== void 0 && _this$props$options3.isTableScalingEnabled) && tableWithFixedColumnWidthsOption; var shouldUseIncreasedScalingPercent = isTableScalingWithFixedColumnWidthsOptionEnabled || !!((_this$props$options4 = this.props.options) !== null && _this$props$options4 !== void 0 && _this$props$options4.isTableScalingEnabled) && !!((_this$props$options5 = this.props.options) !== null && _this$props$options5 !== void 0 && _this$props$options5.isCommentEditor); if (force || !isResizing && shouldUpdateColgroup) { var _this$props$options6, _this$props$options7, _this$props$options8, _this$props$options9; var resizeState = (0, _resizeState.getResizeState)({ minWidth: _consts.COLUMN_MIN_WIDTH, // When numbered column enabled, we need to subtract the width of the numbered column maxSize: tableNode.attrs.isNumberColumnEnabled ? tableRenderWidth - _editorSharedStyles.akEditorTableNumberColumnWidth : tableRenderWidth, table: tableNode, tableRef: this.table, start: start, domAtPos: view.domAtPos.bind(view), isTableScalingEnabled: true, shouldUseIncreasedScalingPercent: shouldUseIncreasedScalingPercent, isCommentEditor: !!((_this$props$options6 = this.props.options) !== null && _this$props$options6 !== void 0 && _this$props$options6.isCommentEditor) }); var shouldScaleOnColgroupUpdate = false; if ((_this$props$options7 = this.props.options) !== null && _this$props$options7 !== void 0 && _this$props$options7.isTableScalingEnabled && !tableWithFixedColumnWidthsOption) { shouldScaleOnColgroupUpdate = true; } if (isTableScalingWithFixedColumnWidthsOptionEnabled && tableNode.attrs.displayMode !== 'fixed') { shouldScaleOnColgroupUpdate = true; } if ((_this$props$options8 = this.props.options) !== null && _this$props$options8 !== void 0 && _this$props$options8.isTableScalingEnabled && (_this$props$options9 = this.props.options) !== null && _this$props$options9 !== void 0 && _this$props$options9.isCommentEditor) { shouldScaleOnColgroupUpdate = true; } var scalePercent = 1; requestAnimationFrame(function () { var _this4$props$options, _this4$props$options2; // Scaling percent has to be calculated inside requestAnimationFrame, otherwise // renderWidth calculated as `tableRef?.parentElement?.clientWidth` // inside of getTableScalingPercent returns 0. if (!((_this4$props$options = _this4.props.options) !== null && _this4$props$options !== void 0 && _this4$props$options.isCommentEditor) || (_this4$props$options2 = _this4.props.options) !== null && _this4$props$options2 !== void 0 && _this4$props$options2.isCommentEditor && tableNode.attrs.width) { scalePercent = (0, _misc.getTableScalingPercent)(tableNode, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion _this4.table, shouldUseIncreasedScalingPercent); } else { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion scalePercent = (0, _misc.getScalingPercentForTableWithoutWidth)(tableNode, _this4.table); } // Request animation frame required for Firefox (0, _resizeState.updateColgroup)(resizeState, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion _this4.table, tableNode, shouldScaleOnColgroupUpdate, scalePercent); }); } } if (isFullWidthModeAndLineLengthChanged) { this.updateColGroupFromFullWidthChange = false; } this.tableNodeWidth = tableNodeWidth; this.wasResizing = isResizing; this.containerWidth = containerWidth; } // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any }, { key: "componentDidUpdate", value: function componentDidUpdate(_, prevState) { var _this$props$options0, _this$props$options1, _this$wrapper, _this5 = this; var _this$props1 = this.props, view = _this$props1.view, getNode = _this$props1.getNode, isMediaFullscreen = _this$props1.isMediaFullscreen, allowColumnResizing = _this$props1.allowColumnResizing, allowTableResizing = _this$props1.allowTableResizing, isResizing = _this$props1.isResizing, options = _this$props1.options, isTableScalingEnabled = _this$props1.isTableScalingEnabled, getPos = _this$props1.getPos, getEditorFeatureFlags = _this$props1.getEditorFeatureFlags, isInDanger = _this$props1.isInDanger; var table = (0, _utils2.findTable)(view.state.selection); var shouldScale = false; var shouldHandleColgroupUpdates = false; var _getEditorFeatureFlag3 = getEditorFeatureFlags(), _getEditorFeatureFlag4 = _getEditorFeatureFlag3.tableWithFixedColumnWidthsOption, tableWithFixedColumnWidthsOption = _getEditorFeatureFlag4 === void 0 ? false : _getEditorFeatureFlag4; if (isTableScalingEnabled && !tableWithFixedColumnWidthsOption) { shouldScale = true; shouldHandleColgroupUpdates = true; } var isTableScalingWithFixedColumnWidthsOptionEnabled = !!isTableScalingEnabled && tableWithFixedColumnWidthsOption; var shouldUseIncreasedScalingPercent = isTableScalingWithFixedColumnWidthsOptionEnabled || !!isTableScalingEnabled && !!((_this$props$options0 = this.props.options) !== null && _this$props$options0 !== void 0 && _this$props$options0.isCommentEditor); if (isTableScalingWithFixedColumnWidthsOptionEnabled && getNode().attrs.displayMode !== 'fixed') { shouldScale = true; shouldHandleColgroupUpdates = true; } if (this.state.windowResized) { shouldHandleColgroupUpdates = true; } if (shouldHandleColgroupUpdates) { this.handleColgroupUpdates(); } // table is always defined so this never runs if (!(0, _expValEquals.expValEquals)('platform_editor_table_drag_handle_hover', 'isEnabled', true)) { if (isInDanger && !table) { (0, _commands.clearHoverSelection)()(view.state, view.dispatch); } } if ((_this$props$options1 = this.props.options) !== null && _this$props$options1 !== void 0 && _this$props$options1.isCommentEditor && allowTableResizing && !(options !== null && options !== void 0 && options.isTableScalingEnabled)) { this.removeInlineTableWidth(); } if ((_this$wrapper = this.wrapper) !== null && _this$wrapper !== void 0 && _this$wrapper.parentElement && this.table && !this.overflowShadowsObserver) { // isDragAndDropEnabled will be false when the editorViewMode is 'live' and so the fix below is never triggered // but the shadow observer must run async so its initial state is correct. // note: when cleaning up platform_editor_table_drag_handle_hover entirely remove this nested if check incl. this.props.isDragAndDropEnabled if (this.props.isDragAndDropEnabled || (0, _expValEquals.expValEquals)('platform_editor_table_drag_handle_hover', 'isEnabled', true)) { // requestAnimationFrame is used here to fix a race condition issue // that happens when a table is nested in expand and expand's width is // changed via breakout button window.requestAnimationFrame(function () { _this5.overflowShadowsObserver = new _OverflowShadowsObserver.OverflowShadowsObserver(_this5.updateShadowStateDebounced, // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting _this5.table, _this5.wrapper); }); } else { this.overflowShadowsObserver = new _OverflowShadowsObserver.OverflowShadowsObserver(this.updateShadowState, this.table, this.wrapper); } } if (this.overflowShadowsObserver) { var _this$state$stickyHea; this.overflowShadowsObserver.observeShadowSentinels((_this$state$stickyHea = this.state.stickyHeader) === null || _this$state$stickyHea === void 0 ? void 0 : _this$state$stickyHea.sticky); } var currentTable = getNode(); var previousTable = this.node; var isNoOfColumnsChanged = (0, _nodes.tablesHaveDifferentNoOfColumns)(currentTable, previousTable); var isNoOfRowsChanged = (0, _nodes.tablesHaveDifferentNoOfRows)(currentTable, previousTable); if (isNoOfColumnsChanged || isNoOfRowsChanged) { var _this$props$pluginInj; (_this$props$pluginInj = this.props.pluginInjectionApi) === null || _this$props$pluginInj === void 0 || (_this$props$pluginInj = _this$props$pluginInj.accessibilityUtils) === null || _this$props$pluginInj === void 0 || _this$props$pluginInj.actions.ariaNotify((0, _table.getAssistiveMessage)(previousTable, currentTable, this.props.intl), { priority: 'important' }); } if (currentTable.attrs.__autoSize) { // Wait for next tick to handle auto sizing, gives the browser time to do layout calc etc. this.handleAutoSizeDebounced(); } // re-drawing will cause media component get unmounted that will exit fullscreen mode if media is in fullscreen mode // see https://product-fabric.atlassian.net/browse/MEX-1290 else if (allowColumnResizing && this.table && !isMediaFullscreen) { // If col widths (e.g. via collab) or number of columns (e.g. delete a column) have changed, // re-draw colgroup. if ((0, _nodes.tablesHaveDifferentColumnWidths)(currentTable, previousTable) || isNoOfColumnsChanged) { var _view = this.props.view; var shouldRecreateResizeCols = !allowTableResizing || !isResizing || isNoOfColumnsChanged && isResizing; if (shouldRecreateResizeCols) { var start = getPos() || 0; var depth = _vie