@atlaskit/editor-plugin-table 0.0.5 → 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.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/plugins/table/commands-with-analytics.js +6 -0
- package/dist/cjs/plugins/table/event-handlers.js +7 -6
- package/dist/cjs/plugins/table/nodeviews/tableCell.js +4 -4
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/cjs/plugins/table/utils/column-controls.js +1 -1
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/plugins/table/commands-with-analytics.js +6 -0
- package/dist/es2019/plugins/table/event-handlers.js +8 -7
- package/dist/es2019/plugins/table/nodeviews/tableCell.js +3 -4
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/es2019/plugins/table/utils/column-controls.js +1 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/plugins/table/commands-with-analytics.js +6 -0
- package/dist/esm/plugins/table/event-handlers.js +8 -7
- package/dist/esm/plugins/table/nodeviews/tableCell.js +3 -4
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/esm/plugins/table/utils/column-controls.js +1 -1
- package/dist/esm/version.json +1 -1
- package/package.json +9 -7
- package/report.api.md +13 -6
- package/src/__tests__/unit/analytics.ts +737 -0
- package/src/__tests__/unit/collab.ts +76 -0
- package/src/__tests__/unit/commands/sort.ts +230 -0
- package/src/__tests__/unit/copy-paste.ts +686 -0
- package/src/__tests__/unit/event-handlers/index.ts +106 -0
- package/src/__tests__/unit/event-handlers.ts +202 -0
- package/src/__tests__/unit/fix-tables.ts +156 -0
- package/src/__tests__/unit/floating-toolbar.ts +95 -0
- package/src/__tests__/unit/handlers.ts +81 -0
- package/src/__tests__/unit/hover-selection.ts +277 -0
- package/src/__tests__/unit/index-with-fake-timers.ts +106 -0
- package/src/__tests__/unit/index.ts +986 -0
- package/src/__tests__/unit/keymap.ts +602 -0
- package/src/__tests__/unit/layout.ts +196 -0
- package/src/__tests__/unit/nodeviews/cell.ts +167 -0
- package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +33 -0
- package/src/__tests__/unit/sort-column.ts +512 -0
- package/src/__tests__/unit/transforms/delete-columns.ts +499 -0
- package/src/__tests__/unit/transforms/delete-rows.ts +557 -0
- package/src/__tests__/unit/transforms/merging.ts +374 -0
- package/src/__tests__/unit/ui/CornerControls.tsx +80 -0
- package/src/__tests__/unit/ui/FloatingContextualButton.tsx +95 -0
- package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +175 -0
- package/src/__tests__/unit/ui/FloatingInsertButton.tsx +266 -0
- package/src/__tests__/unit/ui/RowControls.tsx +301 -0
- package/src/__tests__/unit/ui/TableFloatingControls.tsx +93 -0
- package/src/__tests__/unit/undo-redo.ts +202 -0
- package/src/__tests__/unit/utils/dom.ts +286 -0
- package/src/__tests__/unit/utils/nodes.ts +59 -0
- package/src/__tests__/unit/utils/row-controls.ts +176 -0
- package/src/__tests__/unit/utils/table.ts +93 -0
- package/src/__tests__/unit/utils.ts +652 -0
- package/src/plugins/table/commands-with-analytics.ts +3 -0
- package/src/plugins/table/event-handlers.ts +5 -6
- package/src/plugins/table/nodeviews/tableCell.tsx +5 -4
- package/src/plugins/table/pm-plugins/table-resizing/utils/column-state.ts +1 -1
- package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +6 -2
- package/src/plugins/table/utils/column-controls.ts +1 -1
- package/tmp/api-report-tmp.d.ts +91 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getMousePositionHorizontalRelativeByElement,
|
|
3
|
+
getMousePositionVerticalRelativeByElement,
|
|
4
|
+
} from '../../../plugins/table/utils/dom';
|
|
5
|
+
|
|
6
|
+
describe('table plugin: utils/dom.js', () => {
|
|
7
|
+
let element: HTMLElement;
|
|
8
|
+
let mouseMoveOptimization = false;
|
|
9
|
+
let elementContentRects: any;
|
|
10
|
+
const elementRect: DOMRect = {
|
|
11
|
+
width: 100,
|
|
12
|
+
left: 50,
|
|
13
|
+
height: 100,
|
|
14
|
+
top: 50,
|
|
15
|
+
bottom: 0,
|
|
16
|
+
right: 0,
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
toJSON() {
|
|
20
|
+
return JSON.stringify(this);
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
beforeAll(() => {
|
|
24
|
+
jest.spyOn(HTMLElement.prototype, 'closest').mockImplementation(() => {
|
|
25
|
+
return {
|
|
26
|
+
id: 'table-cell-id',
|
|
27
|
+
} as Element;
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
element = document.createElement('div');
|
|
33
|
+
mouseMoveOptimization = false;
|
|
34
|
+
element.getBoundingClientRect = () => elementRect;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('#getMousePositionHorizontalRelativeByElement', () => {
|
|
38
|
+
describe('when there is a gap of 30px', () => {
|
|
39
|
+
const GAP = 30;
|
|
40
|
+
|
|
41
|
+
describe('and when the mouse is outside of the gap', () => {
|
|
42
|
+
describe('for 1px on the left', () => {
|
|
43
|
+
it('should return null when mouseMoveOptimization is disabled', () => {
|
|
44
|
+
const event = {
|
|
45
|
+
target: element,
|
|
46
|
+
clientX: GAP + elementRect.left + 1,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
expect(
|
|
50
|
+
getMousePositionHorizontalRelativeByElement(
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
event,
|
|
53
|
+
mouseMoveOptimization,
|
|
54
|
+
elementContentRects,
|
|
55
|
+
GAP,
|
|
56
|
+
),
|
|
57
|
+
).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should return null when mouseMoveOptimization is enabled', () => {
|
|
61
|
+
const event = {
|
|
62
|
+
target: element,
|
|
63
|
+
offsetX: GAP + 1,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
mouseMoveOptimization = true;
|
|
67
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
68
|
+
|
|
69
|
+
expect(
|
|
70
|
+
getMousePositionHorizontalRelativeByElement(
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
event,
|
|
73
|
+
mouseMoveOptimization,
|
|
74
|
+
elementContentRects,
|
|
75
|
+
GAP,
|
|
76
|
+
),
|
|
77
|
+
).toBeNull();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('for 1px on the right', () => {
|
|
82
|
+
it('should return null when mouseMoveOptimization is disabled', () => {
|
|
83
|
+
const event = {
|
|
84
|
+
target: element,
|
|
85
|
+
clientX: elementRect.width + elementRect.left - GAP - 1,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
expect(
|
|
89
|
+
getMousePositionHorizontalRelativeByElement(
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
event,
|
|
92
|
+
mouseMoveOptimization,
|
|
93
|
+
elementContentRects,
|
|
94
|
+
GAP,
|
|
95
|
+
),
|
|
96
|
+
).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should return null when mouseMoveOptimization is enabled', () => {
|
|
100
|
+
const event = {
|
|
101
|
+
target: element,
|
|
102
|
+
offsetX: elementRect.width - GAP - 1,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
mouseMoveOptimization = true;
|
|
106
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
107
|
+
|
|
108
|
+
expect(
|
|
109
|
+
getMousePositionHorizontalRelativeByElement(
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
event,
|
|
112
|
+
mouseMoveOptimization,
|
|
113
|
+
elementContentRects,
|
|
114
|
+
GAP,
|
|
115
|
+
),
|
|
116
|
+
).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('and when the mouse is inside of the gap', () => {
|
|
122
|
+
it('should return left when mouseMoveOptimization is disabled', () => {
|
|
123
|
+
const event = {
|
|
124
|
+
target: element,
|
|
125
|
+
clientX: GAP + elementRect.left,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
expect(
|
|
129
|
+
getMousePositionHorizontalRelativeByElement(
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
event,
|
|
132
|
+
mouseMoveOptimization,
|
|
133
|
+
elementContentRects,
|
|
134
|
+
GAP,
|
|
135
|
+
),
|
|
136
|
+
).toBe('left');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should return left when mouseMoveOptimization is enabled', () => {
|
|
140
|
+
const event = {
|
|
141
|
+
target: element,
|
|
142
|
+
offsetX: GAP,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
mouseMoveOptimization = true;
|
|
146
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
147
|
+
|
|
148
|
+
expect(
|
|
149
|
+
getMousePositionHorizontalRelativeByElement(
|
|
150
|
+
// @ts-ignore
|
|
151
|
+
event,
|
|
152
|
+
mouseMoveOptimization,
|
|
153
|
+
elementContentRects,
|
|
154
|
+
GAP,
|
|
155
|
+
),
|
|
156
|
+
).toBe('left');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should return right when mouseMoveOptimization is disabled', () => {
|
|
160
|
+
const event = {
|
|
161
|
+
target: element,
|
|
162
|
+
clientX: elementRect.width + elementRect.left - GAP,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
expect(
|
|
166
|
+
getMousePositionHorizontalRelativeByElement(
|
|
167
|
+
// @ts-ignore
|
|
168
|
+
event,
|
|
169
|
+
mouseMoveOptimization,
|
|
170
|
+
elementContentRects,
|
|
171
|
+
GAP,
|
|
172
|
+
),
|
|
173
|
+
).toBe('right');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should return right when mouseMoveOptimization is enabled', () => {
|
|
177
|
+
const event = {
|
|
178
|
+
target: element,
|
|
179
|
+
offsetX: elementRect.width - GAP,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
mouseMoveOptimization = true;
|
|
183
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
184
|
+
|
|
185
|
+
expect(
|
|
186
|
+
getMousePositionHorizontalRelativeByElement(
|
|
187
|
+
// @ts-ignore
|
|
188
|
+
event,
|
|
189
|
+
mouseMoveOptimization,
|
|
190
|
+
elementContentRects,
|
|
191
|
+
GAP,
|
|
192
|
+
),
|
|
193
|
+
).toBe('right');
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should return left when the mouse is positioned before half of the element and mouseMoveOptimization is disabled', () => {
|
|
199
|
+
const event = {
|
|
200
|
+
target: element,
|
|
201
|
+
clientX: 50,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
// @ts-ignore
|
|
206
|
+
getMousePositionHorizontalRelativeByElement(event),
|
|
207
|
+
).toBe('left');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should return left when the mouse is positioned before half of the element and mouseMoveOptimization is enabled', () => {
|
|
211
|
+
const event = {
|
|
212
|
+
target: element,
|
|
213
|
+
offsetX: 50,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
mouseMoveOptimization = true;
|
|
217
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
218
|
+
|
|
219
|
+
expect(
|
|
220
|
+
getMousePositionHorizontalRelativeByElement(
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
event,
|
|
223
|
+
mouseMoveOptimization,
|
|
224
|
+
elementContentRects,
|
|
225
|
+
),
|
|
226
|
+
).toBe('left');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should return right when the mouse is positioned after half of the element and mouseMoveOptimization is disabled', () => {
|
|
230
|
+
const event = {
|
|
231
|
+
target: element,
|
|
232
|
+
clientX: 101,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
expect(
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
getMousePositionHorizontalRelativeByElement(event),
|
|
238
|
+
).toBe('right');
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should return right when the mouse is positioned after half of the element and mouseMoveOptimization is enabled', () => {
|
|
242
|
+
const event = {
|
|
243
|
+
target: element,
|
|
244
|
+
offsetX: 101,
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
mouseMoveOptimization = true;
|
|
248
|
+
elementContentRects = { 'table-cell-id': { width: 100 } };
|
|
249
|
+
|
|
250
|
+
expect(
|
|
251
|
+
getMousePositionHorizontalRelativeByElement(
|
|
252
|
+
// @ts-ignore
|
|
253
|
+
event,
|
|
254
|
+
mouseMoveOptimization,
|
|
255
|
+
elementContentRects,
|
|
256
|
+
),
|
|
257
|
+
).toBe('right');
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe('#getMousePositionVerticalRelativeByElement', () => {
|
|
262
|
+
it('should return top when the mouse is positioned before half of the element', () => {
|
|
263
|
+
const event = {
|
|
264
|
+
target: element,
|
|
265
|
+
clientY: 50,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
expect(
|
|
269
|
+
// @ts-ignore
|
|
270
|
+
getMousePositionVerticalRelativeByElement(event),
|
|
271
|
+
).toBe('top');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should return bottom when the mouse is positioned before half of the element', () => {
|
|
275
|
+
const event = {
|
|
276
|
+
target: element,
|
|
277
|
+
clientY: 101,
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
expect(
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
getMousePositionVerticalRelativeByElement(event),
|
|
283
|
+
).toBe('bottom');
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
2
|
+
import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
|
|
3
|
+
import {
|
|
4
|
+
doc,
|
|
5
|
+
p,
|
|
6
|
+
table,
|
|
7
|
+
tr,
|
|
8
|
+
th,
|
|
9
|
+
tdEmpty,
|
|
10
|
+
tdCursor,
|
|
11
|
+
thEmpty,
|
|
12
|
+
DocBuilder,
|
|
13
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
14
|
+
import { TablePluginState } from '../../../plugins/table/types';
|
|
15
|
+
import { containsHeaderColumn } from '../../../plugins/table/utils/nodes';
|
|
16
|
+
import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
|
|
17
|
+
|
|
18
|
+
describe('table merging logic', () => {
|
|
19
|
+
const createEditor = createEditorFactory<TablePluginState>();
|
|
20
|
+
|
|
21
|
+
const editor = (doc: DocBuilder) =>
|
|
22
|
+
createEditor({
|
|
23
|
+
doc,
|
|
24
|
+
editorProps: { allowTables: true },
|
|
25
|
+
pluginKey,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('#containsHeaderColumn', () => {
|
|
29
|
+
it('should return true when first col is all tableHeaders', () => {
|
|
30
|
+
const { editorView } = editor(
|
|
31
|
+
doc(
|
|
32
|
+
table()(
|
|
33
|
+
tr(thEmpty, tdCursor, tdEmpty),
|
|
34
|
+
tr(thEmpty, tdEmpty, tdEmpty),
|
|
35
|
+
tr(thEmpty, tdEmpty, tdEmpty),
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const TableWithPos = findTable(editorView.state.selection)!;
|
|
41
|
+
expect(containsHeaderColumn(TableWithPos.node)).toEqual(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return true when first col has a rowspan', () => {
|
|
45
|
+
const { editorView } = editor(
|
|
46
|
+
doc(
|
|
47
|
+
table()(
|
|
48
|
+
tr(thEmpty, tdCursor, tdEmpty),
|
|
49
|
+
tr(th({ rowspan: 2 })(p()), tdEmpty, tdEmpty),
|
|
50
|
+
tr(tdEmpty, tdEmpty),
|
|
51
|
+
),
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const TableWithPos = findTable(editorView.state.selection)!;
|
|
56
|
+
expect(containsHeaderColumn(TableWithPos.node)).toEqual(true);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
2
|
+
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
3
|
+
import { uuid } from '@atlaskit/adf-schema';
|
|
4
|
+
|
|
5
|
+
import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
|
|
6
|
+
import {
|
|
7
|
+
doc,
|
|
8
|
+
p,
|
|
9
|
+
table,
|
|
10
|
+
tr as row,
|
|
11
|
+
th,
|
|
12
|
+
td,
|
|
13
|
+
DocBuilder,
|
|
14
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
15
|
+
import { TablePluginState } from '../../../plugins/table/types';
|
|
16
|
+
import { copyPreviousRow } from '../../../plugins/table/utils/row-controls';
|
|
17
|
+
import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
|
|
18
|
+
|
|
19
|
+
const TABLE_LOCAL_ID = 'test-table-local-id';
|
|
20
|
+
|
|
21
|
+
describe('table plugin: utils/row-controls.js', () => {
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
uuid.setStatic(TABLE_LOCAL_ID);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterAll(() => {
|
|
27
|
+
uuid.setStatic(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const createEditor = createEditorFactory<TablePluginState>();
|
|
31
|
+
const editor = (doc: DocBuilder) =>
|
|
32
|
+
createEditor({
|
|
33
|
+
doc,
|
|
34
|
+
editorProps: { allowTables: true },
|
|
35
|
+
pluginKey,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('#copyPreviousRow', () => {
|
|
39
|
+
describe('complex table', () => {
|
|
40
|
+
it('should accept rowIndex zero', () => {
|
|
41
|
+
const { editorView } = editor(
|
|
42
|
+
doc(
|
|
43
|
+
table()(
|
|
44
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
45
|
+
row(th()(p('b1')), td()(p('b3')), td()(p('b3'))),
|
|
46
|
+
),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
const { state } = editorView;
|
|
50
|
+
expect(() => {
|
|
51
|
+
copyPreviousRow(state.schema)(0)(state.tr);
|
|
52
|
+
}).toThrow(
|
|
53
|
+
/Row Index less or equal 0 isn't not allowed since there is not a previous to copy/,
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should copy column header', () => {
|
|
58
|
+
const { editorView } = editor(
|
|
59
|
+
doc(
|
|
60
|
+
table()(
|
|
61
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
62
|
+
row(th()(p('b1')), td()(p('b3')), td()(p('b3'))),
|
|
63
|
+
),
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
const { state } = editorView;
|
|
67
|
+
const newTr = copyPreviousRow(state.schema)(2)(state.tr);
|
|
68
|
+
expect(newTr.doc).toEqualDocument(
|
|
69
|
+
doc(
|
|
70
|
+
table({ localId: TABLE_LOCAL_ID })(
|
|
71
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
72
|
+
row(th()(p('b1')), td()(p('b3')), td()(p('b3'))),
|
|
73
|
+
row(th()(p('')), td()(p('')), td()(p(''))),
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should copy column header with colspan', () => {
|
|
80
|
+
const { editorView } = editor(
|
|
81
|
+
doc(
|
|
82
|
+
table()(
|
|
83
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
84
|
+
row(th({ colspan: 2 })(p('b1')), td()(p('b3'))),
|
|
85
|
+
),
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
const { state } = editorView;
|
|
89
|
+
const newTr = copyPreviousRow(state.schema)(2)(state.tr);
|
|
90
|
+
expect(newTr.doc).toEqualDocument(
|
|
91
|
+
doc(
|
|
92
|
+
table({ localId: TABLE_LOCAL_ID })(
|
|
93
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
94
|
+
row(th({ colspan: 2 })(p('b1')), td()(p('b3'))),
|
|
95
|
+
row(th({ colspan: 2 })(p('')), td()(p(''))),
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should keep colspan', () => {
|
|
102
|
+
const { editorView } = editor(
|
|
103
|
+
doc(
|
|
104
|
+
table()(
|
|
105
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
106
|
+
row(td({ colspan: 2 })(p('b1')), td()(p('b3'))),
|
|
107
|
+
),
|
|
108
|
+
),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const { state } = editorView;
|
|
112
|
+
const newTr = copyPreviousRow(state.schema)(2)(state.tr);
|
|
113
|
+
expect(newTr.doc).toEqualDocument(
|
|
114
|
+
doc(
|
|
115
|
+
table({ localId: TABLE_LOCAL_ID })(
|
|
116
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
117
|
+
row(td({ colspan: 2 })(p('b1')), td()(p('b3'))),
|
|
118
|
+
row(td({ colspan: 2 })(p('')), td()(p(''))),
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should copy background colors and does not expand previous rowspan', () => {
|
|
125
|
+
const { editorView } = editor(
|
|
126
|
+
doc(
|
|
127
|
+
table()(
|
|
128
|
+
row(th()(p('{<>}a1')), th()(p('a2')), th()(p('a3'))),
|
|
129
|
+
row(
|
|
130
|
+
td()(p('b1')),
|
|
131
|
+
td()(p('b2')),
|
|
132
|
+
td({ background: '#eeeaaa', rowspan: 4 })(p('b3')),
|
|
133
|
+
),
|
|
134
|
+
row(td()(p('c1')), td()(p('c2'))),
|
|
135
|
+
row(
|
|
136
|
+
td()(p('d1')),
|
|
137
|
+
td({ background: '#fffaaa', rowspan: 3 })(p('d2')),
|
|
138
|
+
),
|
|
139
|
+
row(td()(p('XXXX'))),
|
|
140
|
+
row(td()(p('e1')), td()(p('e2'))),
|
|
141
|
+
row(td()(p('f1')), td()(p('f2')), td()(p('f3'))),
|
|
142
|
+
),
|
|
143
|
+
),
|
|
144
|
+
);
|
|
145
|
+
const { state } = editorView;
|
|
146
|
+
|
|
147
|
+
const newTr = copyPreviousRow(state.schema)(5)(state.tr);
|
|
148
|
+
|
|
149
|
+
const newTable = findTable(newTr.selection);
|
|
150
|
+
const map = TableMap.get(newTable!.node);
|
|
151
|
+
expect(map.problems).toBeNull();
|
|
152
|
+
expect(newTr.doc).toEqualDocument(
|
|
153
|
+
doc(
|
|
154
|
+
table({ localId: TABLE_LOCAL_ID })(
|
|
155
|
+
row(th()(p('a1')), th()(p('a2')), th()(p('a3'))),
|
|
156
|
+
row(
|
|
157
|
+
td()(p('b1')),
|
|
158
|
+
td()(p('b2')),
|
|
159
|
+
td({ background: '#eeeaaa', rowspan: 4 })(p('b3')),
|
|
160
|
+
),
|
|
161
|
+
row(td()(p('c1')), td()(p('c2'))),
|
|
162
|
+
row(
|
|
163
|
+
td()(p('d1')),
|
|
164
|
+
td({ background: '#fffaaa', rowspan: 4 })(p('d2')),
|
|
165
|
+
),
|
|
166
|
+
row(td()(p('XXXX'))),
|
|
167
|
+
row(td()(p('')), td({ background: '#eeeaaa' })(p(''))),
|
|
168
|
+
row(td()(p('e1')), td()(p('e2'))),
|
|
169
|
+
row(td()(p('f1')), td()(p('f2')), td()(p('f3'))),
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
doc,
|
|
3
|
+
p,
|
|
4
|
+
table,
|
|
5
|
+
td,
|
|
6
|
+
th,
|
|
7
|
+
tr as row,
|
|
8
|
+
tdEmpty,
|
|
9
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
10
|
+
import { getCellsInRow } from '@atlaskit/editor-tables/utils';
|
|
11
|
+
import { getMergedCellsPositions } from '../../../plugins/table/utils';
|
|
12
|
+
import { createEditorState } from '@atlaskit/editor-test-helpers/create-editor-state';
|
|
13
|
+
|
|
14
|
+
describe('table utils', () => {
|
|
15
|
+
describe('#getMergedCellsPositions', () => {
|
|
16
|
+
describe('when the table has not merged cells', () => {
|
|
17
|
+
it('should returns an emppty array', () => {
|
|
18
|
+
const { tr } = createEditorState(
|
|
19
|
+
doc(
|
|
20
|
+
table()(
|
|
21
|
+
row(th({})(p('Number{<>}'))),
|
|
22
|
+
row(td({})(p('10{<>}'))),
|
|
23
|
+
row(td({})(p('0'))),
|
|
24
|
+
row(td({})(p('5'))),
|
|
25
|
+
),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
expect(getMergedCellsPositions(tr)).toHaveLength(0);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('when the table has merged cells in columns', () => {
|
|
34
|
+
it('should returns the positions', () => {
|
|
35
|
+
const { tr } = createEditorState(
|
|
36
|
+
doc(
|
|
37
|
+
table()(
|
|
38
|
+
row(
|
|
39
|
+
th({})(p('Number{<>}')),
|
|
40
|
+
td({})(p('10{<>}')),
|
|
41
|
+
tdEmpty,
|
|
42
|
+
tdEmpty,
|
|
43
|
+
),
|
|
44
|
+
row(td({})(p('10{<>}')), td({})(p('10{<>}')), tdEmpty, tdEmpty),
|
|
45
|
+
row(td({ colspan: 2 })(p('0')), td({ colspan: 2 })(p('1'))),
|
|
46
|
+
row(td({})(p('5')), td({})(p('10{<>}')), tdEmpty, tdEmpty),
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
const cells = getCellsInRow(2)(tr.selection)!;
|
|
51
|
+
const tableStart = 1;
|
|
52
|
+
|
|
53
|
+
expect(getMergedCellsPositions(tr)).toEqual([
|
|
54
|
+
cells[0].pos - tableStart,
|
|
55
|
+
cells[1].pos - tableStart,
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('when the table has merged cells in rows', () => {
|
|
61
|
+
it('should returns the positions', () => {
|
|
62
|
+
const { tr } = createEditorState(
|
|
63
|
+
doc(
|
|
64
|
+
table()(
|
|
65
|
+
row(
|
|
66
|
+
th({})(p('Number{<>}')),
|
|
67
|
+
td({})(p('10{<>}')),
|
|
68
|
+
tdEmpty,
|
|
69
|
+
tdEmpty,
|
|
70
|
+
),
|
|
71
|
+
row(td({})(p('10{<>}')), td({})(p('10{<>}')), tdEmpty, tdEmpty),
|
|
72
|
+
row(
|
|
73
|
+
td({ rowspan: 2 })(p('0')),
|
|
74
|
+
tdEmpty,
|
|
75
|
+
tdEmpty,
|
|
76
|
+
td({ rowspan: 2 })(p('1')),
|
|
77
|
+
),
|
|
78
|
+
row(tdEmpty, tdEmpty),
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const cells = getCellsInRow(2)(tr.selection)!;
|
|
84
|
+
const tableStart = 1;
|
|
85
|
+
|
|
86
|
+
expect(getMergedCellsPositions(tr)).toEqual([
|
|
87
|
+
cells[0].pos - tableStart,
|
|
88
|
+
cells[3].pos - tableStart,
|
|
89
|
+
]);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|