@atlaskit/editor-plugin-table 5.5.3 → 5.5.5

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 (53) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/plugins/table/commands/index.js +12 -0
  3. package/dist/cjs/plugins/table/commands/misc.js +61 -1
  4. package/dist/cjs/plugins/table/pm-plugins/drag-and-drop/plugin.js +2 -3
  5. package/dist/cjs/plugins/table/ui/FloatingInsertButton/index.js +0 -3
  6. package/dist/cjs/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +8 -2
  7. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +9 -2
  8. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +11 -0
  9. package/dist/cjs/plugins/table/utils/index.js +6 -0
  10. package/dist/cjs/plugins/table/utils/merged-cells.js +75 -1
  11. package/dist/es2019/plugins/table/commands/index.js +1 -1
  12. package/dist/es2019/plugins/table/commands/misc.js +46 -1
  13. package/dist/es2019/plugins/table/pm-plugins/drag-and-drop/plugin.js +3 -4
  14. package/dist/es2019/plugins/table/ui/FloatingInsertButton/index.js +0 -3
  15. package/dist/es2019/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +9 -3
  16. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +9 -2
  17. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +16 -1
  18. package/dist/es2019/plugins/table/utils/index.js +1 -1
  19. package/dist/es2019/plugins/table/utils/merged-cells.js +63 -1
  20. package/dist/esm/plugins/table/commands/index.js +1 -1
  21. package/dist/esm/plugins/table/commands/misc.js +61 -1
  22. package/dist/esm/plugins/table/pm-plugins/drag-and-drop/plugin.js +3 -4
  23. package/dist/esm/plugins/table/ui/FloatingInsertButton/index.js +0 -3
  24. package/dist/esm/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.js +9 -3
  25. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/DragControls.js +9 -2
  26. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +12 -1
  27. package/dist/esm/plugins/table/utils/index.js +1 -1
  28. package/dist/esm/plugins/table/utils/merged-cells.js +73 -0
  29. package/dist/types/plugins/table/commands/index.d.ts +1 -1
  30. package/dist/types/plugins/table/commands/misc.d.ts +2 -0
  31. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +1 -0
  32. package/dist/types/plugins/table/ui/TableFloatingControls/index.d.ts +1 -0
  33. package/dist/types/plugins/table/utils/index.d.ts +1 -1
  34. package/dist/types/plugins/table/utils/merged-cells.d.ts +3 -0
  35. package/dist/types-ts4.5/plugins/table/commands/index.d.ts +1 -1
  36. package/dist/types-ts4.5/plugins/table/commands/misc.d.ts +2 -0
  37. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/RowControls/DragControls.d.ts +1 -0
  38. package/dist/types-ts4.5/plugins/table/ui/TableFloatingControls/index.d.ts +1 -0
  39. package/dist/types-ts4.5/plugins/table/utils/index.d.ts +1 -1
  40. package/dist/types-ts4.5/plugins/table/utils/merged-cells.d.ts +3 -0
  41. package/package.json +1 -1
  42. package/src/__tests__/unit/ui/FloatingInsertButton.tsx +3 -3
  43. package/src/__tests__/unit/ui/RowDragControls.tsx +2 -0
  44. package/src/__tests__/unit/utils/merged-cells.ts +156 -0
  45. package/src/plugins/table/commands/index.ts +2 -0
  46. package/src/plugins/table/commands/misc.ts +78 -0
  47. package/src/plugins/table/pm-plugins/drag-and-drop/plugin.ts +11 -9
  48. package/src/plugins/table/ui/FloatingInsertButton/index.tsx +0 -3
  49. package/src/plugins/table/ui/TableFloatingColumnControls/ColumnControls/index.tsx +22 -2
  50. package/src/plugins/table/ui/TableFloatingControls/RowControls/DragControls.tsx +21 -2
  51. package/src/plugins/table/ui/TableFloatingControls/index.tsx +12 -1
  52. package/src/plugins/table/utils/index.ts +5 -1
  53. package/src/plugins/table/utils/merged-cells.ts +82 -0
@@ -30,8 +30,10 @@ import {
30
30
  isSelectionType,
31
31
  isTableSelected,
32
32
  removeTable,
33
+ selectColumns as selectColumnsTransform,
33
34
  selectColumn as selectColumnTransform,
34
35
  selectionCell,
36
+ selectRows as selectRowsTransform,
35
37
  selectRow as selectRowTransform,
36
38
  setCellAttrs,
37
39
  } from '@atlaskit/editor-tables/utils';
@@ -487,6 +489,53 @@ export const selectColumn = (column: number, expand?: boolean) =>
487
489
  selectColumnTransform(column, expand)(tr).setMeta('addToHistory', false),
488
490
  );
489
491
 
492
+ export const selectColumns = (columnIndexes: number[]) =>
493
+ createCommand(
494
+ (state) => {
495
+ if (!columnIndexes) {
496
+ return false;
497
+ }
498
+ const cells = columnIndexes
499
+ .map((column) => getCellsInColumn(column)(state.tr.selection))
500
+ .flat();
501
+ if (
502
+ !cells ||
503
+ !cells.length ||
504
+ cells.some((cell) => cell && typeof cell.pos !== 'number')
505
+ ) {
506
+ return false;
507
+ }
508
+ const decorations = createColumnSelectedDecoration(
509
+ selectColumnsTransform(columnIndexes)(state.tr),
510
+ );
511
+
512
+ const decorationSet = updatePluginStateDecorations(
513
+ state,
514
+ decorations,
515
+ TableDecorations.COLUMN_SELECTED,
516
+ );
517
+
518
+ const cellsInFirstColumn = getCellsInColumn(Math.min(...columnIndexes))(
519
+ state.tr.selection,
520
+ );
521
+ if (!cellsInFirstColumn || cellsInFirstColumn.length === 0) {
522
+ return false;
523
+ }
524
+ const targetCellPosition = cellsInFirstColumn[0].pos;
525
+
526
+ return {
527
+ type: 'SELECT_COLUMN',
528
+ data: { targetCellPosition, decorationSet },
529
+ };
530
+ },
531
+ (tr: Transaction) => {
532
+ return selectColumnsTransform(columnIndexes)(tr).setMeta(
533
+ 'addToHistory',
534
+ false,
535
+ );
536
+ },
537
+ );
538
+
490
539
  export const selectRow = (row: number, expand?: boolean) =>
491
540
  createCommand(
492
541
  (state) => {
@@ -501,6 +550,35 @@ export const selectRow = (row: number, expand?: boolean) =>
501
550
  (tr) => selectRowTransform(row, expand)(tr).setMeta('addToHistory', false),
502
551
  );
503
552
 
553
+ export const selectRows = (rowIndexes: number[]) =>
554
+ createCommand(
555
+ (state) => {
556
+ if (rowIndexes.length === 0) {
557
+ return false;
558
+ }
559
+ const cells = rowIndexes
560
+ .map((row) => getCellsInRow(row)(state.tr.selection))
561
+ .flat();
562
+ if (
563
+ !cells ||
564
+ !cells.length ||
565
+ cells.some((cell) => cell && typeof cell.pos !== 'number')
566
+ ) {
567
+ return false;
568
+ }
569
+ const cellsInFirstRow = getCellsInRow(Math.min(...rowIndexes))(
570
+ state.tr.selection,
571
+ );
572
+ if (!cellsInFirstRow || cellsInFirstRow.length === 0) {
573
+ return false;
574
+ }
575
+ const targetCellPosition = cellsInFirstRow[0].pos;
576
+
577
+ return { type: 'SET_TARGET_CELL_POSITION', data: { targetCellPosition } };
578
+ },
579
+ (tr) => selectRowsTransform(rowIndexes)(tr).setMeta('addToHistory', false),
580
+ );
581
+
504
582
  export const showInsertColumnButton = (columnIndex: number) =>
505
583
  createCommand(
506
584
  (_) =>
@@ -10,11 +10,10 @@ import { getCellsInRow } from '@atlaskit/editor-tables/utils';
10
10
  import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element';
11
11
 
12
12
  import type { DraggableSourceData } from '../../types';
13
- import { findNearestCellIndexToPoint } from '../../utils';
14
13
  import {
15
- hasMergedCellsInColumn,
16
- hasMergedCellsInRow,
17
- } from '../../utils/merged-cells';
14
+ findNearestCellIndexToPoint,
15
+ hasMergedCellsInBetween,
16
+ } from '../../utils';
18
17
  import { getPluginState as getTablePluginState } from '../plugin-factory';
19
18
  import { pluginKey as tablePluginKey } from '../plugin-key';
20
19
 
@@ -215,12 +214,13 @@ export const createPlugin = (
215
214
  }
216
215
 
217
216
  // If the drop target index contains merged cells then we should not allow the drop to occur.
218
- const hasMergedCells =
219
- sourceType === 'table-row'
220
- ? hasMergedCellsInRow
221
- : hasMergedCellsInColumn;
222
217
  if (
223
- hasMergedCells(targetAdjustedIndex)(editorView.state.selection)
218
+ hasMergedCellsInBetween(
219
+ [targetAdjustedIndex - 1, targetAdjustedIndex],
220
+ sourceType === 'table-row'
221
+ ? DropTargetType.ROW
222
+ : DropTargetType.COLUMN,
223
+ )(editorView.state.selection)
224
224
  ) {
225
225
  clearDropTarget(tr)(editorView.state, editorView.dispatch);
226
226
  return;
@@ -235,6 +235,8 @@ export const createPlugin = (
235
235
  targetAdjustedIndex + (direction === -1 ? 0 : -1),
236
236
  tr,
237
237
  )(editorView.state, editorView.dispatch);
238
+
239
+ editorView.focus();
238
240
  });
239
241
  },
240
242
  }),
@@ -153,9 +153,6 @@ export class FloatingInsertButton extends React.Component<
153
153
  docSize: editorView.state.doc.nodeSize,
154
154
  error: (error as any)?.toString(),
155
155
  },
156
- nonPrivacySafeAttributes: {
157
- errorStack: (error as any).stack || undefined,
158
- },
159
156
  };
160
157
  dispatchAnalyticsEvent(payload);
161
158
  }
@@ -13,6 +13,7 @@ import {
13
13
  hoverCell,
14
14
  hoverColumns,
15
15
  selectColumn,
16
+ selectColumns,
16
17
  } from '../../../commands';
17
18
  import { toggleDragMenu } from '../../../pm-plugins/drag-and-drop/commands';
18
19
  import type { CellHoverMeta, HandleTypes } from '../../../types';
@@ -81,9 +82,28 @@ export const ColumnControls = ({
81
82
  const handleClick = useCallback(
82
83
  (event: MouseEvent) => {
83
84
  const { state, dispatch } = editorView;
84
- selectColumn(colIndex!, event.shiftKey)(state, dispatch);
85
+
86
+ const isClickOutsideSelectedCols =
87
+ selectedColIndexes.length >= 1 &&
88
+ !selectedColIndexes.includes(colIndex!);
89
+
90
+ if (
91
+ !selectedColIndexes ||
92
+ selectedColIndexes.length === 0 ||
93
+ isClickOutsideSelectedCols
94
+ ) {
95
+ selectColumn(colIndex!, event.shiftKey)(state, dispatch);
96
+ }
97
+
98
+ if (
99
+ selectedColIndexes.length > 1 &&
100
+ selectedColIndexes.includes(colIndex!) &&
101
+ !event.shiftKey
102
+ ) {
103
+ selectColumns(selectedColIndexes)(state, dispatch);
104
+ }
85
105
  },
86
- [colIndex, editorView],
106
+ [colIndex, selectedColIndexes, editorView],
87
107
  );
88
108
 
89
109
  const handleMouseOver = useCallback(() => {
@@ -50,6 +50,7 @@ type DragControlsProps = {
50
50
  canDrag?: boolean;
51
51
  hoverRows: (rows: number[], danger?: boolean) => void;
52
52
  selectRow: (row: number, expand: boolean) => void;
53
+ selectRows: (rowIndexes: number[]) => void;
53
54
  updateCellHoverLocation: (rowIndex: number) => void;
54
55
  };
55
56
 
@@ -77,6 +78,7 @@ const DragControlsComponent = ({
77
78
  canDrag,
78
79
  hoverRows,
79
80
  selectRow,
81
+ selectRows,
80
82
  updateCellHoverLocation,
81
83
  }: DragControlsProps & WrappedComponentProps) => {
82
84
  const [isDragging, setIsDragging] = useState(false);
@@ -157,9 +159,26 @@ const DragControlsComponent = ({
157
159
 
158
160
  const handleClick = useCallback(
159
161
  (e: MouseEvent) => {
160
- selectRow(rowIndex!, e?.shiftKey);
162
+ const isClickOutsideSelectedRows =
163
+ selectedRowIndexes.length >= 1 &&
164
+ !selectedRowIndexes.includes(rowIndex!);
165
+ if (
166
+ !selectedRowIndexes ||
167
+ selectedRowIndexes.length === 0 ||
168
+ isClickOutsideSelectedRows
169
+ ) {
170
+ selectRow(rowIndex!, e.shiftKey);
171
+ }
172
+
173
+ if (
174
+ selectedRowIndexes.length > 1 &&
175
+ selectedRowIndexes.includes(rowIndex!) &&
176
+ !e.shiftKey
177
+ ) {
178
+ selectRows(selectedRowIndexes);
179
+ }
161
180
  },
162
- [rowIndex, selectRow],
181
+ [rowIndex, selectRow, selectRows, selectedRowIndexes],
163
182
  );
164
183
 
165
184
  const generateHandleByType = (type: HandleTypes): JSX.Element | null => {
@@ -6,7 +6,7 @@ import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
6
6
  import type { Selection } from '@atlaskit/editor-prosemirror/state';
7
7
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
8
8
 
9
- import { hoverCell, hoverRows, selectRow } from '../../commands';
9
+ import { hoverCell, hoverRows, selectRow, selectRows } from '../../commands';
10
10
  import type { RowStickyState } from '../../pm-plugins/sticky-headers';
11
11
  import { TableCssClassName as ClassName } from '../../types';
12
12
  import type { CellHoverMeta } from '../../types';
@@ -211,6 +211,7 @@ export default class TableFloatingControls extends Component<Props, State> {
211
211
  tableWidth={this.state.tableWrapperWidth}
212
212
  hoverRows={this.hoverRows}
213
213
  selectRow={this.selectRow}
214
+ selectRows={this.selectRows}
214
215
  updateCellHoverLocation={this.updateCellHoverLocation}
215
216
  canDrag={canDrag}
216
217
  />
@@ -256,6 +257,16 @@ export default class TableFloatingControls extends Component<Props, State> {
256
257
  selectRow(row, expand)(state, dispatch);
257
258
  };
258
259
 
260
+ private selectRows = (rowIndexes: number[]) => {
261
+ const { editorView } = this.props;
262
+ const { state, dispatch } = editorView;
263
+ // fix for issue ED-4665
264
+ if (browser.ie_version === 11) {
265
+ (editorView.dom as HTMLElement).blur();
266
+ }
267
+ selectRows(rowIndexes)(state, dispatch);
268
+ };
269
+
259
270
  private hoverRows = (rows: Array<number>, danger?: boolean) => {
260
271
  const { state, dispatch } = this.props.editorView;
261
272
  hoverRows(rows, danger)(state, dispatch);
@@ -79,4 +79,8 @@ export type { RowParams } from './row-controls';
79
79
  export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
80
80
  export { getMergedCellsPositions } from './table';
81
81
  export { updatePluginStateDecorations } from './update-plugin-state-decorations';
82
- export { hasMergedCellsInColumn, hasMergedCellsInRow } from './merged-cells';
82
+ export {
83
+ hasMergedCellsInColumn,
84
+ hasMergedCellsInRow,
85
+ hasMergedCellsInBetween,
86
+ } from './merged-cells';
@@ -2,6 +2,8 @@ import type { Selection } from '@atlaskit/editor-prosemirror/state';
2
2
  import type { Rect } from '@atlaskit/editor-tables';
3
3
  import { findTable, TableMap } from '@atlaskit/editor-tables';
4
4
 
5
+ type MergeType = 'row' | 'column';
6
+
5
7
  const hasMergedCells =
6
8
  (
7
9
  indexes: number | number[],
@@ -65,3 +67,83 @@ export const hasMergedCellsInRow = (rowIndexes: number | number[]) =>
65
67
  bottom: y === index ? y + 1 : y,
66
68
  };
67
69
  });
70
+
71
+ const getRect = (index: number, type: MergeType, map: TableMap) => {
72
+ if (type === 'column') {
73
+ const x = Math.max(Math.min(index, map.width - 1), 0); // clamped index
74
+ return {
75
+ left: x,
76
+ right: x === index ? x + 1 : x,
77
+ top: 0,
78
+ bottom: map.height,
79
+ };
80
+ } else {
81
+ const y = Math.max(Math.min(index, map.height - 1), 0); // clamped index
82
+ return {
83
+ left: 0,
84
+ right: map.width,
85
+ top: y,
86
+ bottom: y === index ? y + 1 : y,
87
+ };
88
+ }
89
+ };
90
+
91
+ export const hasMergedCellsInBetween =
92
+ (indexes: number[], type: MergeType) =>
93
+ (selection: Selection): boolean => {
94
+ const table = findTable(selection);
95
+ if (!table) {
96
+ return false;
97
+ }
98
+
99
+ const map = TableMap.get(table.node);
100
+ const cellPositions = new Set<number>();
101
+ const mergedCells = new Set<number>();
102
+
103
+ map.map.forEach((value) => {
104
+ if (cellPositions.has(value)) {
105
+ mergedCells.add(value);
106
+ } else {
107
+ cellPositions.add(value);
108
+ }
109
+ });
110
+
111
+ if (!mergedCells.size) {
112
+ return false;
113
+ }
114
+
115
+ const getMergedCellsInRect = (index: number, type: MergeType) => {
116
+ const rect = getRect(index, type, map);
117
+ const isValidRectangle = rect.left < rect.right && rect.top < rect.bottom;
118
+ if (!isValidRectangle) {
119
+ return [];
120
+ }
121
+
122
+ const cells = map.cellsInRect(rect);
123
+
124
+ let allCellsInRect = [];
125
+ if (type === 'column') {
126
+ allCellsInRect = map.map.filter((_, key) => key % map.width === index);
127
+ } else {
128
+ allCellsInRect = map.map.filter(
129
+ (_, key) => Math.floor(key / map.width) === index,
130
+ );
131
+ }
132
+ const mergedCell = allCellsInRect.filter((nodePos) => {
133
+ return !cells.includes(nodePos) // cell exists in Rect but not show in the map.cellsInRect list => merged cell
134
+ ? true
135
+ : mergedCells.has(nodePos); // cell includes in mergedCells => merged cell
136
+ });
137
+
138
+ return [...new Set(mergedCell)];
139
+ };
140
+
141
+ const mergedCellsInRectArr = indexes.map((index) =>
142
+ getMergedCellsInRect(index, type),
143
+ );
144
+
145
+ // Currently only support 2 indexes, but we can extend this to support more indexes in the future.
146
+ return mergedCellsInRectArr[0].some((cell) =>
147
+ mergedCellsInRectArr[1].includes(cell),
148
+ );
149
+ };