@atlaskit/editor-plugin-table 19.0.1 → 20.0.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cjs/nodeviews/table.js +18 -2
  3. package/dist/cjs/nodeviews/toDOM.js +18 -4
  4. package/dist/cjs/pm-plugins/main.js +38 -4
  5. package/dist/cjs/pm-plugins/table-width.js +10 -0
  6. package/dist/cjs/pm-plugins/transforms/content-mode.js +48 -0
  7. package/dist/cjs/pm-plugins/transforms/fix-tables.js +4 -35
  8. package/dist/cjs/pm-plugins/transforms/table-transform-utils.js +62 -0
  9. package/dist/cjs/pm-plugins/utils/tableMode.js +149 -0
  10. package/dist/cjs/ui/event-handlers.js +3 -2
  11. package/dist/cjs/ui/toolbar.js +25 -2
  12. package/dist/es2019/nodeviews/table.js +18 -2
  13. package/dist/es2019/nodeviews/toDOM.js +18 -4
  14. package/dist/es2019/pm-plugins/main.js +38 -4
  15. package/dist/es2019/pm-plugins/table-width.js +10 -0
  16. package/dist/es2019/pm-plugins/transforms/content-mode.js +39 -0
  17. package/dist/es2019/pm-plugins/transforms/fix-tables.js +2 -33
  18. package/dist/es2019/pm-plugins/transforms/table-transform-utils.js +56 -0
  19. package/dist/es2019/pm-plugins/utils/tableMode.js +148 -0
  20. package/dist/es2019/ui/event-handlers.js +4 -3
  21. package/dist/es2019/ui/toolbar.js +23 -2
  22. package/dist/esm/nodeviews/table.js +18 -2
  23. package/dist/esm/nodeviews/toDOM.js +18 -4
  24. package/dist/esm/pm-plugins/main.js +38 -4
  25. package/dist/esm/pm-plugins/table-width.js +10 -0
  26. package/dist/esm/pm-plugins/transforms/content-mode.js +41 -0
  27. package/dist/esm/pm-plugins/transforms/fix-tables.js +2 -33
  28. package/dist/esm/pm-plugins/transforms/table-transform-utils.js +56 -0
  29. package/dist/esm/pm-plugins/utils/tableMode.js +143 -0
  30. package/dist/esm/ui/event-handlers.js +4 -3
  31. package/dist/esm/ui/toolbar.js +25 -2
  32. package/dist/types/pm-plugins/transforms/content-mode.d.ts +8 -0
  33. package/dist/types/pm-plugins/transforms/table-transform-utils.d.ts +11 -0
  34. package/dist/types/pm-plugins/utils/tableMode.d.ts +22 -0
  35. package/dist/types/types/index.d.ts +3 -0
  36. package/dist/types-ts4.5/pm-plugins/transforms/content-mode.d.ts +8 -0
  37. package/dist/types-ts4.5/pm-plugins/transforms/table-transform-utils.d.ts +11 -0
  38. package/dist/types-ts4.5/pm-plugins/utils/tableMode.d.ts +22 -0
  39. package/dist/types-ts4.5/types/index.d.ts +3 -0
  40. package/package.json +21 -20
@@ -33,6 +33,7 @@ var _alignImageLeft = _interopRequireDefault(require("@atlaskit/icon/core/align-
33
33
  var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
34
34
  var _customize = _interopRequireDefault(require("@atlaskit/icon/core/customize"));
35
35
  var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
36
+ var _shrinkHorizontal = _interopRequireDefault(require("@atlaskit/icon/core/shrink-horizontal"));
36
37
  var _tableColumnsDistribute = _interopRequireDefault(require("@atlaskit/icon/core/table-columns-distribute"));
37
38
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
38
39
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
@@ -49,6 +50,7 @@ var _alignment = require("../pm-plugins/utils/alignment");
49
50
  var _nodes = require("../pm-plugins/utils/nodes");
50
51
  var _selection = require("../pm-plugins/utils/selection");
51
52
  var _table = require("../pm-plugins/utils/table");
53
+ var _tableMode = require("../pm-plugins/utils/tableMode");
52
54
  var _types = require("../types");
53
55
  var _FloatingAlignmentButtons = require("./FloatingAlignmentButtons/FloatingAlignmentButtons");
54
56
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
@@ -448,7 +450,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
448
450
  // We don't want to show floating toolbar while resizing the table
449
451
  var isWidthResizing = tableWidthState === null || tableWidthState === void 0 ? void 0 : tableWidthState.resizing;
450
452
  if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
451
- var _api$limitedMode$shar, _api$limitedMode, _api$extension, _api$extension2;
453
+ var _api$limitedMode$shar, _api$limitedMode, _api$editorViewMode2, _api$extension, _api$extension2;
452
454
  var isNested = pluginState.tablePos && (0, _nodes.isTableNested)(state, pluginState.tablePos);
453
455
  var isTableScalingWithFixedColumnWidthsOptionShown = isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && !isNested;
454
456
  var areTableColumWidthsFixed = tableObject.node.attrs.displayMode === 'fixed';
@@ -478,6 +480,27 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
478
480
  var cellItems = pluginState.isDragAndDropEnabled ? [] : getCellItems(state, editorView, intl, getEditorContainerWidth, api, editorAnalyticsAPI, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, shouldUseIncreasedScalingPercent, options === null || options === void 0 ? void 0 : options.isCommentEditor, isLimitedModeEnabled);
479
481
  var columnSettingsItems = pluginState.isDragAndDropEnabled ? getColumnSettingItems(state, editorView, intl, getEditorContainerWidth, api, editorAnalyticsAPI, isTableScalingEnabled, isTableFixedColumnWidthsOptionEnabled, options === null || options === void 0 ? void 0 : options.isCommentEditor, isLimitedModeEnabled) : [];
480
482
  var colorPicker = !areAnyNewToolbarFlagsEnabled ? getColorPicker(state, menu, intl, editorAnalyticsAPI, getEditorView) : [];
483
+ var fitToContentButton = (0, _tableMode.isContentModeSupported)({
484
+ allowColumnResizing: !!pluginState.pluginConfig.allowColumnResizing,
485
+ allowTableResizing: !!pluginState.pluginConfig.allowTableResizing,
486
+ isFullPageEditor: !pluginState.isChromelessEditor && !pluginState.isCommentEditor
487
+ }) && !isNested && (api === null || api === void 0 || (_api$editorViewMode2 = api.editorViewMode) === null || _api$editorViewMode2 === void 0 || (_api$editorViewMode2 = _api$editorViewMode2.sharedState.currentState()) === null || _api$editorViewMode2 === void 0 ? void 0 : _api$editorViewMode2.mode) !== 'view' && (0, _expValEquals.expValEquals)('platform_editor_table_fit_to_content_on_demand', 'isEnabled', true) ? [{
488
+ id: 'editor.table.fitToContent',
489
+ type: 'button',
490
+ title: intl.formatMessage(_messages.tableMessages.fitToContent),
491
+ icon: function icon() {
492
+ return (0, _react.jsx)(_shrinkHorizontal.default, {
493
+ spacing: 'spacious',
494
+ label: ''
495
+ });
496
+ },
497
+ onClick: function onClick(_state, _dispatch, view) {
498
+ if (view) {
499
+ (0, _tableMode.applyMeasuredWidthToSelectedTable)(view, api !== null && api !== void 0 ? api : undefined);
500
+ }
501
+ return true;
502
+ }
503
+ }] : [];
481
504
 
482
505
  // Check if we need to show confirm dialog for delete button
483
506
  var confirmDialog;
@@ -556,7 +579,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(getE
556
579
  },
557
580
  zIndex: _editorSharedStyles.akEditorFloatingPanelZIndex + 1,
558
581
  // Place the context menu slightly above the others
559
- items: [menu].concat((0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [separator(menu.hidden)] : []), (0, _toConsumableArray2.default)(alignmentMenu), (0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [separator(alignmentMenu.length === 0)] : []), (0, _toConsumableArray2.default)(cellItems), (0, _toConsumableArray2.default)(columnSettingsItems), (0, _toConsumableArray2.default)(colorPicker), (0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [{
582
+ items: [menu].concat((0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [separator(menu.hidden)] : []), (0, _toConsumableArray2.default)(alignmentMenu), (0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [separator(alignmentMenu.length === 0)] : []), (0, _toConsumableArray2.default)(cellItems), (0, _toConsumableArray2.default)(columnSettingsItems), fitToContentButton, (0, _toConsumableArray2.default)(colorPicker), (0, _toConsumableArray2.default)(!areAnyNewToolbarFlagsEnabled ? [{
560
583
  type: 'extensions-placeholder',
561
584
  separator: 'end'
562
585
  }, copyButton, {
@@ -8,10 +8,12 @@ import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
8
8
  import { TableMap } from '@atlaskit/editor-tables/table-map';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
11
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
11
12
  import { pluginConfig as getPluginConfig } from '../pm-plugins/create-plugin-config';
12
13
  import { getPluginState } from '../pm-plugins/plugin-factory';
13
14
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
14
15
  import { isTableNested, tablesHaveDifferentColumnWidths } from '../pm-plugins/utils/nodes';
16
+ import { isTableInContentMode } from '../pm-plugins/utils/tableMode';
15
17
  import { TableComponentWithSharedState } from './TableComponentWithSharedState';
16
18
  import { tableNodeSpecWithFixedToDOM } from './toDOM';
17
19
  const tableAttributes = node => {
@@ -176,17 +178,31 @@ export default class TableView extends ReactNodeView {
176
178
  }
177
179
  }
178
180
  setDomAttrs(node) {
179
- var _this$reactComponentP6, _this$getEditorFeatur2, _this$options3, _this$options4;
181
+ var _this$reactComponentP8, _this$getEditorFeatur2, _this$options3, _this$options4;
180
182
  if (!this.table) {
181
183
  return; // width / attribute application to actual table will happen later when table is set
182
184
  }
183
185
  const attrs = tableAttributes(node);
186
+ if (expValEqualsNoExposure('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
187
+ var _this$reactComponentP6, _this$reactComponentP7;
188
+ if (isTableInContentMode({
189
+ node,
190
+ allowColumnResizing: !!this.reactComponentProps.allowColumnResizing,
191
+ allowTableResizing: !!this.reactComponentProps.allowTableResizing,
192
+ isFullPageEditor: !((_this$reactComponentP6 = this.reactComponentProps.options) !== null && _this$reactComponentP6 !== void 0 && _this$reactComponentP6.isCommentEditor) && !((_this$reactComponentP7 = this.reactComponentProps.options) !== null && _this$reactComponentP7 !== void 0 && _this$reactComponentP7.isChromelessEditor),
193
+ isTableNested: isTableNested(this.view.state, this.getPos())
194
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
195
+ attrs['data-initial-width-mode'] = 'content';
196
+ } else {
197
+ this.table.removeAttribute('data-initial-width-mode');
198
+ }
199
+ }
184
200
  Object.keys(attrs).forEach(attr => {
185
201
  // Ignored via go/ees005
186
202
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
187
203
  this.table.setAttribute(attr, attrs[attr]);
188
204
  });
189
- const isTableFixedColumnWidthsOptionEnabled = (fg('platform_editor_table_fixed_column_width_prop') ? (_this$reactComponentP6 = this.reactComponentProps) === null || _this$reactComponentP6 === void 0 ? void 0 : _this$reactComponentP6.allowFixedColumnWidthOption : (_this$getEditorFeatur2 = this.getEditorFeatureFlags) === null || _this$getEditorFeatur2 === void 0 ? void 0 : _this$getEditorFeatur2.call(this).tableWithFixedColumnWidthsOption) || false;
205
+ const isTableFixedColumnWidthsOptionEnabled = (fg('platform_editor_table_fixed_column_width_prop') ? (_this$reactComponentP8 = this.reactComponentProps) === null || _this$reactComponentP8 === void 0 ? void 0 : _this$reactComponentP8.allowFixedColumnWidthOption : (_this$getEditorFeatur2 = this.getEditorFeatureFlags) === null || _this$getEditorFeatur2 === void 0 ? void 0 : _this$getEditorFeatur2.call(this).tableWithFixedColumnWidthsOption) || false;
190
206
  // Preserve Table Width cannot have inline width set on the table
191
207
  if (!((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.isTableScalingEnabled) || (_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.isTableScalingEnabled && isTableFixedColumnWidthsOptionEnabled && node.attrs.displayMode === 'fixed') {
192
208
  var _tableWidthPluginKey$;
@@ -1,3 +1,4 @@
1
+ import classNames from 'classnames';
1
2
  import kebabCase from 'lodash/kebabCase';
2
3
  import { table, tableWithNestedTable } from '@atlaskit/adf-schema';
3
4
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
@@ -5,15 +6,23 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
6
  import { generateColgroupFromNode, getResizerMinWidth } from '../pm-plugins/table-resizing/utils/colgroup';
6
7
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from '../pm-plugins/table-resizing/utils/consts';
7
8
  import { getTableResizerContainerMaxWidthInCSS, getTableResizerContainerForFullPageWidthInCSS, getTableResizerItemWidthInCSS } from '../pm-plugins/table-resizing/utils/misc';
9
+ import { isTableInContentMode } from '../pm-plugins/utils/tableMode';
8
10
  import { getAlignmentStyle } from './table-container-styles';
9
11
  export const tableNodeSpecWithFixedToDOM = config => {
10
12
  const tableNode = config.isNestingSupported ? tableWithNestedTable : table;
11
13
  return {
12
14
  ...tableNode,
13
15
  toDOM: node => {
16
+ const isFullPageEditor = !config.isChromelessEditor && !config.isCommentEditor;
17
+ const isInContentMode = isTableInContentMode({
18
+ node,
19
+ allowColumnResizing: config.allowColumnResizing,
20
+ allowTableResizing: config.tableResizingEnabled,
21
+ isFullPageEditor,
22
+ isTableNested: config.isNested
23
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true);
14
24
  const alignmentStyle = Object.entries(getAlignmentStyle(node.attrs.layout)).map(([k, v]) => `${kebabCase(k)}: ${kebabCase(v)}`).join(';');
15
25
  const tableMinWidth = getResizerMinWidth(node);
16
- const isFullPageEditor = !config.isChromelessEditor && !config.isCommentEditor;
17
26
  const attrs = {
18
27
  'data-number-column': node.attrs.isNumberColumnEnabled,
19
28
  'data-layout': node.attrs.layout,
@@ -23,6 +32,9 @@ export const tableNodeSpecWithFixedToDOM = config => {
23
32
  'data-ssr-placeholder': `table-${node.attrs.localId}`,
24
33
  'data-ssr-placeholder-replace': `table-${node.attrs.localId}`
25
34
  };
35
+ if (isInContentMode) {
36
+ attrs['data-initial-width-mode'] = 'content';
37
+ }
26
38
  if (expValEquals('platform_editor_table_display_mode_in_to_dom', 'isEnabled', true)) {
27
39
  attrs['data-table-display-mode'] = node.attrs.displayMode;
28
40
  }
@@ -75,11 +87,13 @@ export const tableNodeSpecWithFixedToDOM = config => {
75
87
  class: 'pm-table-resizer-container',
76
88
  style: convertToInlineCss({
77
89
  '--ak-editor-table-gutter-padding': config.isTableScalingEnabled ? 'calc(var(--ak-editor--large-gutter-padding) * 2)' : 'calc(var(--ak-editor--large-gutter-padding) * 2 - var(--ak-editor-resizer-handle-spacing))',
78
- '--ak-editor-table-width': resizableTableWidth,
90
+ '--ak-editor-table-width': isInContentMode ? 'max-content' : resizableTableWidth,
79
91
  width: `var(--ak-editor-table-width)`
80
92
  })
81
93
  }, ['div', {
82
- class: 'resizer-item display-handle',
94
+ class: expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true) ? 'resizer-item display-handle' : classNames('resizer-item', {
95
+ 'display-handle': !isInContentMode
96
+ }),
83
97
  style: convertToInlineCss({
84
98
  position: 'relative',
85
99
  userSelect: 'auto',
@@ -88,7 +102,7 @@ export const tableNodeSpecWithFixedToDOM = config => {
88
102
  '--ak-editor-table-min-width': `${tableMinWidth}px`,
89
103
  minWidth: 'var(--ak-editor-table-min-width)',
90
104
  maxWidth: getTableResizerContainerMaxWidthInCSS(config.isCommentEditor, config.isChromelessEditor, config.isTableScalingEnabled),
91
- width: getTableResizerItemWidthInCSS(node, config.isCommentEditor, config.isChromelessEditor)
105
+ width: isInContentMode ? 'auto' : getTableResizerItemWidthInCSS(node, config.isCommentEditor, config.isChromelessEditor)
92
106
  })
93
107
  }, ['span', {
94
108
  class: 'resizer-hover-zone'
@@ -1,3 +1,4 @@
1
+ import { bind } from 'bind-event-listener';
1
2
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
3
  import { getBrowserInfo } from '@atlaskit/editor-common/browser';
3
4
  import { insideTable } from '@atlaskit/editor-common/core-utils';
@@ -24,10 +25,13 @@ import { fixTables } from './transforms/fix-tables';
24
25
  import { replaceSelectedTable } from './transforms/replace-table';
25
26
  import { findControlsHoverDecoration } from './utils/decoration';
26
27
  import { transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, transformSliceToRemoveOpenTable, transformSliceToRemoveNestedTables, isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
28
+ import { applyMeasuredWidthToAllTables, isContentModeSupported } from './utils/tableMode';
27
29
  export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, dragAndDropEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor, allowFixedColumnWidthOption) => {
28
30
  var _accessibilityUtils;
29
31
  const state = createPluginState(dispatch, {
30
32
  pluginConfig,
33
+ isCommentEditor,
34
+ isChromelessEditor,
31
35
  isTableHovered: false,
32
36
  insertColumnButtonIndex: undefined,
33
37
  insertRowButtonIndex: undefined,
@@ -117,8 +121,34 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
117
121
  }
118
122
  },
119
123
  view: editorView => {
124
+ var _pluginInjectionApi$e, _pluginInjectionApi$e2;
120
125
  const domAtPos = editorView.domAtPos.bind(editorView);
121
126
  editorViewRef = editorView;
127
+ let contentModeSizeTableId = null;
128
+ let focusListenerBinding = null;
129
+ if ((pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$e = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e === void 0 ? void 0 : (_pluginInjectionApi$e2 = _pluginInjectionApi$e.sharedState.currentState()) === null || _pluginInjectionApi$e2 === void 0 ? void 0 : _pluginInjectionApi$e2.mode) !== 'view' && isContentModeSupported({
130
+ allowColumnResizing: !!pluginConfig.allowColumnResizing,
131
+ allowTableResizing: !!pluginConfig.allowTableResizing,
132
+ isFullPageEditor: !isChromelessEditor && !isCommentEditor
133
+ }) && expValEquals('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
134
+ focusListenerBinding = bind(editorView.dom, {
135
+ type: 'focus',
136
+ listener: () => {
137
+ if (contentModeSizeTableId) {
138
+ return;
139
+ }
140
+ contentModeSizeTableId = requestAnimationFrame(() => {
141
+ if (!editorViewRef) {
142
+ return;
143
+ }
144
+ applyMeasuredWidthToAllTables(editorViewRef, pluginInjectionApi);
145
+ });
146
+ },
147
+ options: {
148
+ once: true
149
+ }
150
+ });
151
+ }
122
152
  return {
123
153
  update: (view, prevState) => {
124
154
  const {
@@ -131,12 +161,12 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
131
161
  const pluginState = getPluginState(state);
132
162
  let tableRef;
133
163
  if (fg('platform_editor_enable_table_dnd')) {
134
- var _pluginInjectionApi$e, _pluginInjectionApi$e2;
164
+ var _pluginInjectionApi$e3, _pluginInjectionApi$e4;
135
165
  const parent = findParentDomRefOfType(state.schema.nodes.table, domAtPos)(selection);
136
- let shouldSetTableRef = fg('platform_editor_enable_table_dnd_patch_1') ? parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$e = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e === void 0 ? void 0 : (_pluginInjectionApi$e2 = _pluginInjectionApi$e.sharedState.currentState()) === null || _pluginInjectionApi$e2 === void 0 ? void 0 : _pluginInjectionApi$e2.mode) !== 'view' : parent;
166
+ let shouldSetTableRef = fg('platform_editor_enable_table_dnd_patch_1') ? parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$e3 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e3 === void 0 ? void 0 : (_pluginInjectionApi$e4 = _pluginInjectionApi$e3.sharedState.currentState()) === null || _pluginInjectionApi$e4 === void 0 ? void 0 : _pluginInjectionApi$e4.mode) !== 'view' : parent;
137
167
  if (expValEquals('platform_editor_table_update_table_ref', 'isEnabled', true) && fg('platform_editor_update_table_ref_fix')) {
138
- var _pluginInjectionApi$e3, _pluginInjectionApi$e4, _pluginInjectionApi$i, _pluginInjectionApi$i2;
139
- shouldSetTableRef = parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$e3 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e3 === void 0 ? void 0 : (_pluginInjectionApi$e4 = _pluginInjectionApi$e3.sharedState.currentState()) === null || _pluginInjectionApi$e4 === void 0 ? void 0 : _pluginInjectionApi$e4.mode) !== 'view' && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$i = pluginInjectionApi.interaction) === null || _pluginInjectionApi$i === void 0 ? void 0 : (_pluginInjectionApi$i2 = _pluginInjectionApi$i.sharedState.currentState()) === null || _pluginInjectionApi$i2 === void 0 ? void 0 : _pluginInjectionApi$i2.interactionState) !== 'hasNotHadInteraction';
168
+ var _pluginInjectionApi$e5, _pluginInjectionApi$e6, _pluginInjectionApi$i, _pluginInjectionApi$i2;
169
+ shouldSetTableRef = parent && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$e5 = pluginInjectionApi.editorViewMode) === null || _pluginInjectionApi$e5 === void 0 ? void 0 : (_pluginInjectionApi$e6 = _pluginInjectionApi$e5.sharedState.currentState()) === null || _pluginInjectionApi$e6 === void 0 ? void 0 : _pluginInjectionApi$e6.mode) !== 'view' && (pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$i = pluginInjectionApi.interaction) === null || _pluginInjectionApi$i === void 0 ? void 0 : (_pluginInjectionApi$i2 = _pluginInjectionApi$i.sharedState.currentState()) === null || _pluginInjectionApi$i2 === void 0 ? void 0 : _pluginInjectionApi$i2.interactionState) !== 'hasNotHadInteraction';
140
170
  }
141
171
  if (shouldSetTableRef) {
142
172
  tableRef =
@@ -199,6 +229,10 @@ export const createPlugin = (dispatchAnalyticsEvent, dispatch, portalProviderAPI
199
229
  } else if (pluginState.isResizeHandleWidgetAdded) {
200
230
  removeResizeHandleDecorations()(state, dispatch);
201
231
  }
232
+ },
233
+ destroy: () => {
234
+ contentModeSizeTableId && cancelAnimationFrame(contentModeSizeTableId);
235
+ focusListenerBinding && focusListenerBinding();
202
236
  }
203
237
  };
204
238
  },
@@ -12,6 +12,7 @@ import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorMaxWi
12
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
13
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from './table-resizing/utils/consts';
14
14
  import { ALIGN_START } from './utils/alignment';
15
+ import { isTableInContentMode } from './utils/tableMode';
15
16
  export const pluginKey = new PluginKey('tableWidthPlugin');
16
17
  const createPlugin = (dispatch, dispatchAnalyticsEvent, fullWidthEnabled, maxWidthEnabled, isTableScalingEnabled, isTableAlignmentEnabled, isCommentEditor) => {
17
18
  return new SafePlugin({
@@ -61,6 +62,15 @@ const createPlugin = (dispatch, dispatchAnalyticsEvent, fullWidthEnabled, maxWid
61
62
  const tr = newState.tr;
62
63
  if (isReplaceDocumentOperation && !isCommentEditor) {
63
64
  newState.doc.forEach((node, offset) => {
65
+ if (isTableInContentMode({
66
+ node,
67
+ allowColumnResizing: true,
68
+ allowTableResizing: true,
69
+ isFullPageEditor: true,
70
+ isTableNested: false
71
+ })) {
72
+ return;
73
+ }
64
74
  if (node.type === table) {
65
75
  const width = node.attrs.width;
66
76
  const layout = node.attrs.layout;
@@ -0,0 +1,39 @@
1
+ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
2
+ import { akEditorFullWidthLayoutWidth, akEditorMaxLayoutWidth } from '@atlaskit/editor-shared-styles';
3
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
+ import { updateCellsMarkup } from './table-transform-utils';
5
+ const tableWidth = contentWidth => {
6
+ const maxEditorWidth = expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? akEditorMaxLayoutWidth : akEditorFullWidthLayoutWidth;
7
+ return Math.min(maxEditorWidth, contentWidth);
8
+ };
9
+ export const getTableMeasurement = tableRef => {
10
+ const colWidths = getRenderedColgroupColumnWidths(tableRef);
11
+ const totalContentWidth = colWidths.reduce((acc, current) => acc + current, 0);
12
+ return {
13
+ colWidths,
14
+ tableWidth: tableWidth(totalContentWidth)
15
+ };
16
+ };
17
+ export const applyTableMeasurement = (tr, tableNode, {
18
+ colWidths,
19
+ tableWidth
20
+ }, tablePos) => {
21
+ tr = updateCellsMarkup(tr, tableNode, tablePos, (cell, _rowIndex, colIndex) => {
22
+ const newColWidths = colWidths.slice(colIndex, colIndex + cell.attrs.colspan);
23
+ return cell.type.createChecked({
24
+ ...cell.attrs,
25
+ colwidth: newColWidths.length ? newColWidths : null
26
+ }, cell.content, cell.marks);
27
+ });
28
+ return tr.setNodeMarkup(tablePos, undefined, {
29
+ ...tableNode.attrs,
30
+ width: tableWidth
31
+ });
32
+ };
33
+ function getRenderedColgroupColumnWidths(tableRef) {
34
+ const cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
35
+ return cols.map(col => {
36
+ const width = col.getBoundingClientRect().width;
37
+ return Math.max(Math.round(width), tableCellMinWidth);
38
+ });
39
+ }
@@ -3,6 +3,7 @@ import { akEditorDefaultLayoutWidth, akEditorWideLayoutWidth } from '@atlaskit/e
3
3
  import { calculateColumnWidth, getCellsRefsInColumn } from '../table-resizing/utils/column-state';
4
4
  import { contentWidth } from '../table-resizing/utils/content-width';
5
5
  import { getLayoutSize } from '../table-resizing/utils/misc';
6
+ import { replaceCells } from './table-transform-utils';
6
7
  const validateTableCellNodeAttrs = ({
7
8
  colspan,
8
9
  rowspan,
@@ -153,36 +154,4 @@ function parseDOMColumnWidths(domAtPos, tableNode, tableStart, tableRef) {
153
154
  }
154
155
  }
155
156
  return cols;
156
- }
157
-
158
- // TODO: ED-26961 - move to prosemirror-utils
159
- const replaceCells = (tr, table, tablePos, modifyCell) => {
160
- const rows = [];
161
- let modifiedCells = 0;
162
- for (let rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
163
- const row = table.child(rowIndex);
164
- const cells = [];
165
- for (let colIndex = 0; colIndex < row.childCount; colIndex++) {
166
- const cell = row.child(colIndex);
167
-
168
- // TODO: ED-26961 - The rowIndex and colIndex are not accurate in a merged cell scenario
169
- // e.g. table with 5 columns might have only one cell in a row, colIndex will be 1, where it should be 4
170
- const node = modifyCell(cell, rowIndex, colIndex);
171
- if (node.sameMarkup(cell) === false) {
172
- modifiedCells++;
173
- }
174
- cells.push(node);
175
- }
176
- if (cells.length) {
177
- rows.push(row.type.createChecked(row.attrs, cells, row.marks));
178
- }
179
- }
180
-
181
- // Check if the table has changed before replacing.
182
- // If no cells are modified our counter will be zero.
183
- if (rows.length && modifiedCells !== 0) {
184
- const newTable = table.type.createChecked(table.attrs, rows, table.marks);
185
- return tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
186
- }
187
- return tr;
188
- };
157
+ }
@@ -0,0 +1,56 @@
1
+ // TODO: ED-26961 - move to prosemirror-utils
2
+ export const replaceCells = (tr, table, tablePos, modifyCell) => {
3
+ const rows = [];
4
+ let modifiedCells = 0;
5
+ for (let rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
6
+ const row = table.child(rowIndex);
7
+ const cells = [];
8
+ for (let colIndex = 0; colIndex < row.childCount; colIndex++) {
9
+ const cell = row.child(colIndex);
10
+
11
+ // TODO: ED-26961 - The rowIndex and colIndex are not accurate in a merged cell scenario
12
+ // e.g. table with 5 columns might have only one cell in a row, colIndex will be 1, where it should be 4
13
+ const node = modifyCell(cell, rowIndex, colIndex);
14
+ if (node.sameMarkup(cell) === false) {
15
+ modifiedCells++;
16
+ }
17
+ cells.push(node);
18
+ }
19
+ if (cells.length) {
20
+ rows.push(row.type.createChecked(row.attrs, cells, row.marks));
21
+ }
22
+ }
23
+
24
+ // Check if the table has changed before replacing.
25
+ // If no cells are modified our counter will be zero.
26
+ if (rows.length && modifiedCells !== 0) {
27
+ const newTable = table.type.createChecked(table.attrs, rows, table.marks);
28
+ return tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
29
+ }
30
+ return tr;
31
+ };
32
+
33
+ /**
34
+ * Position-preserving alternative to `replaceCells`.
35
+ *
36
+ * Uses `setNodeMarkup` per cell instead of rebuilding the whole table with
37
+ * `replaceWith`, so document positions inside cells are never invalidated.
38
+ * This preserves any existing selection through `tr.mapping`.
39
+ */
40
+ export const updateCellsMarkup = (tr, table, tablePos, modifyCell) => {
41
+ let rowOffset = tablePos + 1;
42
+ for (let rowIndex = 0; rowIndex < table.childCount; rowIndex++) {
43
+ const row = table.child(rowIndex);
44
+ let cellOffset = rowOffset + 1;
45
+ for (let colIndex = 0; colIndex < row.childCount; colIndex++) {
46
+ const cell = row.child(colIndex);
47
+ const modified = modifyCell(cell, rowIndex, colIndex);
48
+ if (!modified.sameMarkup(cell)) {
49
+ tr.setNodeMarkup(cellOffset, modified.type, modified.attrs, modified.marks);
50
+ }
51
+ cellOffset += cell.nodeSize;
52
+ }
53
+ rowOffset += row.nodeSize;
54
+ }
55
+ return tr;
56
+ };
@@ -0,0 +1,148 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
3
+ import { findTable } from '@atlaskit/editor-tables/utils';
4
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
5
+ import { hasTableColumnBeenResized } from '../table-resizing/utils/colgroup';
6
+ import { applyTableMeasurement, getTableMeasurement } from '../transforms/content-mode';
7
+ import { ALIGN_START } from './alignment';
8
+ export const isTableInContentMode = ({
9
+ allowColumnResizing,
10
+ allowTableResizing,
11
+ isFullPageEditor,
12
+ isTableNested,
13
+ node
14
+ }) => {
15
+ if (!expValEqualsNoExposure('platform_editor_table_fit_to_content_auto_convert', 'isEnabled', true)) {
16
+ return false;
17
+ }
18
+ if (!node || isTableNested) {
19
+ return false;
20
+ }
21
+ return isContentModeSupported({
22
+ allowColumnResizing,
23
+ allowTableResizing,
24
+ isFullPageEditor
25
+ }) && !hasTableBeenResized(node) && node.attrs.layout === ALIGN_START;
26
+ };
27
+ export const isContentModeSupported = ({
28
+ allowColumnResizing,
29
+ allowTableResizing,
30
+ isFullPageEditor
31
+ }) => {
32
+ return allowColumnResizing && allowTableResizing && isFullPageEditor;
33
+ };
34
+ export const hasTableBeenResized = node => node.attrs.width !== null || hasTableColumnBeenResized(node);
35
+
36
+ /**
37
+ * Iterates all top-level tables in the document, and for those in content mode,
38
+ * measures rendered column widths and sets colwidth + table width attributes
39
+ * in a single batched transaction.
40
+ */
41
+ export const applyMeasuredWidthToAllTables = (view, pluginInjectionApi) => {
42
+ const {
43
+ state: {
44
+ doc,
45
+ schema
46
+ }
47
+ } = view;
48
+ let tr = view.state.tr;
49
+ const {
50
+ table
51
+ } = schema.nodes;
52
+ let modified = false;
53
+ const measuredTables = [];
54
+
55
+ // modify only top-level tables
56
+ doc.forEach((node, offset) => {
57
+ if (node.type !== table || hasTableBeenResized(node) && node.attrs.layout !== ALIGN_START) {
58
+ return;
59
+ }
60
+ const domNode = view.domAtPos(offset + 1).node;
61
+ const tableWrapper = domNode instanceof HTMLElement ? domNode.closest(`.${TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP}`) : null;
62
+ const tableRef = tableWrapper === null || tableWrapper === void 0 ? void 0 : tableWrapper.querySelector('table');
63
+ if (!tableRef) {
64
+ return;
65
+ }
66
+ measuredTables.push({
67
+ node,
68
+ offset,
69
+ measurement: getTableMeasurement(tableRef)
70
+ });
71
+ });
72
+ measuredTables.forEach(({
73
+ node,
74
+ offset,
75
+ measurement
76
+ }) => {
77
+ tr = applyTableMeasurement(tr, node, measurement, offset);
78
+ modified = true;
79
+ });
80
+ if (modified) {
81
+ var _pluginInjectionApi$a, _pluginInjectionApi$a2, _pluginInjectionApi$w, _pluginInjectionApi$w2, _pluginInjectionApi$w3;
82
+ pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : (_pluginInjectionApi$a2 = _pluginInjectionApi$a.actions) === null || _pluginInjectionApi$a2 === void 0 ? void 0 : _pluginInjectionApi$a2.attachAnalyticsEvent({
83
+ action: TABLE_ACTION.FIT_TO_CONTENT_AUTO_CONVERTED,
84
+ actionSubject: ACTION_SUBJECT.TABLE,
85
+ actionSubjectId: null,
86
+ eventType: EVENT_TYPE.TRACK,
87
+ attributes: {
88
+ editorContainerWidth: (_pluginInjectionApi$w = pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$w2 = pluginInjectionApi.width) === null || _pluginInjectionApi$w2 === void 0 ? void 0 : (_pluginInjectionApi$w3 = _pluginInjectionApi$w2.sharedState.currentState()) === null || _pluginInjectionApi$w3 === void 0 ? void 0 : _pluginInjectionApi$w3.width) !== null && _pluginInjectionApi$w !== void 0 ? _pluginInjectionApi$w : 0,
89
+ totalTablesResized: measuredTables.length,
90
+ measurements: measuredTables.map(({
91
+ measurement
92
+ }) => ({
93
+ tableWidth: measurement.tableWidth,
94
+ totalColumnCount: measurement.colWidths.length
95
+ }))
96
+ }
97
+ })(tr);
98
+ view.dispatch(tr.setMeta('addToHistory', false));
99
+ }
100
+ };
101
+ export const applyMeasuredWidthToSelectedTable = (view, api) => {
102
+ var _api$analytics, _api$analytics$action, _api$width$sharedStat, _api$width, _api$width$sharedStat2;
103
+ const tableObject = findTable(view.state.selection);
104
+ if (!tableObject) {
105
+ return;
106
+ }
107
+ const {
108
+ node,
109
+ pos
110
+ } = tableObject;
111
+ const tableState = api === null || api === void 0 ? void 0 : api.table.sharedState.currentState();
112
+ if (!(tableState !== null && tableState !== void 0 && tableState.tableRef)) {
113
+ return;
114
+ }
115
+ const tableRef = tableState.tableRef;
116
+
117
+ // Instead of dispatching a transaction to "strip widths" and then waiting
118
+ // for a rAF to measure natural column widths, instea directly update the DOM elements and
119
+ // take a measurement.
120
+ const cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
121
+ const contentWrap = tableRef.closest(`.${TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP}`);
122
+ const resizerContainer = contentWrap === null || contentWrap === void 0 ? void 0 : contentWrap.querySelector(`.${TableSharedCssClassName.TABLE_RESIZER_CONTAINER}`);
123
+ const resizerItem = resizerContainer === null || resizerContainer === void 0 ? void 0 : resizerContainer.querySelector('.resizer-item.display-handle');
124
+ tableRef.style.width = '';
125
+ tableRef.style.tableLayout = 'auto';
126
+ cols.forEach(col => col.style.width = '');
127
+ if (resizerContainer) {
128
+ resizerContainer.style.width = 'max-content';
129
+ resizerContainer.style.setProperty('--ak-editor-table-width', 'max-content');
130
+ }
131
+ if (resizerItem) {
132
+ resizerItem.style.width = 'max-content';
133
+ }
134
+ const measurement = getTableMeasurement(tableRef);
135
+ const tr = applyTableMeasurement(view.state.tr, node, measurement, pos);
136
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.attachAnalyticsEvent({
137
+ action: TABLE_ACTION.FIT_TO_CONTENT_ON_DEMAND,
138
+ actionSubject: ACTION_SUBJECT.TABLE,
139
+ actionSubjectId: null,
140
+ eventType: EVENT_TYPE.TRACK,
141
+ attributes: {
142
+ editorContainerWidth: (_api$width$sharedStat = api === null || api === void 0 ? void 0 : (_api$width = api.width) === null || _api$width === void 0 ? void 0 : (_api$width$sharedStat2 = _api$width.sharedState.currentState()) === null || _api$width$sharedStat2 === void 0 ? void 0 : _api$width$sharedStat2.width) !== null && _api$width$sharedStat !== void 0 ? _api$width$sharedStat : 0,
143
+ tableWidth: measurement.tableWidth,
144
+ totalColumnCount: measurement.colWidths.length
145
+ }
146
+ })(tr);
147
+ view.dispatch(tr);
148
+ };
@@ -1,7 +1,8 @@
1
1
  import rafSchedule from 'raf-schd';
2
2
  import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
3
+ import { getBrowserInfo } from '@atlaskit/editor-common/browser';
3
4
  import { getParentOfTypeCount } from '@atlaskit/editor-common/nesting';
4
- import { browser, closestElement, isElementInTableCell, isLastItemMediaGroup, setNodeSelection } from '@atlaskit/editor-common/utils';
5
+ import { closestElement, isElementInTableCell, isLastItemMediaGroup, setNodeSelection } from '@atlaskit/editor-common/utils';
5
6
  import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
7
  import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
7
8
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
@@ -30,7 +31,7 @@ export const handleBlur = (view, event) => {
30
31
  } = view;
31
32
  // IE version check for ED-4665
32
33
  // Calendar focus check for ED-10466
33
- if (browser.ie_version !== 11 && !isFocusingCalendar(event) && !isFocusingModal(event) && !isFocusingFloatingToolbar(event) && !isFocusingDragHandles(event) && !isFocusingDragHandlesClickableZone(event)) {
34
+ if (getBrowserInfo().ie_version !== 11 && !isFocusingCalendar(event) && !isFocusingModal(event) && !isFocusingFloatingToolbar(event) && !isFocusingDragHandles(event) && !isFocusingDragHandlesClickableZone(event)) {
34
35
  setEditorFocus(false)(state, dispatch);
35
36
  }
36
37
  event.preventDefault();
@@ -361,7 +362,7 @@ export const handleMouseMove = nodeViewPortalProviderAPI => (view, event) => {
361
362
  // a reflow. So for now this will just grab the offsetX value immediately for gecko and chrome will calculate later
362
363
  // in the deferred callback handler.
363
364
  // Bug Tracking: https://bugzilla.mozilla.org/show_bug.cgi?id=1882903
364
- handleMouseMoveDebounce(nodeViewPortalProviderAPI)(view, event, browser.gecko ? event.offsetX : NaN);
365
+ handleMouseMoveDebounce(nodeViewPortalProviderAPI)(view, event, getBrowserInfo().gecko ? event.offsetX : NaN);
365
366
  return false;
366
367
  };
367
368
  export function handleTripleClick(view, pos) {