@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
890 lines (867 loc) • 57.3 kB
JavaScript
"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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _classnames2 = _interopRequireDefault(require("classnames"));
var _rafSchd = _interopRequireDefault(require("raf-schd"));
var _reactIntlNext = require("react-intl-next");
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 _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 _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 _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, _defineProperty2.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
// 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;
// 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, _defineProperty2.default)(_this, "state", {
parentWidth: undefined,
tableWrapperWidth: undefined,
tableWrapperHeight: undefined,
windowResized: false
});
(0, _defineProperty2.default)(_this, "handleMouseOut", function (event) {
if (!(0, _eventHandlers.isTableInFocus)(_this.props.view)) {
return false;
}
return (0, _eventHandlers.handleMouseOut)(_this.props.view, event);
});
(0, _defineProperty2.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, _defineProperty2.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, _defineProperty2.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
});
}
});
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(0, _defineProperty2.default)(_this, "prevTableState", null);
(0, _defineProperty2.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';
}
}
// force update to for table controls to re-align
_this.forceUpdate();
});
(0, _defineProperty2.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, _defineProperty2.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, _defineProperty2.default)(_this, "handleAutoSize", function () {
if (_this.table) {
var _this$props3 = _this.props,
view = _this$props3.view,
getNode = _this$props3.getNode,
getPos = _this$props3.getPos,
containerWidth = _this$props3.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, _defineProperty2.default)(_this, "handleWindowResize", function () {
var _this$props4 = _this.props,
getNode = _this$props4.getNode,
containerWidth = _this$props4.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, _defineProperty2.default)(_this, "handleWindowResizeNew", function () {
// Set resizing to true immediately
if (!_this.state.windowResized) {
_this.setState({
windowResized: true
});
}
});
(0, _defineProperty2.default)(_this, "getParentNodeWidth", function () {
var _this$props5 = _this.props,
getPos = _this$props5.getPos,
containerWidth = _this$props5.containerWidth,
options = _this$props5.options,
state = _this$props5.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, _defineProperty2.default)(_this, "updateParentWidth", function (width) {
_this.setState({
parentWidth: width
});
});
(0, _defineProperty2.default)(_this, "tableNodeLayoutSize", function (node, containerWidth, options) {
return (0, _misc.getLayoutSize)(node.attrs.layout, containerWidth || _this.props.containerWidth.width, options || _this.props.options || {});
});
(0, _defineProperty2.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, _defineProperty2.default)(_this, "scaleTableDebounced", (0, _rafSchd.default)(_this.scaleTable));
(0, _defineProperty2.default)(_this, "handleTableResizingDebounced", (0, _rafSchd.default)(_this.handleTableResizing));
(0, _defineProperty2.default)(_this, "handleScrollDebounced", (0, _rafSchd.default)(_this.handleScroll));
(0, _defineProperty2.default)(_this, "handleAutoSizeDebounced", (0, _rafSchd.default)(_this.handleAutoSize));
(0, _defineProperty2.default)(_this, "handleWindowResizeDebounced", (0, _rafSchd.default)(_this.handleWindowResize));
(0, _defineProperty2.default)(_this, "handleWindowResizeNewDebounced", (0, _rafSchd.default)(_this.handleWindowResizeNew));
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;
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$props6 = this.props,
allowColumnResizing = _this$props6.allowColumnResizing,
allowTableResizing = _this$props6.allowTableResizing,
eventDispatcher = _this$props6.eventDispatcher,
isDragAndDropEnabled = _this$props6.isDragAndDropEnabled,
getNode = _this$props6.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);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
var _this$resizeObserver, _this$wrapperReisizeO, _this$table4, _this$table5, _this$table6;
var _this$props7 = this.props,
allowColumnResizing = _this$props7.allowColumnResizing,
allowTableResizing = _this$props7.allowTableResizing,
eventDispatcher = _this$props7.eventDispatcher,
isDragAndDropEnabled = _this$props7.isDragAndDropEnabled,
view = _this$props7.view,
isInDanger = _this$props7.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);
// 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$props8 = this.props,
isResizing = _this$props8.isResizing,
getNode = _this$props8.getNode,
view = _this$props8.view,
getPos = _this$props8.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$props9 = this.props,
getNode = _this$props9.getNode,
containerWidth = _this$props9.containerWidth,
isResizing = _this$props9.isResizing,
view = _this$props9.view,
getPos = _this$props9.getPos,
getEditorFeatureFlags = _this$props9.getEditorFeatureFlags,
options = _this$props9.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;
var _this$props0 = this.props,
view = _this$props0.view,
getNode = _this$props0.getNode,
isMediaFullscreen = _this$props0.isMediaFullscreen,
allowColumnResizing = _this$props0.allowColumnResizing,
allowTableResizing = _this$props0.allowTableResizing,
isResizing = _this$props0.isResizing,
options = _this$props0.options,
isTableScalingEnabled = _this$props0.isTableScalingEnabled,
getPos = _this$props0.getPos,
getEditorFeatureFlags = _this$props0.getEditorFeatureFlags,
isInDanger = _this$props0.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();
}
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 = _view.state.doc.resolve(start).depth;
shouldScale = depth === 0 && shouldScale;
(0, _colgroup.insertColgroupFromNode)(this.table, currentTable, shouldScale, undefined, shouldUseIncreasedScalingPercent, options === null || options === void 0 ? void 0 : options.isCommentEditor);
}
(0, _dom.updateControls)()(_view.state);
}
this.handleTableResizingDebounced();
}
}
}, {
key: "observeTable",
value: function observeTable(table) {
if (table) {
var _this$resizeObserver2;
(_this$resizeObserver2 = this.resizeObserver) === null || _this$resizeObserver2 === void 0 || _this$resizeObserver2.observe(table);
}
}
}, {
key: "render",
value: function render() {
var _this5 = this,
_this$props$options10;
var _this$props1 = this.props,
view = _this$props1.view,
getNode = _this$props1.getNode,
isResizing = _this$props1.isResizing,
_this$props1$allowCon = _this$props1.allowControls,
allowControls = _this$props1$allowCon === void 0 ? true : _this$props1$allowCon,
isHeaderRowEnabled = _this$props1.isHeaderRowEnabled,
ordering = _this$props1.ordering,
isHeaderColumnEnabled = _this$props1.isHeaderColumnEnabled,
tableActive = _this$props1.tableActive,
containerWidth = _this$props1.containerWidth,
options = _this$props1.options,
getPos = _this$props1.getPos,
pluginInjectionApi = _this$props1.pluginInjectionApi,
isDragAndDropEnabled = _this$props1.isDragAndDropEnabled,
getEditorFeatureFlags = _this$props1.getEditorFeatureFlags,
isTableScalingEnabled = _this$props1.isTableScalingEnabled,
allowTableResizing = _this$props1.allowTableResizing,
allowTableAlignment = _this$props1.allowTableAlignment,
selection = _this$props1.selection,
isInDanger = _this$props1.isInDanger,
hoveredRows = _this$props1.hoveredRows,
hoveredCell = _this$props1.hoveredCell,
isTableHovered = _this$props1.isTableHovered,
isWholeTableInDanger = _this$props1.isWholeTableInDanger;
var node = getNode();
var tableRef = this.table || undefined;
var headerRow = tableRef ? tableRef.querySelector('tr[data-header-row]') : undefined;
var hasHeaderRow = (0, _nodes.containsHeaderRow)(node);
var rowControls = /*#__PURE__*/_react.default.createElement(_TableFloatingControls.default, {
editorView: view,
tableRef: tableRef,
tableNode: node,
tableActive: tableActive,
hoveredRows: hoveredRows,
hoveredCell: hoveredCell,
isTableHovered: isTableHovered,
isInDanger: isInDanger,
isResizing: isResizing,
isNumberColumnEnabled: node.attrs.isNumberColumnEnabled,
isHeaderRowEnabled: isHeaderRowEnabled,
isDragAndDropEnabled: isDragAndDropEnabled,
ordering: ordering,
isHeaderColumnEnabled: isHeaderColumnEnabled,
hasHeaderRow: hasHeaderRow
// pass `selection` and `tableHeight` to control re-render
,
selection: view.state.selection,
headerRowHeight: headerRow ? headerRow.offsetHeight : undefined,
stickyHeader: !this.props.limitedMode ? this.state.stickyHeader : undefined,
tableWrapperWidth: this.state.tableWrapperWidth,
api: pluginInjectionApi,
isChromelessEditor: options === null || options === void 0 ? void 0 : options.isChromelessEditor
});
var tableContainerWidth = (0, _nodeWidth.getTableContainerWidth)(node);
var colControls = isDragAndDropEnabled ? /*#__PURE__*/_react.default.createElement(_TableFloatingColumnControls.default, {
editorView: view,
tableRef: tableRef,
getNode: getNode,
tableActive: tableActive,
isInDanger: isInDanger,
hoveredRows: hoveredRows,
hoveredCell: hoveredCell,
isTableHovered: isTableHovered,
isResizing: isResizing,
ordering: ordering,
hasHeaderRow: hasHeaderRow
// pass `selection` to control re-render
,
selection: view.state.selection,
headerRowHeight: headerRow ? headerRow.offsetHeight : undefined,
stickyHeader: !this.props.limitedMode ? this.state.stickyHeader : undefined,
getEditorFeatureFlags: getEditorFeatureFlags,
tableContainerWidth: tableContainerWidth,
isNumberColumnEnabled: node.attrs.isNumberColumnEnabled,
getScrollOffset: function getScrollOffset() {
var _this5$wrapper;
return ((_this5$wrapper = _this5.wrapper) === null || _this5$wrapper === void 0 ? void 0 : _this5$wrapper.scrollLeft) || 0;
},
tableWrapperHeight: this.state.tableWrapperHeight,
api: pluginInjectionApi,
isChromelessEditor: options === null || options === void 0 ? void 0 : options.isChromelessEditor
}) : null;
/**
* ED-19838
* There is a getPos issue coming from this code. We need to apply this workaround for now and apply a patch
* before CR6 lands in production
*/
var tablePos;
try {
tablePos = getPos ? getPos() : undefined;
} catch (e) {
tablePos = undefined;
}
var isNested = (0, _nodes.isTableNested)(view.state, tablePos);
var _getEditorFeatureFlag5 = getEditorFeatureFlags(),
_getEditorFeatureFlag6 = _getEditorFeatureFlag5.tableWithFixedColumnWidthsOption,
tableWithFixedColumnWidthsOption = _getEditorFeatureFlag6 === void 0 ? false : _getEditorFeatureFlag6;
var shouldUseIncreasedScalingPercent = !!isTableScalingEnabled && (tableWithFixedColumnWidthsOption || !!((_this$props$options10 = this.props.options) !== null && _this$props$options10 !== void 0 && _this$props$options10.isCommentEditor));
return