@atlaskit/editor-plugin-table 22.4.14 → 22.4.15

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 (69) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/nodeviews/TableComponent.js +2 -2
  3. package/dist/cjs/nodeviews/table.js +2 -2
  4. package/dist/cjs/nodeviews/toDOM.js +2 -2
  5. package/dist/cjs/pm-plugins/main.js +4 -3
  6. package/dist/cjs/pm-plugins/table-width.js +2 -2
  7. package/dist/cjs/pm-plugins/transforms/content-mode.js +3 -2
  8. package/dist/cjs/pm-plugins/utils/tableMode/apply-measured-width-to-all-tables.js +70 -0
  9. package/dist/cjs/pm-plugins/utils/tableMode/apply-measured-width-to-selected-table.js +41 -0
  10. package/dist/cjs/pm-plugins/utils/tableMode/is-content-mode-supported.js +12 -0
  11. package/dist/cjs/pm-plugins/utils/tableMode/measure-table-with-auto-layout.js +113 -0
  12. package/dist/cjs/pm-plugins/utils/tableMode/smart-adjust/constants.js +10 -0
  13. package/dist/cjs/pm-plugins/utils/tableMode/smart-adjust/distribute-column-widths.js +83 -0
  14. package/dist/cjs/pm-plugins/utils/tableMode/smart-adjust/run-smart-adjust.js +56 -0
  15. package/dist/cjs/ui/toolbar.js +4 -3
  16. package/dist/es2019/nodeviews/TableComponent.js +1 -1
  17. package/dist/es2019/nodeviews/table.js +1 -1
  18. package/dist/es2019/nodeviews/toDOM.js +1 -1
  19. package/dist/es2019/pm-plugins/main.js +2 -1
  20. package/dist/es2019/pm-plugins/table-width.js +1 -1
  21. package/dist/es2019/pm-plugins/transforms/content-mode.js +2 -1
  22. package/dist/es2019/pm-plugins/utils/tableMode/apply-measured-width-to-all-tables.js +70 -0
  23. package/dist/es2019/pm-plugins/utils/tableMode/apply-measured-width-to-selected-table.js +38 -0
  24. package/dist/es2019/pm-plugins/utils/tableMode/is-content-mode-supported.js +7 -0
  25. package/dist/es2019/pm-plugins/utils/tableMode/measure-table-with-auto-layout.js +97 -0
  26. package/dist/es2019/pm-plugins/utils/tableMode/smart-adjust/constants.js +4 -0
  27. package/dist/es2019/pm-plugins/utils/tableMode/smart-adjust/distribute-column-widths.js +63 -0
  28. package/dist/es2019/pm-plugins/utils/tableMode/smart-adjust/run-smart-adjust.js +47 -0
  29. package/dist/es2019/ui/toolbar.js +2 -1
  30. package/dist/esm/nodeviews/TableComponent.js +1 -1
  31. package/dist/esm/nodeviews/table.js +1 -1
  32. package/dist/esm/nodeviews/toDOM.js +1 -1
  33. package/dist/esm/pm-plugins/main.js +2 -1
  34. package/dist/esm/pm-plugins/table-width.js +1 -1
  35. package/dist/esm/pm-plugins/transforms/content-mode.js +2 -1
  36. package/dist/esm/pm-plugins/utils/tableMode/apply-measured-width-to-all-tables.js +65 -0
  37. package/dist/esm/pm-plugins/utils/tableMode/apply-measured-width-to-selected-table.js +36 -0
  38. package/dist/esm/pm-plugins/utils/tableMode/is-content-mode-supported.js +6 -0
  39. package/dist/esm/pm-plugins/utils/tableMode/measure-table-with-auto-layout.js +107 -0
  40. package/dist/esm/pm-plugins/utils/tableMode/smart-adjust/constants.js +4 -0
  41. package/dist/esm/pm-plugins/utils/tableMode/smart-adjust/distribute-column-widths.js +77 -0
  42. package/dist/esm/pm-plugins/utils/tableMode/smart-adjust/run-smart-adjust.js +49 -0
  43. package/dist/esm/ui/toolbar.js +2 -1
  44. package/dist/types/pm-plugins/transforms/content-mode.d.ts +1 -0
  45. package/dist/types/pm-plugins/utils/tableMode/apply-measured-width-to-all-tables.d.ts +8 -0
  46. package/dist/types/pm-plugins/utils/tableMode/apply-measured-width-to-selected-table.d.ts +6 -0
  47. package/dist/types/pm-plugins/utils/tableMode/is-content-mode-supported.d.ts +7 -0
  48. package/dist/types/pm-plugins/utils/tableMode/measure-table-with-auto-layout.d.ts +2 -0
  49. package/dist/types/pm-plugins/utils/tableMode/smart-adjust/constants.d.ts +4 -0
  50. package/dist/types/pm-plugins/utils/tableMode/smart-adjust/distribute-column-widths.d.ts +8 -0
  51. package/dist/types/pm-plugins/utils/tableMode/smart-adjust/run-smart-adjust.d.ts +7 -0
  52. package/dist/types/ui/TableMenu/column/getColumnMenuComponents.d.ts +1 -1
  53. package/dist/types/ui/TableMenu/column/items/DistributeColumnsItem.d.ts +1 -1
  54. package/dist/types-ts4.5/pm-plugins/transforms/content-mode.d.ts +1 -0
  55. package/dist/types-ts4.5/pm-plugins/utils/tableMode/apply-measured-width-to-all-tables.d.ts +8 -0
  56. package/dist/types-ts4.5/pm-plugins/utils/tableMode/apply-measured-width-to-selected-table.d.ts +6 -0
  57. package/dist/types-ts4.5/pm-plugins/utils/tableMode/is-content-mode-supported.d.ts +7 -0
  58. package/dist/types-ts4.5/pm-plugins/utils/tableMode/measure-table-with-auto-layout.d.ts +2 -0
  59. package/dist/types-ts4.5/pm-plugins/utils/tableMode/smart-adjust/constants.d.ts +4 -0
  60. package/dist/types-ts4.5/pm-plugins/utils/tableMode/smart-adjust/distribute-column-widths.d.ts +8 -0
  61. package/dist/types-ts4.5/pm-plugins/utils/tableMode/smart-adjust/run-smart-adjust.d.ts +7 -0
  62. package/dist/types-ts4.5/ui/TableMenu/column/getColumnMenuComponents.d.ts +1 -1
  63. package/dist/types-ts4.5/ui/TableMenu/column/items/DistributeColumnsItem.d.ts +1 -1
  64. package/package.json +10 -7
  65. package/dist/cjs/pm-plugins/utils/tableMode.js +0 -162
  66. package/dist/es2019/pm-plugins/utils/tableMode.js +0 -158
  67. package/dist/esm/pm-plugins/utils/tableMode.js +0 -156
  68. package/dist/types/pm-plugins/utils/tableMode.d.ts +0 -26
  69. package/dist/types-ts4.5/pm-plugins/utils/tableMode.d.ts +0 -26
@@ -0,0 +1,70 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
3
+ import { hasTableBeenResized } from '@atlaskit/editor-common/table';
4
+ import { applyTableMeasurement, getTableMeasurement } from '../../transforms/content-mode';
5
+
6
+ /**
7
+ * Iterates all top-level tables in the document, and for those in content mode,
8
+ * measures rendered column widths and sets colwidth + table width attributes
9
+ * in a single batched transaction.
10
+ */
11
+ export const applyMeasuredWidthToAllTables = (view, pluginInjectionApi) => {
12
+ const {
13
+ state: {
14
+ doc,
15
+ schema
16
+ }
17
+ } = view;
18
+ let tr = view.state.tr;
19
+ const {
20
+ table
21
+ } = schema.nodes;
22
+ let modified = false;
23
+ const measuredTables = [];
24
+
25
+ // modify only top-level tables
26
+ doc.forEach((node, offset) => {
27
+ if (node.type !== table || hasTableBeenResized(node) && node.attrs.layout !== 'align-start') {
28
+ return;
29
+ }
30
+ const domNode = view.domAtPos(offset + 1).node;
31
+ const tableWrapper = domNode instanceof HTMLElement ? domNode.closest(`.${TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP}`) : null;
32
+ const tableRef = tableWrapper === null || tableWrapper === void 0 ? void 0 : tableWrapper.querySelector('table');
33
+ if (!tableRef) {
34
+ return;
35
+ }
36
+ measuredTables.push({
37
+ node,
38
+ offset,
39
+ measurement: getTableMeasurement(tableRef)
40
+ });
41
+ });
42
+ measuredTables.forEach(({
43
+ node,
44
+ offset,
45
+ measurement
46
+ }) => {
47
+ tr = applyTableMeasurement(tr, node, measurement, offset);
48
+ modified = true;
49
+ });
50
+ if (modified) {
51
+ var _pluginInjectionApi$a, _pluginInjectionApi$a2, _pluginInjectionApi$w, _pluginInjectionApi$w2, _pluginInjectionApi$w3;
52
+ 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({
53
+ action: TABLE_ACTION.FIT_TO_CONTENT_AUTO_CONVERTED,
54
+ actionSubject: ACTION_SUBJECT.TABLE,
55
+ actionSubjectId: null,
56
+ eventType: EVENT_TYPE.TRACK,
57
+ attributes: {
58
+ 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,
59
+ totalTablesResized: measuredTables.length,
60
+ measurements: measuredTables.map(({
61
+ measurement
62
+ }) => ({
63
+ tableWidth: measurement.tableWidth,
64
+ totalColumnCount: measurement.colWidths.length
65
+ }))
66
+ }
67
+ })(tr);
68
+ view.dispatch(tr.setMeta('addToHistory', false));
69
+ }
70
+ };
@@ -0,0 +1,38 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { findTable } from '@atlaskit/editor-tables/utils';
3
+ import { applyTableMeasurement } from '../../transforms/content-mode';
4
+ import { measureTableWithAutoLayout } from './measure-table-with-auto-layout';
5
+
6
+ /**
7
+ * Used to measure a selected table width with it's content being laid out natively by the browser
8
+ */
9
+ export const applyMeasuredWidthToSelectedTable = (view, api) => {
10
+ var _api$width, _api$width$sharedStat, _api$analytics, _api$analytics$action, _api$width$sharedStat2, _api$width2, _api$width2$sharedSta;
11
+ const tableObject = findTable(view.state.selection);
12
+ if (!tableObject) {
13
+ return;
14
+ }
15
+ const {
16
+ node,
17
+ pos
18
+ } = tableObject;
19
+ const tableState = api === null || api === void 0 ? void 0 : api.table.sharedState.currentState();
20
+ if (!(tableState !== null && tableState !== void 0 && tableState.tableRef)) {
21
+ return;
22
+ }
23
+ const editorContainerWidth = api === null || api === void 0 ? void 0 : (_api$width = api.width) === null || _api$width === void 0 ? void 0 : (_api$width$sharedStat = _api$width.sharedState.currentState()) === null || _api$width$sharedStat === void 0 ? void 0 : _api$width$sharedStat.width;
24
+ const measurement = measureTableWithAutoLayout(tableState.tableRef, editorContainerWidth);
25
+ const tr = applyTableMeasurement(view.state.tr, node, measurement, pos);
26
+ 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({
27
+ action: TABLE_ACTION.FIT_TO_CONTENT_ON_DEMAND,
28
+ actionSubject: ACTION_SUBJECT.TABLE,
29
+ actionSubjectId: null,
30
+ eventType: EVENT_TYPE.TRACK,
31
+ attributes: {
32
+ editorContainerWidth: (_api$width$sharedStat2 = api === null || api === void 0 ? void 0 : (_api$width2 = api.width) === null || _api$width2 === void 0 ? void 0 : (_api$width2$sharedSta = _api$width2.sharedState.currentState()) === null || _api$width2$sharedSta === void 0 ? void 0 : _api$width2$sharedSta.width) !== null && _api$width$sharedStat2 !== void 0 ? _api$width$sharedStat2 : 0,
33
+ tableWidth: measurement.tableWidth,
34
+ totalColumnCount: measurement.colWidths.length
35
+ }
36
+ })(tr);
37
+ view.dispatch(tr);
38
+ };
@@ -0,0 +1,7 @@
1
+ export const isContentModeSupported = ({
2
+ allowColumnResizing,
3
+ allowTableResizing,
4
+ isFullPageEditor
5
+ }) => {
6
+ return allowColumnResizing && allowTableResizing && isFullPageEditor;
7
+ };
@@ -0,0 +1,97 @@
1
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import { getTableMeasurement } from '../../transforms/content-mode';
4
+ import { restoreResizerContainer, runSmartAdjust } from './smart-adjust/run-smart-adjust';
5
+ export const measureTableWithAutoLayout = (tableRef, editorContainerWidth) => {
6
+ const cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
7
+ const contentWrap = tableRef.closest(`.${TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP}`);
8
+ const resizerContainer = contentWrap === null || contentWrap === void 0 ? void 0 : contentWrap.querySelector(`.${TableSharedCssClassName.TABLE_RESIZER_CONTAINER}`);
9
+ const resizerItem = resizerContainer === null || resizerContainer === void 0 ? void 0 : resizerContainer.querySelector('.resizer-item.display-handle');
10
+ const prevTableWidth = tableRef.style.width;
11
+ const prevTableLayout = tableRef.style.tableLayout;
12
+ const prevColWidths = cols.map(col => col.style.width);
13
+ const prevResizerItemWidth = resizerItem === null || resizerItem === void 0 ? void 0 : resizerItem.style.width;
14
+ tableRef.style.width = '';
15
+ tableRef.style.tableLayout = 'auto';
16
+ cols.forEach(col => col.style.width = '');
17
+ if (fg('platform_editor_table_fit_to_content_smart_adjust')) {
18
+ const hadTableSticky = tableRef.classList.contains(TableSharedCssClassName.TABLE_STICKY);
19
+ const prevTableMarginTop = tableRef.style.marginTop;
20
+ if (hadTableSticky) {
21
+ tableRef.classList.remove(TableSharedCssClassName.TABLE_NATIVE_STICKY);
22
+ }
23
+ if (prevTableMarginTop) {
24
+ tableRef.style.marginTop = '';
25
+ }
26
+ const stickyRows = Array.from(tableRef.querySelectorAll(`tr.sticky, tr.${TableSharedCssClassName.TABLE_NATIVE_STICKY}`));
27
+ const prevStickyRowState = stickyRows.map(row => ({
28
+ row,
29
+ hadSticky: row.classList.contains('sticky'),
30
+ hadNative: row.classList.contains(TableSharedCssClassName.TABLE_NATIVE_STICKY),
31
+ width: row.style.width,
32
+ top: row.style.top,
33
+ position: row.style.position,
34
+ gridTemplateColumns: row.style.gridTemplateColumns
35
+ }));
36
+ stickyRows.forEach(row => {
37
+ row.classList.remove('sticky');
38
+ row.classList.remove(TableSharedCssClassName.TABLE_NATIVE_STICKY);
39
+ row.style.width = '';
40
+ row.style.top = '';
41
+ row.style.position = '';
42
+ row.style.gridTemplateColumns = '';
43
+ });
44
+ try {
45
+ return runSmartAdjust(tableRef, resizerContainer, resizerItem, editorContainerWidth);
46
+ } finally {
47
+ tableRef.style.width = prevTableWidth;
48
+ tableRef.style.tableLayout = prevTableLayout;
49
+ cols.forEach((col, i) => col.style.width = prevColWidths[i]);
50
+ if (hadTableSticky) {
51
+ tableRef.classList.add(TableSharedCssClassName.TABLE_STICKY);
52
+ }
53
+ if (prevTableMarginTop) {
54
+ tableRef.style.marginTop = prevTableMarginTop;
55
+ }
56
+ prevStickyRowState.forEach(state => {
57
+ if (state.hadSticky) {
58
+ state.row.classList.add('sticky');
59
+ }
60
+ if (state.hadNative) {
61
+ state.row.classList.add(TableSharedCssClassName.TABLE_NATIVE_STICKY);
62
+ }
63
+ if (state.width) {
64
+ state.row.style.width = state.width;
65
+ }
66
+ if (state.top) {
67
+ state.row.style.top = state.top;
68
+ }
69
+ if (state.position) {
70
+ state.row.style.position = state.position;
71
+ }
72
+ if (state.gridTemplateColumns) {
73
+ state.row.style.gridTemplateColumns = state.gridTemplateColumns;
74
+ }
75
+ });
76
+ restoreResizerContainer(resizerContainer);
77
+ if (resizerItem) {
78
+ resizerItem.style.width = prevResizerItemWidth !== null && prevResizerItemWidth !== void 0 ? prevResizerItemWidth : '';
79
+ }
80
+ }
81
+ }
82
+ if (resizerContainer) {
83
+ resizerContainer.style.width = 'var(--ak-editor-table-width)';
84
+ resizerContainer.style.setProperty('--ak-editor-table-width', 'max-content');
85
+ }
86
+ if (resizerItem) {
87
+ resizerItem.style.width = 'max-content';
88
+ }
89
+ const measurement = getTableMeasurement(tableRef);
90
+ tableRef.style.width = prevTableWidth;
91
+ tableRef.style.tableLayout = prevTableLayout;
92
+ cols.forEach((col, i) => col.style.width = prevColWidths[i]);
93
+ if (resizerItem) {
94
+ resizerItem.style.width = prevResizerItemWidth !== null && prevResizerItemWidth !== void 0 ? prevResizerItemWidth : '';
95
+ }
96
+ return measurement;
97
+ };
@@ -0,0 +1,4 @@
1
+ /** Each column's max width is `MAX × (usableWidth / numCols)`. */
2
+ export const EVEN_SHARE_RATIO = {
3
+ MAX: 2
4
+ };
@@ -0,0 +1,63 @@
1
+ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
2
+ import { akEditorGutterPaddingDynamic } from '@atlaskit/editor-shared-styles';
3
+ import { EVEN_SHARE_RATIO } from './constants';
4
+ export const sumWidths = widths => widths.reduce((sum, width) => sum + width, 0);
5
+
6
+ // 2px absorbs sub-pixel rounding in `getRenderedColgroupColumnWidths`.
7
+ const SUB_PIXEL_ROUNDING_ALLOWANCE = 2;
8
+
9
+ /**
10
+ * Clamps each desired width to `[tableCellMinWidth, MAX × evenShare]`. Greedy
11
+ * columns (paragraphs) hit the ceiling and wrap; small columns stay at their
12
+ * natural width. Leftover canvas budget grows ceiling-hitters up to their
13
+ * desired; overflow reclaims from ceiling-hitters only.
14
+ */
15
+ export const distributeByEvenShareRatio = (desiredWidths, editorContainerWidth) => {
16
+ if (desiredWidths.length === 0 || !isFinite(editorContainerWidth) || editorContainerWidth <= 0) {
17
+ return desiredWidths;
18
+ }
19
+ const usableWidth = Math.max(editorContainerWidth - akEditorGutterPaddingDynamic() * 2, tableCellMinWidth * desiredWidths.length);
20
+ const evenShare = usableWidth / desiredWidths.length;
21
+ const ceiling = EVEN_SHARE_RATIO.MAX * evenShare;
22
+ const isCompactColumn = width => width <= ceiling;
23
+ const desiredCeil = desiredWidths.map(desired => Math.max(tableCellMinWidth, Math.ceil(desired) + SUB_PIXEL_ROUNDING_ALLOWANCE));
24
+ const capped = desiredCeil.map(desired => isCompactColumn(desired) ? desired : Math.min(ceiling, desired));
25
+ const sum = sumWidths(capped);
26
+
27
+ // Underflow: grow non-protected ceiling-hitters into the leftover, up to their desired.
28
+ if (sum < usableWidth) {
29
+ const leftover = usableWidth - sum;
30
+ const growthHeadroom = capped.map((width, index) => !isCompactColumn(desiredCeil[index]) && width >= ceiling ? Math.max(desiredCeil[index] - width, 0) : 0);
31
+ const totalHeadroom = sumWidths(growthHeadroom);
32
+ if (totalHeadroom > 0) {
33
+ const totalGrowth = Math.min(leftover, totalHeadroom);
34
+ return capped.map((width, index) => {
35
+ const headroom = growthHeadroom[index];
36
+ if (headroom <= 0) {
37
+ return width;
38
+ }
39
+ return width + headroom / totalHeadroom * totalGrowth;
40
+ });
41
+ }
42
+ return capped;
43
+ }
44
+ if (sum === usableWidth) {
45
+ return capped;
46
+ }
47
+
48
+ // Overflow: reclaim from non-protected ceiling-hitters only.
49
+ const overage = sum - usableWidth;
50
+ const slacks = capped.map((width, index) => !isCompactColumn(desiredCeil[index]) && width >= ceiling ? Math.max(width - tableCellMinWidth, 0) : 0);
51
+ const totalSlack = sumWidths(slacks);
52
+ if (totalSlack <= 0) {
53
+ return capped;
54
+ }
55
+ return capped.map((width, index) => {
56
+ const slack = slacks[index];
57
+ if (slack <= 0) {
58
+ return width;
59
+ }
60
+ const share = slack / totalSlack * Math.min(overage, totalSlack);
61
+ return Math.max(width - share, tableCellMinWidth);
62
+ });
63
+ };
@@ -0,0 +1,47 @@
1
+ import { getTableMeasurement } from '../../../transforms/content-mode';
2
+ import { distributeByEvenShareRatio, sumWidths } from './distribute-column-widths';
3
+ const measureWithIntrinsicWidth = (tableRef, resizerContainer, resizerItem) => {
4
+ if (resizerContainer) {
5
+ resizerContainer.style.width = 'var(--ak-editor-table-width)';
6
+ resizerContainer.style.setProperty('--ak-editor-table-width', 'max-content');
7
+ }
8
+ if (resizerItem) {
9
+ resizerItem.style.width = 'max-content';
10
+ }
11
+ const prevTableWidth = tableRef.style.width;
12
+ const prevTableMaxWidth = tableRef.style.maxWidth;
13
+ const prevTableMinWidth = tableRef.style.minWidth;
14
+ tableRef.style.setProperty('width', 'max-content', 'important');
15
+ tableRef.style.setProperty('max-width', 'none', 'important');
16
+ tableRef.style.setProperty('min-width', '0', 'important');
17
+ try {
18
+ return getTableMeasurement(tableRef);
19
+ } finally {
20
+ tableRef.style.width = prevTableWidth;
21
+ tableRef.style.maxWidth = prevTableMaxWidth;
22
+ tableRef.style.minWidth = prevTableMinWidth;
23
+ }
24
+ };
25
+ export const restoreResizerContainer = resizerContainer => {
26
+ if (!resizerContainer) {
27
+ return;
28
+ }
29
+ resizerContainer.style.width = 'var(--ak-editor-table-width)';
30
+ resizerContainer.style.removeProperty('--ak-editor-table-width');
31
+ };
32
+
33
+ /**
34
+ * Smart-adjust: measure unconstrained max-content per column, then clamp via
35
+ * `distributeByEvenShareRatio`.
36
+ */
37
+ export const runSmartAdjust = (tableRef, resizerContainer, resizerItem, editorContainerWidthFromApi) => {
38
+ const preferredMeasurement = measureWithIntrinsicWidth(tableRef, resizerContainer, resizerItem);
39
+ const desiredWidths = preferredMeasurement.colWidths;
40
+ const editorContainerWidth = editorContainerWidthFromApi !== null && editorContainerWidthFromApi !== void 0 ? editorContainerWidthFromApi : sumWidths(desiredWidths);
41
+ const colWidths = distributeByEvenShareRatio(desiredWidths, editorContainerWidth);
42
+ return {
43
+ ...preferredMeasurement,
44
+ colWidths,
45
+ tableWidth: sumWidths(colWidths)
46
+ };
47
+ };
@@ -44,7 +44,8 @@ import { normaliseAlignment } from '../pm-plugins/utils/alignment';
44
44
  import { isTableNested } from '../pm-plugins/utils/nodes';
45
45
  import { getSelectedColumnIndexes, getSelectedRowIndexes } from '../pm-plugins/utils/selection';
46
46
  import { getMergedCellsPositions } from '../pm-plugins/utils/table';
47
- import { applyMeasuredWidthToSelectedTable, isContentModeSupported } from '../pm-plugins/utils/tableMode';
47
+ import { applyMeasuredWidthToSelectedTable } from '../pm-plugins/utils/tableMode/apply-measured-width-to-selected-table';
48
+ import { isContentModeSupported } from '../pm-plugins/utils/tableMode/is-content-mode-supported';
48
49
  import { TableCssClassName } from '../types';
49
50
  import { FloatingAlignmentButtons } from './FloatingAlignmentButtons/FloatingAlignmentButtons';
50
51
  export const getToolbarMenuConfig = (config, state, {
@@ -41,7 +41,7 @@ import { getResizeState, updateColgroup } from '../pm-plugins/table-resizing/uti
41
41
  import { scaleTable } from '../pm-plugins/table-resizing/utils/scale-table';
42
42
  import { containsHeaderRow, isTableNested, isTableNestedInMoreThanOneNode, isTableNestedUnderBodiedSyncBlock, tablesHaveDifferentColumnWidths, tablesHaveDifferentNoOfColumns, tablesHaveDifferentNoOfRows } from '../pm-plugins/utils/nodes';
43
43
  import { getAssistiveMessage } from '../pm-plugins/utils/table';
44
- import { isContentModeSupported } from '../pm-plugins/utils/tableMode';
44
+ import { isContentModeSupported } from '../pm-plugins/utils/tableMode/is-content-mode-supported';
45
45
  import { TableCssClassName as ClassName } from '../types';
46
46
  import { handleMouseOut, handleMouseOver, isTableInFocus, withCellTracking } from '../ui/event-handlers';
47
47
  import TableFloatingColumnControls from '../ui/TableFloatingColumnControls';
@@ -23,7 +23,7 @@ import { pluginConfig as getPluginConfig } from '../pm-plugins/create-plugin-con
23
23
  import { getPluginState } from '../pm-plugins/plugin-factory';
24
24
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
25
25
  import { isTableNested, tablesHaveDifferentColumnWidths } from '../pm-plugins/utils/nodes';
26
- import { isContentModeSupported } from '../pm-plugins/utils/tableMode';
26
+ import { isContentModeSupported } from '../pm-plugins/utils/tableMode/is-content-mode-supported';
27
27
  import { TableComponentWithSharedState } from './TableComponentWithSharedState';
28
28
  import { tableNodeSpecWithFixedToDOM } from './toDOM';
29
29
  var tableAttributes = function tableAttributes(node) {
@@ -12,7 +12,7 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
12
12
  import { generateColgroupFromNode, getResizerMinWidth } from '../pm-plugins/table-resizing/utils/colgroup';
13
13
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from '../pm-plugins/table-resizing/utils/consts';
14
14
  import { getTableResizerContainerMaxWidthInCSS, getTableResizerContainerForFullPageWidthInCSS, getTableResizerItemWidthInCSS } from '../pm-plugins/table-resizing/utils/misc';
15
- import { isContentModeSupported } from '../pm-plugins/utils/tableMode';
15
+ import { isContentModeSupported } from '../pm-plugins/utils/tableMode/is-content-mode-supported';
16
16
  import { getAlignmentStyle } from './table-container-styles';
17
17
  export var tableNodeSpecWithFixedToDOM = function tableNodeSpecWithFixedToDOM(config) {
18
18
  var tableNode = config.isNestingSupported ? tableWithNestedTable : table;
@@ -28,7 +28,8 @@ import { fixTables } from './transforms/fix-tables';
28
28
  import { replaceSelectedTable } from './transforms/replace-table';
29
29
  import { findControlsHoverDecoration } from './utils/decoration';
30
30
  import { transformSliceToCorrectEmptyTableCells, transformSliceToFixHardBreakProblemOnCopyFromCell, transformSliceToRemoveOpenTable, transformSliceToRemoveNestedTables, isHeaderRowRequired, transformSliceTableLayoutDefaultToCenter } from './utils/paste';
31
- import { applyMeasuredWidthToAllTables, isContentModeSupported } from './utils/tableMode';
31
+ import { applyMeasuredWidthToAllTables } from './utils/tableMode/apply-measured-width-to-all-tables';
32
+ import { isContentModeSupported } from './utils/tableMode/is-content-mode-supported';
32
33
  export var createPlugin = function createPlugin(dispatchAnalyticsEvent, dispatch, portalProviderAPI, nodeViewPortalProviderAPI, eventDispatcher, pluginConfig, getEditorContainerWidth, getEditorFeatureFlags, getIntl, fullWidthModeEnabled, previousFullWidthModeEnabled, editorAnalyticsAPI, pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent, isCommentEditor, isChromelessEditor, allowFixedColumnWidthOption) {
33
34
  var _accessibilityUtils;
34
35
  var state = createPluginState(dispatch, _objectSpread(_objectSpread(_objectSpread({
@@ -18,7 +18,7 @@ import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorMaxWi
18
18
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
19
19
  import { TABLE_MAX_WIDTH, TABLE_FULL_WIDTH } from './table-resizing/utils/consts';
20
20
  import { ALIGN_START } from './utils/alignment';
21
- import { isContentModeSupported } from './utils/tableMode';
21
+ import { isContentModeSupported } from './utils/tableMode/is-content-mode-supported';
22
22
  export var pluginKey = new PluginKey('tableWidthPlugin');
23
23
  var createPlugin = function createPlugin(dispatch, dispatchAnalyticsEvent, fullWidthEnabled, maxWidthEnabled, isTableScalingEnabled, isTableAlignmentEnabled, isCommentEditor) {
24
24
  return new SafePlugin({
@@ -5,10 +5,11 @@ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
5
5
  import { akEditorFullWidthLayoutWidth, akEditorMaxLayoutWidth } from '@atlaskit/editor-shared-styles';
6
6
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
7
  import { updateCellsMarkup } from './table-transform-utils';
8
- var tableWidth = function tableWidth(contentWidth) {
8
+ export var clampToEditorMaxWidth = function clampToEditorMaxWidth(contentWidth) {
9
9
  var maxEditorWidth = expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? akEditorMaxLayoutWidth : akEditorFullWidthLayoutWidth;
10
10
  return Math.min(maxEditorWidth, contentWidth);
11
11
  };
12
+ var tableWidth = clampToEditorMaxWidth;
12
13
  export var getTableMeasurement = function getTableMeasurement(tableRef) {
13
14
  var colWidths = getRenderedColgroupColumnWidths(tableRef);
14
15
  var totalContentWidth = colWidths.reduce(function (acc, current) {
@@ -0,0 +1,65 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
3
+ import { hasTableBeenResized } from '@atlaskit/editor-common/table';
4
+ import { applyTableMeasurement, getTableMeasurement } from '../../transforms/content-mode';
5
+
6
+ /**
7
+ * Iterates all top-level tables in the document, and for those in content mode,
8
+ * measures rendered column widths and sets colwidth + table width attributes
9
+ * in a single batched transaction.
10
+ */
11
+ export var applyMeasuredWidthToAllTables = function applyMeasuredWidthToAllTables(view, pluginInjectionApi) {
12
+ var _view$state = view.state,
13
+ doc = _view$state.doc,
14
+ schema = _view$state.schema;
15
+ var tr = view.state.tr;
16
+ var table = schema.nodes.table;
17
+ var modified = false;
18
+ var measuredTables = [];
19
+
20
+ // modify only top-level tables
21
+ doc.forEach(function (node, offset) {
22
+ if (node.type !== table || hasTableBeenResized(node) && node.attrs.layout !== 'align-start') {
23
+ return;
24
+ }
25
+ var domNode = view.domAtPos(offset + 1).node;
26
+ var tableWrapper = domNode instanceof HTMLElement ? domNode.closest(".".concat(TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP)) : null;
27
+ var tableRef = tableWrapper === null || tableWrapper === void 0 ? void 0 : tableWrapper.querySelector('table');
28
+ if (!tableRef) {
29
+ return;
30
+ }
31
+ measuredTables.push({
32
+ node: node,
33
+ offset: offset,
34
+ measurement: getTableMeasurement(tableRef)
35
+ });
36
+ });
37
+ measuredTables.forEach(function (_ref) {
38
+ var node = _ref.node,
39
+ offset = _ref.offset,
40
+ measurement = _ref.measurement;
41
+ tr = applyTableMeasurement(tr, node, measurement, offset);
42
+ modified = true;
43
+ });
44
+ if (modified) {
45
+ var _pluginInjectionApi$a, _pluginInjectionApi$w, _pluginInjectionApi$w2;
46
+ pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 || (_pluginInjectionApi$a = _pluginInjectionApi$a.actions) === null || _pluginInjectionApi$a === void 0 || _pluginInjectionApi$a.attachAnalyticsEvent({
47
+ action: TABLE_ACTION.FIT_TO_CONTENT_AUTO_CONVERTED,
48
+ actionSubject: ACTION_SUBJECT.TABLE,
49
+ actionSubjectId: null,
50
+ eventType: EVENT_TYPE.TRACK,
51
+ attributes: {
52
+ editorContainerWidth: (_pluginInjectionApi$w = pluginInjectionApi === null || pluginInjectionApi === void 0 || (_pluginInjectionApi$w2 = pluginInjectionApi.width) === null || _pluginInjectionApi$w2 === void 0 || (_pluginInjectionApi$w2 = _pluginInjectionApi$w2.sharedState.currentState()) === null || _pluginInjectionApi$w2 === void 0 ? void 0 : _pluginInjectionApi$w2.width) !== null && _pluginInjectionApi$w !== void 0 ? _pluginInjectionApi$w : 0,
53
+ totalTablesResized: measuredTables.length,
54
+ measurements: measuredTables.map(function (_ref2) {
55
+ var measurement = _ref2.measurement;
56
+ return {
57
+ tableWidth: measurement.tableWidth,
58
+ totalColumnCount: measurement.colWidths.length
59
+ };
60
+ })
61
+ }
62
+ })(tr);
63
+ view.dispatch(tr.setMeta('addToHistory', false));
64
+ }
65
+ };
@@ -0,0 +1,36 @@
1
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
2
+ import { findTable } from '@atlaskit/editor-tables/utils';
3
+ import { applyTableMeasurement } from '../../transforms/content-mode';
4
+ import { measureTableWithAutoLayout } from './measure-table-with-auto-layout';
5
+
6
+ /**
7
+ * Used to measure a selected table width with it's content being laid out natively by the browser
8
+ */
9
+ export var applyMeasuredWidthToSelectedTable = function applyMeasuredWidthToSelectedTable(view, api) {
10
+ var _api$width, _api$analytics, _api$width$sharedStat, _api$width2;
11
+ var tableObject = findTable(view.state.selection);
12
+ if (!tableObject) {
13
+ return;
14
+ }
15
+ var node = tableObject.node,
16
+ pos = tableObject.pos;
17
+ var tableState = api === null || api === void 0 ? void 0 : api.table.sharedState.currentState();
18
+ if (!(tableState !== null && tableState !== void 0 && tableState.tableRef)) {
19
+ return;
20
+ }
21
+ var editorContainerWidth = api === null || api === void 0 || (_api$width = api.width) === null || _api$width === void 0 || (_api$width = _api$width.sharedState.currentState()) === null || _api$width === void 0 ? void 0 : _api$width.width;
22
+ var measurement = measureTableWithAutoLayout(tableState.tableRef, editorContainerWidth);
23
+ var tr = applyTableMeasurement(view.state.tr, node, measurement, pos);
24
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
25
+ action: TABLE_ACTION.FIT_TO_CONTENT_ON_DEMAND,
26
+ actionSubject: ACTION_SUBJECT.TABLE,
27
+ actionSubjectId: null,
28
+ eventType: EVENT_TYPE.TRACK,
29
+ attributes: {
30
+ editorContainerWidth: (_api$width$sharedStat = api === null || api === void 0 || (_api$width2 = api.width) === null || _api$width2 === void 0 || (_api$width2 = _api$width2.sharedState.currentState()) === null || _api$width2 === void 0 ? void 0 : _api$width2.width) !== null && _api$width$sharedStat !== void 0 ? _api$width$sharedStat : 0,
31
+ tableWidth: measurement.tableWidth,
32
+ totalColumnCount: measurement.colWidths.length
33
+ }
34
+ })(tr);
35
+ view.dispatch(tr);
36
+ };
@@ -0,0 +1,6 @@
1
+ export var isContentModeSupported = function isContentModeSupported(_ref) {
2
+ var allowColumnResizing = _ref.allowColumnResizing,
3
+ allowTableResizing = _ref.allowTableResizing,
4
+ isFullPageEditor = _ref.isFullPageEditor;
5
+ return allowColumnResizing && allowTableResizing && isFullPageEditor;
6
+ };
@@ -0,0 +1,107 @@
1
+ import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import { getTableMeasurement } from '../../transforms/content-mode';
4
+ import { restoreResizerContainer, runSmartAdjust } from './smart-adjust/run-smart-adjust';
5
+ export var measureTableWithAutoLayout = function measureTableWithAutoLayout(tableRef, editorContainerWidth) {
6
+ var cols = Array.from(tableRef.querySelectorAll(':scope > colgroup > col'));
7
+ var contentWrap = tableRef.closest(".".concat(TableSharedCssClassName.TABLE_VIEW_CONTENT_WRAP));
8
+ var resizerContainer = contentWrap === null || contentWrap === void 0 ? void 0 : contentWrap.querySelector(".".concat(TableSharedCssClassName.TABLE_RESIZER_CONTAINER));
9
+ var resizerItem = resizerContainer === null || resizerContainer === void 0 ? void 0 : resizerContainer.querySelector('.resizer-item.display-handle');
10
+ var prevTableWidth = tableRef.style.width;
11
+ var prevTableLayout = tableRef.style.tableLayout;
12
+ var prevColWidths = cols.map(function (col) {
13
+ return col.style.width;
14
+ });
15
+ var prevResizerItemWidth = resizerItem === null || resizerItem === void 0 ? void 0 : resizerItem.style.width;
16
+ tableRef.style.width = '';
17
+ tableRef.style.tableLayout = 'auto';
18
+ cols.forEach(function (col) {
19
+ return col.style.width = '';
20
+ });
21
+ if (fg('platform_editor_table_fit_to_content_smart_adjust')) {
22
+ var hadTableSticky = tableRef.classList.contains(TableSharedCssClassName.TABLE_STICKY);
23
+ var prevTableMarginTop = tableRef.style.marginTop;
24
+ if (hadTableSticky) {
25
+ tableRef.classList.remove(TableSharedCssClassName.TABLE_NATIVE_STICKY);
26
+ }
27
+ if (prevTableMarginTop) {
28
+ tableRef.style.marginTop = '';
29
+ }
30
+ var stickyRows = Array.from(tableRef.querySelectorAll("tr.sticky, tr.".concat(TableSharedCssClassName.TABLE_NATIVE_STICKY)));
31
+ var prevStickyRowState = stickyRows.map(function (row) {
32
+ return {
33
+ row: row,
34
+ hadSticky: row.classList.contains('sticky'),
35
+ hadNative: row.classList.contains(TableSharedCssClassName.TABLE_NATIVE_STICKY),
36
+ width: row.style.width,
37
+ top: row.style.top,
38
+ position: row.style.position,
39
+ gridTemplateColumns: row.style.gridTemplateColumns
40
+ };
41
+ });
42
+ stickyRows.forEach(function (row) {
43
+ row.classList.remove('sticky');
44
+ row.classList.remove(TableSharedCssClassName.TABLE_NATIVE_STICKY);
45
+ row.style.width = '';
46
+ row.style.top = '';
47
+ row.style.position = '';
48
+ row.style.gridTemplateColumns = '';
49
+ });
50
+ try {
51
+ return runSmartAdjust(tableRef, resizerContainer, resizerItem, editorContainerWidth);
52
+ } finally {
53
+ tableRef.style.width = prevTableWidth;
54
+ tableRef.style.tableLayout = prevTableLayout;
55
+ cols.forEach(function (col, i) {
56
+ return col.style.width = prevColWidths[i];
57
+ });
58
+ if (hadTableSticky) {
59
+ tableRef.classList.add(TableSharedCssClassName.TABLE_STICKY);
60
+ }
61
+ if (prevTableMarginTop) {
62
+ tableRef.style.marginTop = prevTableMarginTop;
63
+ }
64
+ prevStickyRowState.forEach(function (state) {
65
+ if (state.hadSticky) {
66
+ state.row.classList.add('sticky');
67
+ }
68
+ if (state.hadNative) {
69
+ state.row.classList.add(TableSharedCssClassName.TABLE_NATIVE_STICKY);
70
+ }
71
+ if (state.width) {
72
+ state.row.style.width = state.width;
73
+ }
74
+ if (state.top) {
75
+ state.row.style.top = state.top;
76
+ }
77
+ if (state.position) {
78
+ state.row.style.position = state.position;
79
+ }
80
+ if (state.gridTemplateColumns) {
81
+ state.row.style.gridTemplateColumns = state.gridTemplateColumns;
82
+ }
83
+ });
84
+ restoreResizerContainer(resizerContainer);
85
+ if (resizerItem) {
86
+ resizerItem.style.width = prevResizerItemWidth !== null && prevResizerItemWidth !== void 0 ? prevResizerItemWidth : '';
87
+ }
88
+ }
89
+ }
90
+ if (resizerContainer) {
91
+ resizerContainer.style.width = 'var(--ak-editor-table-width)';
92
+ resizerContainer.style.setProperty('--ak-editor-table-width', 'max-content');
93
+ }
94
+ if (resizerItem) {
95
+ resizerItem.style.width = 'max-content';
96
+ }
97
+ var measurement = getTableMeasurement(tableRef);
98
+ tableRef.style.width = prevTableWidth;
99
+ tableRef.style.tableLayout = prevTableLayout;
100
+ cols.forEach(function (col, i) {
101
+ return col.style.width = prevColWidths[i];
102
+ });
103
+ if (resizerItem) {
104
+ resizerItem.style.width = prevResizerItemWidth !== null && prevResizerItemWidth !== void 0 ? prevResizerItemWidth : '';
105
+ }
106
+ return measurement;
107
+ };
@@ -0,0 +1,4 @@
1
+ /** Each column's max width is `MAX × (usableWidth / numCols)`. */
2
+ export var EVEN_SHARE_RATIO = {
3
+ MAX: 2
4
+ };