@atlaskit/editor-plugin-table 0.0.6 → 0.0.7

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 (57) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/cjs/plugins/table/event-handlers.js +7 -6
  3. package/dist/cjs/plugins/table/nodeviews/tableCell.js +4 -4
  4. package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  5. package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  6. package/dist/cjs/plugins/table/utils/column-controls.js +1 -1
  7. package/dist/cjs/version.json +1 -1
  8. package/dist/es2019/plugins/table/event-handlers.js +8 -7
  9. package/dist/es2019/plugins/table/nodeviews/tableCell.js +3 -4
  10. package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  11. package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  12. package/dist/es2019/plugins/table/utils/column-controls.js +1 -1
  13. package/dist/es2019/version.json +1 -1
  14. package/dist/esm/plugins/table/event-handlers.js +8 -7
  15. package/dist/esm/plugins/table/nodeviews/tableCell.js +3 -4
  16. package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  17. package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  18. package/dist/esm/plugins/table/utils/column-controls.js +1 -1
  19. package/dist/esm/version.json +1 -1
  20. package/package.json +4 -2
  21. package/src/__tests__/unit/analytics.ts +737 -0
  22. package/src/__tests__/unit/collab.ts +76 -0
  23. package/src/__tests__/unit/commands/sort.ts +230 -0
  24. package/src/__tests__/unit/copy-paste.ts +686 -0
  25. package/src/__tests__/unit/event-handlers/index.ts +106 -0
  26. package/src/__tests__/unit/event-handlers.ts +202 -0
  27. package/src/__tests__/unit/fix-tables.ts +156 -0
  28. package/src/__tests__/unit/floating-toolbar.ts +95 -0
  29. package/src/__tests__/unit/handlers.ts +81 -0
  30. package/src/__tests__/unit/hover-selection.ts +277 -0
  31. package/src/__tests__/unit/index-with-fake-timers.ts +106 -0
  32. package/src/__tests__/unit/index.ts +986 -0
  33. package/src/__tests__/unit/keymap.ts +602 -0
  34. package/src/__tests__/unit/layout.ts +196 -0
  35. package/src/__tests__/unit/nodeviews/cell.ts +167 -0
  36. package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +33 -0
  37. package/src/__tests__/unit/sort-column.ts +512 -0
  38. package/src/__tests__/unit/transforms/delete-columns.ts +499 -0
  39. package/src/__tests__/unit/transforms/delete-rows.ts +557 -0
  40. package/src/__tests__/unit/transforms/merging.ts +374 -0
  41. package/src/__tests__/unit/ui/CornerControls.tsx +80 -0
  42. package/src/__tests__/unit/ui/FloatingContextualButton.tsx +95 -0
  43. package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +175 -0
  44. package/src/__tests__/unit/ui/FloatingInsertButton.tsx +266 -0
  45. package/src/__tests__/unit/ui/RowControls.tsx +301 -0
  46. package/src/__tests__/unit/ui/TableFloatingControls.tsx +93 -0
  47. package/src/__tests__/unit/undo-redo.ts +202 -0
  48. package/src/__tests__/unit/utils/dom.ts +286 -0
  49. package/src/__tests__/unit/utils/nodes.ts +59 -0
  50. package/src/__tests__/unit/utils/row-controls.ts +176 -0
  51. package/src/__tests__/unit/utils/table.ts +93 -0
  52. package/src/__tests__/unit/utils.ts +652 -0
  53. package/src/plugins/table/event-handlers.ts +5 -6
  54. package/src/plugins/table/nodeviews/tableCell.tsx +5 -4
  55. package/src/plugins/table/pm-plugins/table-resizing/utils/column-state.ts +1 -1
  56. package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +6 -2
  57. package/src/plugins/table/utils/column-controls.ts +1 -1
@@ -0,0 +1,499 @@
1
+ import { Rect } from '@atlaskit/editor-tables/table-map';
2
+ import {
3
+ createProsemirrorEditorFactory,
4
+ Preset,
5
+ LightEditorPlugin,
6
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
7
+ import {
8
+ doc,
9
+ p,
10
+ table,
11
+ tr,
12
+ td,
13
+ tdCursor,
14
+ tdEmpty,
15
+ DocBuilder,
16
+ } from '@atlaskit/editor-test-helpers/doc-builder';
17
+ import { uuid } from '@atlaskit/adf-schema';
18
+ import { TablePluginState } from '../../../plugins/table/types';
19
+ import { deleteColumns } from '../../../plugins/table/transforms';
20
+ import { getSelectionRect } from '@atlaskit/editor-tables/utils';
21
+ import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
22
+ import { PluginKey } from 'prosemirror-state';
23
+ import tablePlugin from '../../../plugins/table-plugin';
24
+
25
+ const colsToRect = (cols: Array<number>, noOfRows: number): Rect => ({
26
+ left: Math.min(...cols),
27
+ right: Math.max(...cols) + 1,
28
+ top: 0,
29
+ bottom: noOfRows,
30
+ });
31
+
32
+ const TABLE_LOCAL_ID = 'test-table-local-id';
33
+
34
+ describe('table plugin -> transforms -> delete columns', () => {
35
+ beforeAll(() => {
36
+ uuid.setStatic(TABLE_LOCAL_ID);
37
+ });
38
+
39
+ afterAll(() => {
40
+ uuid.setStatic(false);
41
+ });
42
+
43
+ const createEditor = createProsemirrorEditorFactory();
44
+ const preset = new Preset<LightEditorPlugin>().add([tablePlugin]);
45
+
46
+ const editor = (doc: DocBuilder) =>
47
+ createEditor<TablePluginState, PluginKey>({
48
+ doc,
49
+ preset,
50
+ pluginKey,
51
+ });
52
+
53
+ describe('when selection rect is given', () => {
54
+ describe('when the first column is deleted', () => {
55
+ it('should delete the column and move cursor to the first column', () => {
56
+ const {
57
+ editorView,
58
+ refs: { nextCursorPos },
59
+ } = editor(
60
+ doc(
61
+ p('text'),
62
+ table()(
63
+ tr(
64
+ td({})(p('{nextCursorPos}')),
65
+ td({})(p('c2')),
66
+ td({})(p('c3')),
67
+ ),
68
+ ),
69
+ ),
70
+ );
71
+ const { state, dispatch } = editorView;
72
+ dispatch(deleteColumns(colsToRect([0], 1))(state.tr));
73
+ expect(editorView.state.doc).toEqualDocument(
74
+ doc(
75
+ p('text'),
76
+ table({ localId: TABLE_LOCAL_ID })(
77
+ tr(td({})(p('c2')), td()(p('c3'))),
78
+ ),
79
+ ),
80
+ );
81
+ expect(editorView.state.selection.from).toEqual(nextCursorPos);
82
+ });
83
+ });
84
+
85
+ describe('when middle column is deleted', () => {
86
+ it('should delete the column and move cursor to the previous column', () => {
87
+ const {
88
+ editorView,
89
+ refs: { nextCursorPos },
90
+ } = editor(
91
+ doc(
92
+ p('text'),
93
+ table()(
94
+ tr(
95
+ td({})(p('{nextCursorPos}')),
96
+ td({})(p('c2')),
97
+ td({})(p('c3')),
98
+ ),
99
+ ),
100
+ ),
101
+ );
102
+ const { state, dispatch } = editorView;
103
+ dispatch(deleteColumns(colsToRect([1], 1))(state.tr));
104
+ expect(editorView.state.doc).toEqualDocument(
105
+ doc(
106
+ p('text'),
107
+ table({ localId: TABLE_LOCAL_ID })(tr(tdEmpty, td()(p('c3')))),
108
+ ),
109
+ );
110
+ expect(editorView.state.selection.from).toEqual(nextCursorPos);
111
+ });
112
+ });
113
+
114
+ describe('when multiple rows are selected', () => {
115
+ it('should delete these columns', () => {
116
+ const { editorView } = editor(
117
+ doc(
118
+ p('text'),
119
+ table()(tr(tdCursor, td({})(p('c1')), td({})(p('c2')))),
120
+ ),
121
+ );
122
+ const { state, dispatch } = editorView;
123
+ dispatch(deleteColumns(colsToRect([0, 1], 1))(state.tr));
124
+ expect(editorView.state.doc).toEqualDocument(
125
+ doc(p('text'), table({ localId: TABLE_LOCAL_ID })(tr(td()(p('c2'))))),
126
+ );
127
+ });
128
+ });
129
+ });
130
+
131
+ describe('when one column is selected', () => {
132
+ it('should delete the column', () => {
133
+ const { editorView } = editor(
134
+ doc(
135
+ p('text'),
136
+ table()(
137
+ tr(td({})(p('a1')), td({})(p('{<cell}a2')), td({})(p('a3'))),
138
+ tr(td({})(p('b1')), td({})(p('{cell>}b2')), td({})(p('b3'))),
139
+ ),
140
+ ),
141
+ );
142
+ const { state, dispatch } = editorView;
143
+ dispatch(deleteColumns(getSelectionRect(state.selection)!)(state.tr));
144
+ expect(editorView.state.doc).toEqualDocument(
145
+ doc(
146
+ p('text'),
147
+ table({ localId: TABLE_LOCAL_ID })(
148
+ tr(td({})(p('a1')), td({})(p('a3'))),
149
+ tr(td({})(p('b1')), td({})(p('b3'))),
150
+ ),
151
+ ),
152
+ );
153
+ });
154
+ });
155
+
156
+ describe('when multiple columns are selected', () => {
157
+ it('should delete these column', () => {
158
+ const { editorView } = editor(
159
+ doc(
160
+ p('text'),
161
+ table()(
162
+ tr(td({})(p('{<cell}a1')), td({})(p('a2')), td({})(p('a3'))),
163
+ tr(td({})(p('b1')), td({})(p('{cell>}b2')), td({})(p('b3'))),
164
+ ),
165
+ ),
166
+ );
167
+ const { state, dispatch } = editorView;
168
+ dispatch(deleteColumns(getSelectionRect(state.selection)!)(state.tr));
169
+ expect(editorView.state.doc).toEqualDocument(
170
+ doc(
171
+ p('text'),
172
+ table({ localId: TABLE_LOCAL_ID })(
173
+ tr(td({})(p('a3'))),
174
+ tr(td({})(p('b3'))),
175
+ ),
176
+ ),
177
+ );
178
+ });
179
+ });
180
+
181
+ describe('when some of the columns are merged', () => {
182
+ it('should delete columns and update colspans of cells DOM nodes', () => {
183
+ const { editorView } = editor(
184
+ doc(
185
+ p('text'),
186
+ table()(
187
+ tr(td({ colspan: 2 })(p('{<cell}c1')), td({})(p('c2'))),
188
+ tr(td({})(p('{cell>}c3')), td({})(p('c4')), td({})(p('c5'))),
189
+ ),
190
+ ),
191
+ );
192
+ const { state, dispatch } = editorView;
193
+ dispatch(deleteColumns(getSelectionRect(state.selection)!)(state.tr));
194
+ expect(editorView.state.doc).toEqualDocument(
195
+ doc(
196
+ p('text'),
197
+ table({ localId: TABLE_LOCAL_ID })(
198
+ tr(td({ colspan: 1 })(p('c2'))),
199
+ tr(td({ colspan: 1 })(p('c5'))),
200
+ ),
201
+ ),
202
+ );
203
+ const cells = editorView.dom.querySelectorAll('td');
204
+ for (let i = 0, count = cells.length; i < count; i++) {
205
+ const cell = cells[i] as HTMLElement;
206
+ expect(cell.getAttribute('colspan')).not.toEqual('2');
207
+ }
208
+ });
209
+
210
+ describe('when after deleting the last column table has rows where cells have rowspans > 1 in each column', () => {
211
+ it('should decrement rowspans of these cells', () => {
212
+ const { editorView } = editor(
213
+ doc(
214
+ p('text'),
215
+ table()(
216
+ tr(tdEmpty, tdEmpty, td({})(p('{<cell}a3'))),
217
+ tr(
218
+ td({ rowspan: 2 })(p('b1')),
219
+ td({ rowspan: 2 })(p('b2')),
220
+ tdEmpty,
221
+ ),
222
+ tr(td({})(p('{cell>}c3'))),
223
+ ),
224
+ ),
225
+ );
226
+ const { state, dispatch } = editorView;
227
+ dispatch(deleteColumns(getSelectionRect(state.selection)!)(state.tr));
228
+ expect(editorView.state.doc).toEqualDocument(
229
+ doc(
230
+ p('text'),
231
+ table({ localId: TABLE_LOCAL_ID })(
232
+ tr(tdEmpty, tdEmpty),
233
+ tr(td({})(p('b1')), td({})(p('b2'))),
234
+ ),
235
+ ),
236
+ );
237
+ });
238
+ });
239
+
240
+ describe('when after deleting the first column table has rows where cells have rowspans > 1 in each column', () => {
241
+ it('should decrement rowspans of these cells', () => {
242
+ const { editorView } = editor(
243
+ doc(
244
+ p('text'),
245
+ table()(
246
+ tr(td({})(p('{<cell}a1')), tdEmpty, tdEmpty),
247
+ tr(
248
+ tdEmpty,
249
+ td({ rowspan: 2 })(p('b2')),
250
+ td({ rowspan: 2 })(p('b3')),
251
+ ),
252
+ tr(td({})(p('{cell>}c1'))),
253
+ ),
254
+ ),
255
+ );
256
+ const { state, dispatch } = editorView;
257
+ dispatch(deleteColumns(getSelectionRect(state.selection)!)(state.tr));
258
+ expect(editorView.state.doc).toEqualDocument(
259
+ doc(
260
+ p('text'),
261
+ table({ localId: TABLE_LOCAL_ID })(
262
+ tr(tdEmpty, tdEmpty),
263
+ tr(td({})(p('b2')), td({})(p('b3'))),
264
+ ),
265
+ ),
266
+ );
267
+ });
268
+ });
269
+
270
+ describe('when a column-spanning cell is deleted', () => {
271
+ describe('when this cell has rowspan = 1', () => {
272
+ it('should append missing cells to the column(s) to the right from the deleted column', () => {
273
+ const { editorView } = editor(
274
+ doc(
275
+ table()(
276
+ tr(
277
+ td({ colwidth: [110] })(p('a1')),
278
+ td({ colwidth: [120] })(p('a2')),
279
+ td({ colwidth: [130] })(p('a3')),
280
+ ),
281
+ tr(td({ colwidth: [110, 120, 130], colspan: 3 })(p('b1'))),
282
+ tr(
283
+ td({ colwidth: [110] })(p('c1')),
284
+ td({ colwidth: [120] })(p('c2')),
285
+ td({ colwidth: [130] })(p('c3')),
286
+ ),
287
+ ),
288
+ ),
289
+ );
290
+ const { state, dispatch } = editorView;
291
+ dispatch(deleteColumns(colsToRect([0], 3))(state.tr));
292
+ expect(editorView.state.doc).toEqualDocument(
293
+ doc(
294
+ table({ localId: TABLE_LOCAL_ID })(
295
+ tr(
296
+ td({ colwidth: [120] })(p('a2')),
297
+ td({ colwidth: [130] })(p('a3')),
298
+ ),
299
+ tr(
300
+ td({ colwidth: [120] })(p('')),
301
+ td({ colwidth: [130] })(p('')),
302
+ ),
303
+ tr(
304
+ td({ colwidth: [120] })(p('c2')),
305
+ td({ colwidth: [130] })(p('c3')),
306
+ ),
307
+ ),
308
+ ),
309
+ );
310
+ });
311
+ });
312
+
313
+ describe('when this cell has rowspan > 1', () => {
314
+ it('should append missing cells to the column(s) to the right from the deleted column', () => {
315
+ const { editorView } = editor(
316
+ doc(
317
+ table()(
318
+ tr(
319
+ td({ colwidth: [110] })(p('a1')),
320
+ td({ colwidth: [120] })(p('a2')),
321
+ td({ colwidth: [130] })(p('a3')),
322
+ td({ colwidth: [140] })(p('a4')),
323
+ ),
324
+ tr(
325
+ td({ colwidth: [110, 120, 130], colspan: 3, rowspan: 2 })(
326
+ p('b1'),
327
+ ),
328
+ td({ colwidth: [140] })(p('b4')),
329
+ ),
330
+ tr(td({ colwidth: [140] })(p('c4'))),
331
+ tr(
332
+ td({ colwidth: [110] })(p('d1')),
333
+ td({ colwidth: [120] })(p('d2')),
334
+ td({ colwidth: [130] })(p('d3')),
335
+ td({ colwidth: [140] })(p('d4')),
336
+ ),
337
+ ),
338
+ ),
339
+ );
340
+ const { state, dispatch } = editorView;
341
+ dispatch(deleteColumns(colsToRect([0], 4))(state.tr));
342
+ expect(editorView.state.doc).toEqualDocument(
343
+ doc(
344
+ table({ localId: TABLE_LOCAL_ID })(
345
+ tr(
346
+ td({ colwidth: [120] })(p('a2')),
347
+ td({ colwidth: [130] })(p('a3')),
348
+ td({ colwidth: [140] })(p('a4')),
349
+ ),
350
+ tr(
351
+ td({ colwidth: [120] })(p('')),
352
+ td({ colwidth: [130] })(p('')),
353
+ td({ colwidth: [140] })(p('b4')),
354
+ ),
355
+ tr(
356
+ td({ colwidth: [120] })(p('')),
357
+ td({ colwidth: [130] })(p('')),
358
+ td({ colwidth: [140] })(p('c4')),
359
+ ),
360
+ tr(
361
+ td({ colwidth: [120] })(p('d2')),
362
+ td({ colwidth: [130] })(p('d3')),
363
+ td({ colwidth: [140] })(p('d4')),
364
+ ),
365
+ ),
366
+ ),
367
+ );
368
+ });
369
+ });
370
+ });
371
+
372
+ describe('when a column-spanning cell overlaps deleted column from the left', () => {
373
+ describe('when this cell has rowspan = 1', () => {
374
+ it('should decrement the colspan of that cell', () => {
375
+ const { editorView } = editor(
376
+ doc(
377
+ table()(
378
+ tr(
379
+ td({ colwidth: [110] })(p('a1')),
380
+ td({ colwidth: [120] })(p('a2')),
381
+ td({ colwidth: [130] })(p('a3')),
382
+ ),
383
+ tr(td({ colwidth: [110, 120, 130], colspan: 3 })(p('b1'))),
384
+ tr(
385
+ td({ colwidth: [110] })(p('c1')),
386
+ td({ colwidth: [120] })(p('c2')),
387
+ td({ colwidth: [130] })(p('c3')),
388
+ ),
389
+ ),
390
+ ),
391
+ );
392
+ const { state, dispatch } = editorView;
393
+ dispatch(deleteColumns(colsToRect([1], 3))(state.tr));
394
+ expect(editorView.state.doc).toEqualDocument(
395
+ doc(
396
+ table({ localId: TABLE_LOCAL_ID })(
397
+ tr(
398
+ td({ colwidth: [110] })(p('a1')),
399
+ td({ colwidth: [130] })(p('a3')),
400
+ ),
401
+ tr(td({ colwidth: [110, 130], colspan: 2 })(p('b1'))),
402
+ tr(
403
+ td({ colwidth: [110] })(p('c1')),
404
+ td({ colwidth: [130] })(p('c3')),
405
+ ),
406
+ ),
407
+ ),
408
+ );
409
+ });
410
+ });
411
+
412
+ describe('when this cell has rowspan > 1', () => {
413
+ it('should decrement the colspan of that cell', () => {
414
+ const { editorView } = editor(
415
+ doc(
416
+ table()(
417
+ tr(
418
+ td({ colwidth: [110] })(p('a1')),
419
+ td({ colwidth: [120] })(p('a2')),
420
+ td({ colwidth: [130] })(p('a3')),
421
+ td({ colwidth: [140] })(p('a4')),
422
+ ),
423
+ tr(
424
+ td({ colwidth: [110, 120, 130], colspan: 3, rowspan: 2 })(
425
+ p('b1'),
426
+ ),
427
+ td({ colwidth: [140] })(p('b4')),
428
+ ),
429
+ tr(td({ colwidth: [140] })(p('c4'))),
430
+ tr(
431
+ td({ colwidth: [110] })(p('d1')),
432
+ td({ colwidth: [120] })(p('d2')),
433
+ td({ colwidth: [130] })(p('d3')),
434
+ td({ colwidth: [140] })(p('d4')),
435
+ ),
436
+ ),
437
+ ),
438
+ );
439
+ const { state, dispatch } = editorView;
440
+ dispatch(deleteColumns(colsToRect([1], 4))(state.tr));
441
+ expect(editorView.state.doc).toEqualDocument(
442
+ doc(
443
+ table({ localId: TABLE_LOCAL_ID })(
444
+ tr(
445
+ td({ colwidth: [110] })(p('a1')),
446
+ td({ colwidth: [130] })(p('a3')),
447
+ td({ colwidth: [140] })(p('a4')),
448
+ ),
449
+ tr(
450
+ td({ colwidth: [110, 130], colspan: 2, rowspan: 2 })(p('b1')),
451
+ td({ colwidth: [140] })(p('b4')),
452
+ ),
453
+ tr(td({ colwidth: [140] })(p('c4'))),
454
+ tr(
455
+ td({ colwidth: [110] })(p('d1')),
456
+ td({ colwidth: [130] })(p('d3')),
457
+ td({ colwidth: [140] })(p('d4')),
458
+ ),
459
+ ),
460
+ ),
461
+ );
462
+ });
463
+ });
464
+ });
465
+
466
+ describe('when a column-spanning cell overlaps two deleted columns from the left', () => {
467
+ it('should decrement the colspan of that cell twice', () => {
468
+ const { editorView } = editor(
469
+ doc(
470
+ table()(
471
+ tr(
472
+ td({ colwidth: [110] })(p('a1')),
473
+ td({ colwidth: [120] })(p('a2')),
474
+ td({ colwidth: [130] })(p('a3')),
475
+ ),
476
+ tr(td({ colwidth: [110, 120, 130], colspan: 3 })(p('b1'))),
477
+ tr(
478
+ td({ colwidth: [110] })(p('c1')),
479
+ td({ colwidth: [120] })(p('c2')),
480
+ td({ colwidth: [130] })(p('c3')),
481
+ ),
482
+ ),
483
+ ),
484
+ );
485
+ const { state, dispatch } = editorView;
486
+ dispatch(deleteColumns(colsToRect([1, 2], 3))(state.tr));
487
+ expect(editorView.state.doc).toEqualDocument(
488
+ doc(
489
+ table({ localId: TABLE_LOCAL_ID })(
490
+ tr(td({ colwidth: [110] })(p('a1'))),
491
+ tr(td({ colwidth: [110] })(p('b1'))),
492
+ tr(td({ colwidth: [110] })(p('c1'))),
493
+ ),
494
+ ),
495
+ );
496
+ });
497
+ });
498
+ });
499
+ });