@atlaskit/editor-plugin-table 4.1.1 → 4.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/plugins/table/commands/delete.js +18 -0
  3. package/dist/cjs/plugins/table/commands-with-analytics.js +2 -7
  4. package/dist/cjs/plugins/table/event-handlers.js +2 -2
  5. package/dist/cjs/plugins/table/pm-plugins/main.js +1 -1
  6. package/dist/cjs/plugins/table/transforms/column-width.js +110 -5
  7. package/dist/cjs/plugins/table/transforms/delete-columns.js +16 -6
  8. package/dist/cjs/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +1 -1
  9. package/dist/cjs/plugins/table/ui/FloatingDeleteButton/index.js +1 -1
  10. package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
  11. package/dist/es2019/plugins/table/commands/delete.js +10 -0
  12. package/dist/es2019/plugins/table/commands-with-analytics.js +3 -8
  13. package/dist/es2019/plugins/table/event-handlers.js +2 -2
  14. package/dist/es2019/plugins/table/pm-plugins/main.js +1 -1
  15. package/dist/es2019/plugins/table/transforms/column-width.js +105 -5
  16. package/dist/es2019/plugins/table/transforms/delete-columns.js +16 -5
  17. package/dist/es2019/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +1 -1
  18. package/dist/es2019/plugins/table/ui/FloatingDeleteButton/index.js +1 -1
  19. package/dist/es2019/plugins/table/ui/common-styles.js +0 -1
  20. package/dist/esm/plugins/table/commands/delete.js +12 -0
  21. package/dist/esm/plugins/table/commands-with-analytics.js +3 -8
  22. package/dist/esm/plugins/table/event-handlers.js +2 -2
  23. package/dist/esm/plugins/table/pm-plugins/main.js +1 -1
  24. package/dist/esm/plugins/table/transforms/column-width.js +111 -5
  25. package/dist/esm/plugins/table/transforms/delete-columns.js +16 -6
  26. package/dist/esm/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +1 -1
  27. package/dist/esm/plugins/table/ui/FloatingDeleteButton/index.js +1 -1
  28. package/dist/esm/plugins/table/ui/common-styles.js +1 -1
  29. package/dist/types/plugins/table/commands/delete.d.ts +3 -0
  30. package/dist/types/plugins/table/event-handlers.d.ts +1 -1
  31. package/dist/types/plugins/table/pm-plugins/table-resizing/utils/misc.d.ts +1 -1
  32. package/dist/types/plugins/table/transforms/column-width.d.ts +25 -6
  33. package/dist/types/plugins/table/transforms/delete-columns.d.ts +2 -1
  34. package/dist/types/plugins/table/ui/FloatingDeleteButton/index.d.ts +4 -4
  35. package/dist/types-ts4.5/plugins/table/commands/delete.d.ts +3 -0
  36. package/dist/types-ts4.5/plugins/table/event-handlers.d.ts +1 -1
  37. package/dist/types-ts4.5/plugins/table/pm-plugins/table-resizing/utils/misc.d.ts +1 -1
  38. package/dist/types-ts4.5/plugins/table/transforms/column-width.d.ts +25 -6
  39. package/dist/types-ts4.5/plugins/table/transforms/delete-columns.d.ts +2 -1
  40. package/dist/types-ts4.5/plugins/table/ui/FloatingDeleteButton/index.d.ts +4 -4
  41. package/package.json +4 -1
  42. package/src/__tests__/unit/commands.ts +1 -0
  43. package/src/__tests__/unit/transforms/delete-columns.ts +406 -105
  44. package/src/__tests__/unit/undo-redo.ts +1 -1
  45. package/src/plugins/table/commands/delete.ts +20 -0
  46. package/src/plugins/table/commands-with-analytics.ts +3 -10
  47. package/src/plugins/table/event-handlers.ts +6 -1
  48. package/src/plugins/table/pm-plugins/main.ts +7 -1
  49. package/src/plugins/table/pm-plugins/table-resizing/utils/misc.ts +1 -1
  50. package/src/plugins/table/transforms/column-width.ts +155 -15
  51. package/src/plugins/table/transforms/delete-columns.ts +23 -6
  52. package/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx +1 -1
  53. package/src/plugins/table/ui/FloatingDeleteButton/index.tsx +7 -6
  54. package/src/plugins/table/ui/common-styles.ts +0 -1
@@ -27,6 +27,7 @@ import {
27
27
 
28
28
  import { clearMultipleCells } from './commands/clear';
29
29
  import { wrapTableInExpand } from './commands/collapse';
30
+ import { deleteColumnsCommand } from './commands/delete';
30
31
  import { insertColumn, insertRow } from './commands/insert';
31
32
  import {
32
33
  deleteTable,
@@ -45,7 +46,7 @@ import {
45
46
  import { getPluginState } from './pm-plugins/plugin-factory';
46
47
  import { distributeColumnsWidths } from './pm-plugins/table-resizing/commands';
47
48
  import type { ResizeStateWithAnalytics } from './pm-plugins/table-resizing/utils';
48
- import { deleteColumns, deleteRows, mergeCells } from './transforms';
49
+ import { deleteRows, mergeCells } from './transforms';
49
50
  import type {
50
51
  InsertRowMethods,
51
52
  InsertRowOptions,
@@ -57,7 +58,6 @@ import {
57
58
  getSelectedTableInfo,
58
59
  } from './utils';
59
60
  import { withEditorAnalyticsAPI } from './utils/analytics';
60
- import { getAllowAddColumnCustomStep } from './utils/get-allow-add-column-custom-step';
61
61
 
62
62
  const TABLE_BREAKOUT_NAME_MAPPING = {
63
63
  default: TABLE_BREAKOUT.NORMAL,
@@ -337,14 +337,7 @@ export const deleteColumnsWithAnalytics =
337
337
  },
338
338
  eventType: EVENT_TYPE.TRACK,
339
339
  };
340
- })(editorAnalyticsAPI)((state, dispatch) => {
341
- if (dispatch) {
342
- dispatch(
343
- deleteColumns(rect, getAllowAddColumnCustomStep(state))(state.tr),
344
- );
345
- }
346
- return true;
347
- });
340
+ })(editorAnalyticsAPI)(deleteColumnsCommand(rect));
348
341
 
349
342
  const getTableDeletedAnalytics = (
350
343
  selection: Selection,
@@ -412,6 +412,7 @@ export const handleCut = (
412
412
  oldState: EditorState,
413
413
  newState: EditorState,
414
414
  editorAnalyticsAPI?: EditorAnalyticsAPI,
415
+ editorView?: EditorView,
415
416
  ): Transaction => {
416
417
  const oldSelection = oldState.tr.selection;
417
418
  let { tr } = newState;
@@ -464,7 +465,11 @@ export const handleCut = (
464
465
  } = getPluginState(newState);
465
466
  tr = deleteRows(rect, isHeaderRowRequired)(tr);
466
467
  } else if (tr.selection.isColSelection()) {
467
- tr = deleteColumns(rect, getAllowAddColumnCustomStep(oldState))(tr);
468
+ tr = deleteColumns(
469
+ rect,
470
+ getAllowAddColumnCustomStep(oldState),
471
+ editorView,
472
+ )(tr);
468
473
  }
469
474
  }
470
475
  }
@@ -191,7 +191,13 @@ export const createPlugin = (
191
191
 
192
192
  if (tr) {
193
193
  // "fixTables" removes empty rows as we don't allow that in schema
194
- const updatedTr = handleCut(tr, oldState, newState, editorAnalyticsAPI);
194
+ const updatedTr = handleCut(
195
+ tr,
196
+ oldState,
197
+ newState,
198
+ editorAnalyticsAPI,
199
+ editorViewRef || undefined,
200
+ );
195
201
  return fixTables(updatedTr) || updatedTr;
196
202
  }
197
203
  if (transactions.find((tr) => tr.docChanged)) {
@@ -130,5 +130,5 @@ export const getTableMaxWidth = ({
130
130
  maxWidth -= akEditorTableNumberColumnWidth;
131
131
  }
132
132
 
133
- return maxWidth;
133
+ return maxWidth as number;
134
134
  };
@@ -1,22 +1,20 @@
1
- import { CellAttributes } from '@atlaskit/adf-schema';
1
+ import type { CellAttributes } from '@atlaskit/adf-schema';
2
2
  import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
3
- import {
4
- tableCellMinWidth,
5
- tableNewColumnMinWidth,
6
- } from '@atlaskit/editor-common/styles';
3
+ import { tableCellMinWidth } from '@atlaskit/editor-common/styles';
7
4
  import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
8
- import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
9
- import { Transaction } from '@atlaskit/editor-prosemirror/state';
10
- import { ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
11
- import { EditorView } from '@atlaskit/editor-prosemirror/view';
5
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
6
+ import type { Transaction } from '@atlaskit/editor-prosemirror/state';
7
+ import type { ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
8
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
12
9
  import { akEditorDefaultLayoutWidth } from '@atlaskit/editor-shared-styles';
13
- import { TableMap } from '@atlaskit/editor-tables/table-map';
10
+ import {
11
+ TableMap,
12
+ tableNewColumnMinWidth,
13
+ } from '@atlaskit/editor-tables/table-map';
14
14
  import { getBooleanFF } from '@atlaskit/platform-feature-flags';
15
15
 
16
- import {
17
- hasTableBeenResized,
18
- ResizeState,
19
- } from '../pm-plugins/table-resizing/utils';
16
+ import type { ResizeState } from '../pm-plugins/table-resizing/utils';
17
+ import { hasTableBeenResized } from '../pm-plugins/table-resizing/utils';
20
18
  import { isMinCellWidthTable } from '../pm-plugins/table-resizing/utils/colgroup';
21
19
  import { getTableMaxWidth } from '../pm-plugins/table-resizing/utils/misc';
22
20
  import {
@@ -26,6 +24,13 @@ import {
26
24
  import { scaleTableTo } from '../pm-plugins/table-resizing/utils/scale-table';
27
25
  import { insertColumnButtonOffset } from '../ui/common-styles';
28
26
 
27
+ /**
28
+ * Given a new ResizeState object, create a transaction that replaces and updates the table node based on new state.
29
+ * @param resizeState
30
+ * @param table
31
+ * @param start
32
+ * @returns
33
+ */
29
34
  export const updateColumnWidths =
30
35
  (resizeState: ResizeState, table: PMNode, start: number) =>
31
36
  (tr: Transaction): Transaction => {
@@ -147,7 +152,129 @@ export const updateColumnWidths =
147
152
  * @param view
148
153
  * @returns Updated transaction with rescaled columns for a given table
149
154
  */
150
- export const rescaleColumns =
155
+ export const rescaleColumnsNew =
156
+ () =>
157
+ (table: ContentNodeWithPos, view: EditorView | undefined) =>
158
+ (tr: Transaction): Transaction => {
159
+ if (!view) {
160
+ return tr;
161
+ }
162
+
163
+ const newTable = tr.doc.nodeAt(table.pos);
164
+ const domAtPos = view.domAtPos.bind(view);
165
+ const maybeTable = domAtPos(table.start).node as HTMLElement;
166
+ const tableRef = maybeTable.closest('table');
167
+
168
+ if (!tableRef || !newTable) {
169
+ return tr;
170
+ }
171
+
172
+ const isResized = hasTableBeenResized(table.node);
173
+ // get current table info
174
+ const previousTableInfo = {
175
+ // when table is resized the tableRef client width will be 1px larger than colGroup, which is used in calculations
176
+ width: isResized ? tableRef.clientWidth - 1 : tableRef.clientWidth,
177
+ /** the is the width the table can reach before overflowing */
178
+ possibleMaxWidth: getBooleanFF('platform.editor.custom-table-width')
179
+ ? tableRef?.parentElement?.clientWidth || 0
180
+ : (tableRef?.parentElement?.clientWidth || 0) -
181
+ insertColumnButtonOffset -
182
+ 1,
183
+ isResized,
184
+ };
185
+
186
+ // determine the new table, based on new width
187
+ const newTableInfo = {
188
+ noOfColumns: TableMap.get(newTable).width,
189
+ };
190
+
191
+ if (!newTableInfo.noOfColumns || newTableInfo.noOfColumns <= 0) {
192
+ return tr;
193
+ }
194
+
195
+ const averageColumnWidth =
196
+ previousTableInfo.width / newTableInfo.noOfColumns;
197
+
198
+ // If the table has not been resized (i.e. all columns will have the same width) and every column width is bigger than the minimum column width
199
+ // we skip updating the size of columns here.
200
+ if (
201
+ !previousTableInfo.isResized &&
202
+ averageColumnWidth > tableCellMinWidth
203
+ ) {
204
+ return tr;
205
+ }
206
+
207
+ const wasTableInOverflow =
208
+ previousTableInfo.width > previousTableInfo.possibleMaxWidth;
209
+
210
+ // If the table has not been resized, and each column width is smaller than the minimum column width
211
+ // Or if the table has been resized, but each column width is either 48px or null
212
+ // we update the table to have 48px for each column
213
+ if (
214
+ (!previousTableInfo.isResized &&
215
+ averageColumnWidth <= tableCellMinWidth) ||
216
+ (previousTableInfo.isResized && isMinCellWidthTable(table.node))
217
+ ) {
218
+ const widths = new Array(newTableInfo.noOfColumns).fill(
219
+ tableCellMinWidth,
220
+ );
221
+ const cols = widths.map((_, index) => ({
222
+ width: tableCellMinWidth,
223
+ minWidth: tableCellMinWidth,
224
+ index,
225
+ }));
226
+
227
+ const minWidthResizeState = {
228
+ cols,
229
+ widths,
230
+ maxSize: previousTableInfo.possibleMaxWidth,
231
+ tableWidth: previousTableInfo.width,
232
+ overflow: wasTableInOverflow,
233
+ };
234
+ return updateColumnWidths(
235
+ minWidthResizeState,
236
+ table.node,
237
+ table.start,
238
+ )(tr);
239
+ }
240
+
241
+ let resizeState = getResizeState({
242
+ minWidth: tableCellMinWidth,
243
+ table: table.node,
244
+ start: table.start,
245
+ tableRef,
246
+ domAtPos,
247
+ maxSize: previousTableInfo.possibleMaxWidth,
248
+ });
249
+
250
+ // Two scenarios that require scaling:
251
+ // 1. If the new table width will result in the table going into overflow
252
+ // we resize the cells to avoid it (e.g. adding a column)
253
+ // 2. If the new table width will be shorter than the parent width, scale columns to fit parent
254
+ if (
255
+ (!wasTableInOverflow && resizeState.overflow) ||
256
+ resizeState.tableWidth < resizeState.maxSize
257
+ ) {
258
+ resizeState = scaleTableTo(
259
+ resizeState,
260
+ previousTableInfo.possibleMaxWidth,
261
+ );
262
+ }
263
+
264
+ return updateColumnWidths(resizeState, table.node, table.start)(tr);
265
+ };
266
+
267
+ /**
268
+ * This function is called when user inserts/deletes a column in a table to;
269
+ * - rescale all columns (if the table did not overflow before the insertion)
270
+ * - and update column widths.
271
+ *
272
+ * This is done manually to avoid a multi-dispatch in TableComponent. See [ED-8288].
273
+ * @param table
274
+ * @param view
275
+ * @returns Updated transaction with rescaled columns for a given table
276
+ */
277
+ export const rescaleColumnsOld =
151
278
  (getEditorContainerWidth: GetEditorContainerWidth) =>
152
279
  (table: ContentNodeWithPos, view: EditorView | undefined) =>
153
280
  (tr: Transaction): Transaction => {
@@ -246,3 +373,16 @@ export const rescaleColumns =
246
373
 
247
374
  return updateColumnWidths(resizeState, table.node, table.start)(tr);
248
375
  };
376
+
377
+ export const rescaleColumns = (
378
+ getEditorContainerWidth?: GetEditorContainerWidth,
379
+ ) => {
380
+ if (
381
+ getBooleanFF(
382
+ 'platform.editor.table-update-colwidths-after-column-is-deleted',
383
+ )
384
+ ) {
385
+ return rescaleColumnsNew();
386
+ }
387
+ return rescaleColumnsOld(getEditorContainerWidth!);
388
+ };
@@ -4,12 +4,15 @@ import { TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics
4
4
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
5
  import type { Transaction } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Selection } from '@atlaskit/editor-prosemirror/state';
7
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
8
  import type { Rect } from '@atlaskit/editor-tables/table-map';
8
9
  import { TableMap } from '@atlaskit/editor-tables/table-map';
9
10
  import { findTable } from '@atlaskit/editor-tables/utils';
11
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
10
12
 
11
13
  import { META_KEYS } from '../pm-plugins/table-analytics';
12
14
 
15
+ import { rescaleColumns } from './column-width';
13
16
  import { splitCellsInColumns } from './split';
14
17
 
15
18
  const deleteColumnsCustomStep =
@@ -247,13 +250,27 @@ function fixRowSpans(table: PMNode): PMNode | null {
247
250
  }
248
251
 
249
252
  export const deleteColumns =
250
- (rect: Rect, allowAddColumnCustomStep = false) =>
251
- (tr: Transaction): Transaction => {
252
- tr.setMeta(META_KEYS.OVERFLOW_TRIGGER, {
253
+ (rect: Rect, allowCustomStep: boolean, view?: EditorView) =>
254
+ (tr: Transaction) => {
255
+ let updatedTr = tr;
256
+ updatedTr.setMeta(META_KEYS.OVERFLOW_TRIGGER, {
253
257
  name: TABLE_OVERFLOW_CHANGE_TRIGGER.DELETED_COLUMN,
254
258
  });
255
- if (allowAddColumnCustomStep) {
256
- return deleteColumnsCustomStep(rect)(tr);
259
+
260
+ if (allowCustomStep) {
261
+ updatedTr = deleteColumnsCustomStep(rect)(updatedTr);
262
+ } else {
263
+ updatedTr = deleteColumnsLegacy(rect)(updatedTr);
264
+ }
265
+ const table = findTable(updatedTr.selection);
266
+ if (
267
+ getBooleanFF(
268
+ 'platform.editor.table-update-colwidths-after-column-is-deleted',
269
+ )
270
+ ) {
271
+ if (table) {
272
+ updatedTr = rescaleColumns()(table, view)(updatedTr);
273
+ }
257
274
  }
258
- return deleteColumnsLegacy(rect)(tr);
275
+ return updatedTr;
259
276
  };
@@ -434,7 +434,7 @@ export class ContextualMenu extends Component<
434
434
  deleteColumnsWithAnalytics(editorAnalyticsAPI)(
435
435
  INPUT_METHOD.CONTEXT_MENU,
436
436
  selectionRect,
437
- )(state, dispatch);
437
+ )(state, dispatch, editorView);
438
438
  this.toggleOpen();
439
439
  break;
440
440
  case 'delete_row':
@@ -1,4 +1,5 @@
1
- import React, { Component, SyntheticEvent } from 'react';
1
+ import type { SyntheticEvent } from 'react';
2
+ import React, { Component } from 'react';
2
3
 
3
4
  import { createPortal } from 'react-dom';
4
5
 
@@ -6,8 +7,8 @@ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
6
7
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
7
8
  import { Popup } from '@atlaskit/editor-common/ui';
8
9
  import { closestElement } from '@atlaskit/editor-common/utils';
9
- import { Selection } from '@atlaskit/editor-prosemirror/state';
10
- import { EditorView } from '@atlaskit/editor-prosemirror/view';
10
+ import type { Selection } from '@atlaskit/editor-prosemirror/state';
11
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
11
12
  import { akEditorTableNumberColumnWidth } from '@atlaskit/editor-shared-styles';
12
13
  import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
13
14
  import {
@@ -21,7 +22,7 @@ import {
21
22
  deleteRowsWithAnalytics,
22
23
  } from '../../commands-with-analytics';
23
24
  import { getPluginState as getTablePluginState } from '../../pm-plugins/plugin-factory';
24
- import { RowStickyState } from '../../pm-plugins/sticky-headers';
25
+ import type { RowStickyState } from '../../pm-plugins/sticky-headers';
25
26
  import { TableCssClassName as ClassName } from '../../types';
26
27
  import {
27
28
  getColumnDeleteButtonParams,
@@ -34,7 +35,7 @@ import tableMessages from '../messages';
34
35
 
35
36
  import DeleteButton from './DeleteButton';
36
37
  import getPopupOptions from './getPopUpOptions';
37
- import { CellSelectionType } from './types';
38
+ import type { CellSelectionType } from './types';
38
39
 
39
40
  export interface Props {
40
41
  editorView: EditorView;
@@ -278,7 +279,7 @@ class FloatingDeleteButton extends Component<Props, State> {
278
279
  deleteColumnsWithAnalytics(editorAnalyticsAPI)(
279
280
  INPUT_METHOD.BUTTON,
280
281
  rect,
281
- )(state, dispatch);
282
+ )(state, dispatch, this.props.editorView);
282
283
  return;
283
284
  }
284
285
  case 'row': {
@@ -249,7 +249,6 @@ const tableWrapperStyles = () => {
249
249
  position: relative;
250
250
 
251
251
  > table[data-number-column='true'] {
252
- margin-left: 1px;
253
252
  width: calc(100% - 1px);
254
253
  }
255
254
  }