@atlaskit/editor-plugin-table 16.1.9 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 16.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`9ee3f2262dfcf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9ee3f2262dfcf) -
8
+ improve performance of table floating toolbar when determine the disabled state of distribute
9
+ column button
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 16.1.9
4
16
 
5
17
  ### Patch Changes
@@ -6,10 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.getToolbarMenuConfig = exports.getToolbarConfig = exports.getToolbarCellOptionsConfig = exports.getClosestSelectionRect = void 0;
9
+ var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
9
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
11
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
12
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
12
13
  var _react = require("@emotion/react");
14
+ var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
15
+ var _memoizeOne = _interopRequireDefault(require("memoize-one"));
13
16
  var _customSteps = require("@atlaskit/custom-steps");
14
17
  var _analytics = require("@atlaskit/editor-common/analytics");
15
18
  var _floatingToolbar = require("@atlaskit/editor-common/floating-toolbar");
@@ -249,14 +252,14 @@ var getToolbarCellOptionsConfig = exports.getToolbarCellOptionsConfig = function
249
252
 
250
253
  // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
251
254
  // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
252
- if (!isLimitedModeEnabled) {
255
+ if (!isLimitedModeEnabled && !(0, _expValEquals.expValEquals)('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
253
256
  var _newResizeStateWithAn, _newResizeStateWithAn2;
254
257
  newResizeStateWithAnalytics = editorView ? (0, _resizeState.getNewResizeStateFromSelectedColumns)(initialSelectionRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor) : undefined;
255
258
  wouldChange = (_newResizeStateWithAn = (_newResizeStateWithAn2 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn2 === void 0 ? void 0 : _newResizeStateWithAn2.changed) !== null && _newResizeStateWithAn !== void 0 ? _newResizeStateWithAn : false;
256
259
  }
257
260
  var distributeColumnWidths = function distributeColumnWidths(state, dispatch, view) {
258
261
  // When optimization is enabled, calculate on-demand when clicked
259
- if (isLimitedModeEnabled) {
262
+ if (isLimitedModeEnabled || (0, _expValEquals.expValEquals)('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
260
263
  if (view) {
261
264
  var resizeState = (0, _resizeState.getNewResizeStateFromSelectedColumns)(initialSelectionRect, state, view.domAtPos.bind(view), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
262
265
  if (resizeState) {
@@ -379,6 +382,27 @@ var getClosestSelectionOrTableRect = function getClosestSelectionOrTableRect(sta
379
382
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
380
383
  return (0, _utils3.isSelectionType)(selection, 'cell') ? (0, _utils3.getSelectionRect)(selection) : tableRect;
381
384
  };
385
+
386
+ // Memoize the expensive DOM queries (querySelector, closestElement) separately
387
+ // Cache key is the parent DOM node reference - stays same when typing in same cell
388
+ var getTableWrapperFromParentImpl = function getTableWrapperFromParentImpl(parent) {
389
+ if (!parent) {
390
+ return undefined;
391
+ }
392
+
393
+ // These are the expensive DOM operations
394
+ var tableRef =
395
+ // Ignored via go/ees005
396
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
397
+ parent.querySelector('table') || undefined;
398
+ if (!tableRef) {
399
+ return undefined;
400
+ }
401
+ return (0, _utils.closestElement)(tableRef, ".".concat(_types.TableCssClassName.TABLE_NODE_WRAPPER)) || undefined;
402
+ };
403
+
404
+ // Create memoized version ONCE - reused across all calls
405
+ var getMemoizedTableWrapperFromParent = (0, _memoizeOne.default)(getTableWrapperFromParentImpl);
382
406
  var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options) {
383
407
  var isTableFixedColumnWidthsOptionEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
384
408
  var shouldUseIncreasedScalingPercent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
@@ -432,7 +456,11 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
432
456
  var isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
433
457
  var areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
434
458
  var editorView = getEditorView();
435
- var getDomRef = function getDomRef(editorView) {
459
+ var getDomRef = (0, _expValEquals.expValEquals)('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? function (editorView) {
460
+ var domAtPos = editorView.domAtPos.bind(editorView);
461
+ var parent = (0, _utils2.findParentDomRefOfType)(nodeType, domAtPos)(state.selection);
462
+ return getMemoizedTableWrapperFromParent(parent);
463
+ } : function (editorView) {
436
464
  var element;
437
465
  var domAtPos = editorView.domAtPos.bind(editorView);
438
466
  var parent = (0, _utils2.findParentDomRefOfType)(nodeType, domAtPos)(state.selection);
@@ -649,21 +677,26 @@ var getColumnSettingItems = function getColumnSettingItems(editorState, editorVi
649
677
  var isCommentEditor = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
650
678
  var isLimitedModeEnabled = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
651
679
  var pluginState = (0, _pluginFactory2.getPluginState)(editorState);
652
- var selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
653
- if (!selectionOrTableRect || !editorView) {
654
- return [];
655
- }
680
+ var items = [];
656
681
  var wouldChange = true; // Default to enabled - show the button.
657
682
  var newResizeStateWithAnalytics;
658
-
659
- // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
660
- // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
661
- if (!isLimitedModeEnabled) {
662
- var _newResizeStateWithAn3, _newResizeStateWithAn4;
663
- newResizeStateWithAnalytics = (0, _resizeState.getNewResizeStateFromSelectedColumns)(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
664
- wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
683
+ if ((0, _expValEquals.expValEquals)('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
684
+ if (!editorView) {
685
+ return [];
686
+ }
687
+ } else {
688
+ var selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
689
+ if (!selectionOrTableRect || !editorView) {
690
+ return [];
691
+ }
692
+ // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
693
+ // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
694
+ if (!isLimitedModeEnabled) {
695
+ var _newResizeStateWithAn3, _newResizeStateWithAn4;
696
+ newResizeStateWithAnalytics = (0, _resizeState.getNewResizeStateFromSelectedColumns)(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
697
+ wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
698
+ }
665
699
  }
666
- var items = [];
667
700
  if (pluginState !== null && pluginState !== void 0 && (_pluginState$pluginCo3 = pluginState.pluginConfig) !== null && _pluginState$pluginCo3 !== void 0 && _pluginState$pluginCo3.allowDistributeColumns && pluginState.isDragAndDropEnabled) {
668
701
  items.push({
669
702
  id: 'editor.table.distributeColumns',
@@ -790,6 +823,7 @@ var getAlignmentOptionsConfig = function getAlignmentOptionsConfig(editorState,
790
823
  value = alignmentIcon.value,
791
824
  icon = alignmentIcon.icon;
792
825
  var currentLayout = tableObject.node.attrs.layout;
826
+ var shouldDisableLayoutOption = (0, _expValEquals.expValEquals)('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? getMemoizedIsLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView !== null, shouldUseIncreasedScalingPercent, isFullWidthEditor) : isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor);
793
827
  return _objectSpread({
794
828
  id: id,
795
829
  type: 'button',
@@ -797,7 +831,7 @@ var getAlignmentOptionsConfig = function getAlignmentOptionsConfig(editorState,
797
831
  title: formatMessage(layoutToMessages[value]),
798
832
  selected: (0, _alignment.normaliseAlignment)(currentLayout) === value,
799
833
  onClick: (0, _commandsWithAnalytics.setTableAlignmentWithAnalytics)(editorAnalyticsAPI, isCommentEditor || false)(value, currentLayout, _analytics.INPUT_METHOD.FLOATING_TB, _analytics.CHANGE_ALIGNMENT_REASON.TOOLBAR_OPTION_CHANGED)
800
- }, isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) && {
834
+ }, shouldDisableLayoutOption && {
801
835
  disabled: value !== 'center'
802
836
  });
803
837
  });
@@ -831,11 +865,44 @@ var getSelectedAlignmentIcon = function getSelectedAlignmentIcon(alignmentIcons,
831
865
  return icon.value === (0, _alignment.normaliseAlignment)(selectedAlignment);
832
866
  });
833
867
  };
834
- var isLayoutOptionDisabled = function isLayoutOptionDisabled(selectedNode, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
868
+ var isLayoutOptionDisabledImpl = function isLayoutOptionDisabledImpl(selectedNode, getEditorContainerWidth, hasEditorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
835
869
  var _getEditorContainerWi = getEditorContainerWidth(),
836
870
  lineLength = _getEditorContainerWi.lineLength;
837
871
  var tableContainerWidth = (0, _nodeWidth.getTableContainerWidth)(selectedNode);
838
872
 
873
+ // table may be scaled, use the scale percent to calculate the table width
874
+ if (hasEditorView) {
875
+ var tableWrapperWidth = tableContainerWidth;
876
+ var scalePercent = (0, _misc.getStaticTableScalingPercent)(selectedNode, tableWrapperWidth, shouldUseIncreasedScalingPercent);
877
+ tableContainerWidth = tableContainerWidth * scalePercent;
878
+ }
879
+
880
+ // If fixed-width editor, we disable 'left-alignment' when table width is 760px.
881
+ // tableContainerWidth +1 here because tableContainerWidth is 759 in fixed-width editor
882
+ if (selectedNode && !isFullWidthEditor && lineLength && tableContainerWidth + 1 >= lineLength) {
883
+ return true;
884
+ }
885
+ return false;
886
+ };
887
+ var getMemoizedIsLayoutOptionDisabled = (0, _memoizeOne.default)(isLayoutOptionDisabledImpl, function (_ref7, _ref8) {
888
+ var _ref9 = (0, _toArray2.default)(_ref7),
889
+ prevNode = _ref9[0],
890
+ prevRest = _ref9.slice(1);
891
+ var _ref0 = (0, _toArray2.default)(_ref8),
892
+ nextNode = _ref0[0],
893
+ nextRest = _ref0.slice(1);
894
+ // Only node needs special comparison (attrs only), rest use reference equality
895
+ var nodeEqual = (0, _isEqual.default)(prevNode.attrs, nextNode.attrs);
896
+ var restEqual = prevRest.every(function (val, idx) {
897
+ return val === nextRest[idx];
898
+ });
899
+ return nodeEqual && restEqual;
900
+ });
901
+ var isLayoutOptionDisabled = function isLayoutOptionDisabled(selectedNode, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
902
+ var _getEditorContainerWi2 = getEditorContainerWidth(),
903
+ lineLength = _getEditorContainerWi2.lineLength;
904
+ var tableContainerWidth = (0, _nodeWidth.getTableContainerWidth)(selectedNode);
905
+
839
906
  // table may be scaled, use the scale percent to calculate the table width
840
907
  if (editorView) {
841
908
  var tableWrapperWidth = tableContainerWidth;
@@ -5,6 +5,8 @@ import _extends from "@babel/runtime/helpers/extends";
5
5
  */
6
6
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
7
7
  import { jsx } from '@emotion/react';
8
+ import isEqual from 'lodash/isEqual';
9
+ import memoizeOne from 'memoize-one';
8
10
  import { TableSortOrder as SortOrder } from '@atlaskit/custom-steps';
9
11
  import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
10
12
  import { DropdownMenuExtensionItems } from '@atlaskit/editor-common/floating-toolbar';
@@ -231,14 +233,14 @@ export const getToolbarCellOptionsConfig = (editorState, editorView, initialSele
231
233
 
232
234
  // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
233
235
  // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
234
- if (!isLimitedModeEnabled) {
236
+ if (!isLimitedModeEnabled && !expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
235
237
  var _newResizeStateWithAn, _newResizeStateWithAn2;
236
238
  newResizeStateWithAnalytics = editorView ? getNewResizeStateFromSelectedColumns(initialSelectionRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor) : undefined;
237
239
  wouldChange = (_newResizeStateWithAn = (_newResizeStateWithAn2 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn2 === void 0 ? void 0 : _newResizeStateWithAn2.changed) !== null && _newResizeStateWithAn !== void 0 ? _newResizeStateWithAn : false;
238
240
  }
239
241
  const distributeColumnWidths = (state, dispatch, view) => {
240
242
  // When optimization is enabled, calculate on-demand when clicked
241
- if (isLimitedModeEnabled) {
243
+ if (isLimitedModeEnabled || expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
242
244
  if (view) {
243
245
  const resizeState = getNewResizeStateFromSelectedColumns(initialSelectionRect, state, view.domAtPos.bind(view), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
244
246
  if (resizeState) {
@@ -362,6 +364,27 @@ const getClosestSelectionOrTableRect = state => {
362
364
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
363
365
  return isSelectionType(selection, 'cell') ? getSelectionRect(selection) : tableRect;
364
366
  };
367
+
368
+ // Memoize the expensive DOM queries (querySelector, closestElement) separately
369
+ // Cache key is the parent DOM node reference - stays same when typing in same cell
370
+ const getTableWrapperFromParentImpl = parent => {
371
+ if (!parent) {
372
+ return undefined;
373
+ }
374
+
375
+ // These are the expensive DOM operations
376
+ const tableRef =
377
+ // Ignored via go/ees005
378
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
379
+ parent.querySelector('table') || undefined;
380
+ if (!tableRef) {
381
+ return undefined;
382
+ }
383
+ return closestElement(tableRef, `.${TableCssClassName.TABLE_NODE_WRAPPER}`) || undefined;
384
+ };
385
+
386
+ // Create memoized version ONCE - reused across all calls
387
+ const getMemoizedTableWrapperFromParent = memoizeOne(getTableWrapperFromParentImpl);
365
388
  export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options, isTableFixedColumnWidthsOptionEnabled = false, shouldUseIncreasedScalingPercent = false) => config => (state, intl) => {
366
389
  const tableObject = findTable(state.selection);
367
390
  const pluginState = getPluginState(state);
@@ -410,7 +433,11 @@ export const getToolbarConfig = (getEditorContainerWidth, api, editorAnalyticsAP
410
433
  const isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
411
434
  const areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
412
435
  const editorView = getEditorView();
413
- const getDomRef = editorView => {
436
+ const getDomRef = expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? editorView => {
437
+ const domAtPos = editorView.domAtPos.bind(editorView);
438
+ const parent = findParentDomRefOfType(nodeType, domAtPos)(state.selection);
439
+ return getMemoizedTableWrapperFromParent(parent);
440
+ } : editorView => {
414
441
  let element;
415
442
  const domAtPos = editorView.domAtPos.bind(editorView);
416
443
  const parent = findParentDomRefOfType(nodeType, domAtPos)(state.selection);
@@ -605,21 +632,26 @@ const getColumnSettingItems = (editorState, editorView, {
605
632
  }, getEditorContainerWidth, api, editorAnalyticsAPI, isTableScalingEnabled = false, isTableFixedColumnWidthsOptionEnabled = false, isCommentEditor = false, isLimitedModeEnabled = false) => {
606
633
  var _pluginState$pluginCo3;
607
634
  const pluginState = getPluginState(editorState);
608
- const selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
609
- if (!selectionOrTableRect || !editorView) {
610
- return [];
611
- }
635
+ const items = [];
612
636
  let wouldChange = true; // Default to enabled - show the button.
613
637
  let newResizeStateWithAnalytics;
614
-
615
- // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
616
- // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
617
- if (!isLimitedModeEnabled) {
618
- var _newResizeStateWithAn3, _newResizeStateWithAn4;
619
- newResizeStateWithAnalytics = getNewResizeStateFromSelectedColumns(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
620
- wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
638
+ if (expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
639
+ if (!editorView) {
640
+ return [];
641
+ }
642
+ } else {
643
+ const selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
644
+ if (!selectionOrTableRect || !editorView) {
645
+ return [];
646
+ }
647
+ // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
648
+ // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
649
+ if (!isLimitedModeEnabled) {
650
+ var _newResizeStateWithAn3, _newResizeStateWithAn4;
651
+ newResizeStateWithAnalytics = getNewResizeStateFromSelectedColumns(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
652
+ wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
653
+ }
621
654
  }
622
- const items = [];
623
655
  if (pluginState !== null && pluginState !== void 0 && (_pluginState$pluginCo3 = pluginState.pluginConfig) !== null && _pluginState$pluginCo3 !== void 0 && _pluginState$pluginCo3.allowDistributeColumns && pluginState.isDragAndDropEnabled) {
624
656
  items.push({
625
657
  id: 'editor.table.distributeColumns',
@@ -737,6 +769,7 @@ const getAlignmentOptionsConfig = (editorState, {
737
769
  icon
738
770
  } = alignmentIcon;
739
771
  const currentLayout = tableObject.node.attrs.layout;
772
+ const shouldDisableLayoutOption = expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? getMemoizedIsLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView !== null, shouldUseIncreasedScalingPercent, isFullWidthEditor) : isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor);
740
773
  return {
741
774
  id: id,
742
775
  type: 'button',
@@ -744,7 +777,7 @@ const getAlignmentOptionsConfig = (editorState, {
744
777
  title: formatMessage(layoutToMessages[value]),
745
778
  selected: normaliseAlignment(currentLayout) === value,
746
779
  onClick: setTableAlignmentWithAnalytics(editorAnalyticsAPI, isCommentEditor || false)(value, currentLayout, INPUT_METHOD.FLOATING_TB, CHANGE_ALIGNMENT_REASON.TOOLBAR_OPTION_CHANGED),
747
- ...(isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) && {
780
+ ...(shouldDisableLayoutOption && {
748
781
  disabled: value !== 'center'
749
782
  })
750
783
  };
@@ -777,6 +810,32 @@ const getSelectedAlignmentIcon = (alignmentIcons, selectedNode) => {
777
810
  const selectedAlignment = selectedNode.attrs.layout;
778
811
  return alignmentIcons.find(icon => icon.value === normaliseAlignment(selectedAlignment));
779
812
  };
813
+ const isLayoutOptionDisabledImpl = (selectedNode, getEditorContainerWidth, hasEditorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) => {
814
+ const {
815
+ lineLength
816
+ } = getEditorContainerWidth();
817
+ let tableContainerWidth = getTableContainerWidth(selectedNode);
818
+
819
+ // table may be scaled, use the scale percent to calculate the table width
820
+ if (hasEditorView) {
821
+ const tableWrapperWidth = tableContainerWidth;
822
+ const scalePercent = getStaticTableScalingPercent(selectedNode, tableWrapperWidth, shouldUseIncreasedScalingPercent);
823
+ tableContainerWidth = tableContainerWidth * scalePercent;
824
+ }
825
+
826
+ // If fixed-width editor, we disable 'left-alignment' when table width is 760px.
827
+ // tableContainerWidth +1 here because tableContainerWidth is 759 in fixed-width editor
828
+ if (selectedNode && !isFullWidthEditor && lineLength && tableContainerWidth + 1 >= lineLength) {
829
+ return true;
830
+ }
831
+ return false;
832
+ };
833
+ const getMemoizedIsLayoutOptionDisabled = memoizeOne(isLayoutOptionDisabledImpl, ([prevNode, ...prevRest], [nextNode, ...nextRest]) => {
834
+ // Only node needs special comparison (attrs only), rest use reference equality
835
+ const nodeEqual = isEqual(prevNode.attrs, nextNode.attrs);
836
+ const restEqual = prevRest.every((val, idx) => val === nextRest[idx]);
837
+ return nodeEqual && restEqual;
838
+ });
780
839
  const isLayoutOptionDisabled = (selectedNode, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) => {
781
840
  const {
782
841
  lineLength
@@ -1,3 +1,4 @@
1
+ import _toArray from "@babel/runtime/helpers/toArray";
1
2
  import _extends from "@babel/runtime/helpers/extends";
2
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
4
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
@@ -9,6 +10,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
9
10
  */
10
11
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
11
12
  import { jsx } from '@emotion/react';
13
+ import isEqual from 'lodash/isEqual';
14
+ import memoizeOne from 'memoize-one';
12
15
  import { TableSortOrder as SortOrder } from '@atlaskit/custom-steps';
13
16
  import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
14
17
  import { DropdownMenuExtensionItems } from '@atlaskit/editor-common/floating-toolbar';
@@ -242,14 +245,14 @@ export var getToolbarCellOptionsConfig = function getToolbarCellOptionsConfig(ed
242
245
 
243
246
  // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
244
247
  // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
245
- if (!isLimitedModeEnabled) {
248
+ if (!isLimitedModeEnabled && !expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
246
249
  var _newResizeStateWithAn, _newResizeStateWithAn2;
247
250
  newResizeStateWithAnalytics = editorView ? getNewResizeStateFromSelectedColumns(initialSelectionRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor) : undefined;
248
251
  wouldChange = (_newResizeStateWithAn = (_newResizeStateWithAn2 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn2 === void 0 ? void 0 : _newResizeStateWithAn2.changed) !== null && _newResizeStateWithAn !== void 0 ? _newResizeStateWithAn : false;
249
252
  }
250
253
  var distributeColumnWidths = function distributeColumnWidths(state, dispatch, view) {
251
254
  // When optimization is enabled, calculate on-demand when clicked
252
- if (isLimitedModeEnabled) {
255
+ if (isLimitedModeEnabled || expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
253
256
  if (view) {
254
257
  var resizeState = getNewResizeStateFromSelectedColumns(initialSelectionRect, state, view.domAtPos.bind(view), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
255
258
  if (resizeState) {
@@ -372,6 +375,27 @@ var getClosestSelectionOrTableRect = function getClosestSelectionOrTableRect(sta
372
375
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
373
376
  return isSelectionType(selection, 'cell') ? getSelectionRect(selection) : tableRect;
374
377
  };
378
+
379
+ // Memoize the expensive DOM queries (querySelector, closestElement) separately
380
+ // Cache key is the parent DOM node reference - stays same when typing in same cell
381
+ var getTableWrapperFromParentImpl = function getTableWrapperFromParentImpl(parent) {
382
+ if (!parent) {
383
+ return undefined;
384
+ }
385
+
386
+ // These are the expensive DOM operations
387
+ var tableRef =
388
+ // Ignored via go/ees005
389
+ // eslint-disable-next-line @atlaskit/editor/no-as-casting
390
+ parent.querySelector('table') || undefined;
391
+ if (!tableRef) {
392
+ return undefined;
393
+ }
394
+ return closestElement(tableRef, ".".concat(TableCssClassName.TABLE_NODE_WRAPPER)) || undefined;
395
+ };
396
+
397
+ // Create memoized version ONCE - reused across all calls
398
+ var getMemoizedTableWrapperFromParent = memoizeOne(getTableWrapperFromParentImpl);
375
399
  export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth, api, editorAnalyticsAPI, getEditorView, options) {
376
400
  var isTableFixedColumnWidthsOptionEnabled = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
377
401
  var shouldUseIncreasedScalingPercent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
@@ -425,7 +449,11 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
425
449
  var isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
426
450
  var areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
427
451
  var editorView = getEditorView();
428
- var getDomRef = function getDomRef(editorView) {
452
+ var getDomRef = expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? function (editorView) {
453
+ var domAtPos = editorView.domAtPos.bind(editorView);
454
+ var parent = findParentDomRefOfType(nodeType, domAtPos)(state.selection);
455
+ return getMemoizedTableWrapperFromParent(parent);
456
+ } : function (editorView) {
429
457
  var element;
430
458
  var domAtPos = editorView.domAtPos.bind(editorView);
431
459
  var parent = findParentDomRefOfType(nodeType, domAtPos)(state.selection);
@@ -642,21 +670,26 @@ var getColumnSettingItems = function getColumnSettingItems(editorState, editorVi
642
670
  var isCommentEditor = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
643
671
  var isLimitedModeEnabled = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
644
672
  var pluginState = getPluginState(editorState);
645
- var selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
646
- if (!selectionOrTableRect || !editorView) {
647
- return [];
648
- }
673
+ var items = [];
649
674
  var wouldChange = true; // Default to enabled - show the button.
650
675
  var newResizeStateWithAnalytics;
651
-
652
- // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
653
- // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
654
- if (!isLimitedModeEnabled) {
655
- var _newResizeStateWithAn3, _newResizeStateWithAn4;
656
- newResizeStateWithAnalytics = getNewResizeStateFromSelectedColumns(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
657
- wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
676
+ if (expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true)) {
677
+ if (!editorView) {
678
+ return [];
679
+ }
680
+ } else {
681
+ var selectionOrTableRect = getClosestSelectionOrTableRect(editorState);
682
+ if (!selectionOrTableRect || !editorView) {
683
+ return [];
684
+ }
685
+ // Performance optimization: Skip expensive getTableScalingPercent() DOM query when limited mode is enabled.
686
+ // This avoids layout reflows on every transaction. Instead, button stays enabled and calculates on-demand when clicked.
687
+ if (!isLimitedModeEnabled) {
688
+ var _newResizeStateWithAn3, _newResizeStateWithAn4;
689
+ newResizeStateWithAnalytics = getNewResizeStateFromSelectedColumns(selectionOrTableRect, editorState, editorView.domAtPos.bind(editorView), getEditorContainerWidth, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, isCommentEditor);
690
+ wouldChange = (_newResizeStateWithAn3 = (_newResizeStateWithAn4 = newResizeStateWithAnalytics) === null || _newResizeStateWithAn4 === void 0 ? void 0 : _newResizeStateWithAn4.changed) !== null && _newResizeStateWithAn3 !== void 0 ? _newResizeStateWithAn3 : false;
691
+ }
658
692
  }
659
- var items = [];
660
693
  if (pluginState !== null && pluginState !== void 0 && (_pluginState$pluginCo3 = pluginState.pluginConfig) !== null && _pluginState$pluginCo3 !== void 0 && _pluginState$pluginCo3.allowDistributeColumns && pluginState.isDragAndDropEnabled) {
661
694
  items.push({
662
695
  id: 'editor.table.distributeColumns',
@@ -783,6 +816,7 @@ var getAlignmentOptionsConfig = function getAlignmentOptionsConfig(editorState,
783
816
  value = alignmentIcon.value,
784
817
  icon = alignmentIcon.icon;
785
818
  var currentLayout = tableObject.node.attrs.layout;
819
+ var shouldDisableLayoutOption = expValEquals('platform_editor_table_toolbar_perf_fix', 'isEnabled', true) ? getMemoizedIsLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView !== null, shouldUseIncreasedScalingPercent, isFullWidthEditor) : isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor);
786
820
  return _objectSpread({
787
821
  id: id,
788
822
  type: 'button',
@@ -790,7 +824,7 @@ var getAlignmentOptionsConfig = function getAlignmentOptionsConfig(editorState,
790
824
  title: formatMessage(layoutToMessages[value]),
791
825
  selected: normaliseAlignment(currentLayout) === value,
792
826
  onClick: setTableAlignmentWithAnalytics(editorAnalyticsAPI, isCommentEditor || false)(value, currentLayout, INPUT_METHOD.FLOATING_TB, CHANGE_ALIGNMENT_REASON.TOOLBAR_OPTION_CHANGED)
793
- }, isLayoutOptionDisabled(tableObject.node, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) && {
827
+ }, shouldDisableLayoutOption && {
794
828
  disabled: value !== 'center'
795
829
  });
796
830
  });
@@ -824,11 +858,44 @@ var getSelectedAlignmentIcon = function getSelectedAlignmentIcon(alignmentIcons,
824
858
  return icon.value === normaliseAlignment(selectedAlignment);
825
859
  });
826
860
  };
827
- var isLayoutOptionDisabled = function isLayoutOptionDisabled(selectedNode, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
861
+ var isLayoutOptionDisabledImpl = function isLayoutOptionDisabledImpl(selectedNode, getEditorContainerWidth, hasEditorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
828
862
  var _getEditorContainerWi = getEditorContainerWidth(),
829
863
  lineLength = _getEditorContainerWi.lineLength;
830
864
  var tableContainerWidth = getTableContainerWidth(selectedNode);
831
865
 
866
+ // table may be scaled, use the scale percent to calculate the table width
867
+ if (hasEditorView) {
868
+ var tableWrapperWidth = tableContainerWidth;
869
+ var scalePercent = getStaticTableScalingPercent(selectedNode, tableWrapperWidth, shouldUseIncreasedScalingPercent);
870
+ tableContainerWidth = tableContainerWidth * scalePercent;
871
+ }
872
+
873
+ // If fixed-width editor, we disable 'left-alignment' when table width is 760px.
874
+ // tableContainerWidth +1 here because tableContainerWidth is 759 in fixed-width editor
875
+ if (selectedNode && !isFullWidthEditor && lineLength && tableContainerWidth + 1 >= lineLength) {
876
+ return true;
877
+ }
878
+ return false;
879
+ };
880
+ var getMemoizedIsLayoutOptionDisabled = memoizeOne(isLayoutOptionDisabledImpl, function (_ref7, _ref8) {
881
+ var _ref9 = _toArray(_ref7),
882
+ prevNode = _ref9[0],
883
+ prevRest = _ref9.slice(1);
884
+ var _ref0 = _toArray(_ref8),
885
+ nextNode = _ref0[0],
886
+ nextRest = _ref0.slice(1);
887
+ // Only node needs special comparison (attrs only), rest use reference equality
888
+ var nodeEqual = isEqual(prevNode.attrs, nextNode.attrs);
889
+ var restEqual = prevRest.every(function (val, idx) {
890
+ return val === nextRest[idx];
891
+ });
892
+ return nodeEqual && restEqual;
893
+ });
894
+ var isLayoutOptionDisabled = function isLayoutOptionDisabled(selectedNode, getEditorContainerWidth, editorView, shouldUseIncreasedScalingPercent, isFullWidthEditor) {
895
+ var _getEditorContainerWi2 = getEditorContainerWidth(),
896
+ lineLength = _getEditorContainerWi2.lineLength;
897
+ var tableContainerWidth = getTableContainerWidth(selectedNode);
898
+
832
899
  // table may be scaled, use the scale percent to calculate the table width
833
900
  if (editorView) {
834
901
  var tableWrapperWidth = tableContainerWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "16.1.9",
3
+ "version": "16.2.0",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -57,10 +57,10 @@
57
57
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
58
58
  "@atlaskit/primitives": "^17.0.0",
59
59
  "@atlaskit/theme": "^21.0.0",
60
- "@atlaskit/tmp-editor-statsig": "^16.11.0",
60
+ "@atlaskit/tmp-editor-statsig": "^16.15.0",
61
61
  "@atlaskit/toggle": "^15.2.0",
62
62
  "@atlaskit/tokens": "^9.1.0",
63
- "@atlaskit/tooltip": "^20.12.0",
63
+ "@atlaskit/tooltip": "^20.13.0",
64
64
  "@babel/runtime": "^7.0.0",
65
65
  "@emotion/react": "^11.7.1",
66
66
  "classnames": "^2.2.5",