@atlaskit/editor-plugin-table 0.2.2 → 0.2.3
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 +20 -0
- package/dist/cjs/plugins/table/commands/hover.js +2 -1
- package/dist/cjs/plugins/table/event-handlers.js +5 -12
- package/dist/cjs/plugins/table/index.js +3 -1
- package/dist/cjs/plugins/table/nodeviews/TableComponent.js +15 -5
- package/dist/cjs/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/cjs/plugins/table/pm-plugins/main.js +2 -2
- package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +42 -8
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/cjs/plugins/table/toolbar.js +42 -10
- package/dist/cjs/plugins/table/ui/FloatingContextualButton/index.js +7 -1
- package/dist/cjs/plugins/table/ui/FloatingContextualButton/styles.js +34 -6
- package/dist/cjs/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
- package/dist/cjs/plugins/table/ui/consts.js +4 -4
- package/dist/cjs/plugins/table/ui/ui-styles.js +5 -5
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/plugins/table/commands/hover.js +2 -1
- package/dist/es2019/plugins/table/event-handlers.js +5 -11
- package/dist/es2019/plugins/table/index.js +1 -1
- package/dist/es2019/plugins/table/nodeviews/TableComponent.js +12 -1
- package/dist/es2019/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/es2019/plugins/table/pm-plugins/main.js +2 -2
- package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +31 -4
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/es2019/plugins/table/toolbar.js +43 -12
- package/dist/es2019/plugins/table/ui/FloatingContextualButton/index.js +6 -2
- package/dist/es2019/plugins/table/ui/FloatingContextualButton/styles.js +47 -8
- package/dist/es2019/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/es2019/plugins/table/ui/common-styles.js +9 -9
- package/dist/es2019/plugins/table/ui/consts.js +5 -5
- package/dist/es2019/plugins/table/ui/ui-styles.js +5 -5
- package/dist/es2019/version.json +1 -1
- package/dist/esm/plugins/table/commands/hover.js +2 -1
- package/dist/esm/plugins/table/event-handlers.js +5 -12
- package/dist/esm/plugins/table/index.js +3 -1
- package/dist/esm/plugins/table/nodeviews/TableComponent.js +17 -6
- package/dist/esm/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/esm/plugins/table/pm-plugins/main.js +2 -2
- package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +43 -8
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/esm/plugins/table/toolbar.js +43 -12
- package/dist/esm/plugins/table/ui/FloatingContextualButton/index.js +8 -2
- package/dist/esm/plugins/table/ui/FloatingContextualButton/styles.js +28 -5
- package/dist/esm/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/esm/plugins/table/ui/common-styles.js +1 -1
- package/dist/esm/plugins/table/ui/consts.js +5 -5
- package/dist/esm/plugins/table/ui/ui-styles.js +5 -5
- package/dist/esm/version.json +1 -1
- package/dist/types/plugins/table/event-handlers.d.ts +2 -2
- package/dist/types/plugins/table/pm-plugins/default-table-selection.d.ts +0 -1
- package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +8 -0
- package/dist/types/plugins/table/toolbar.d.ts +3 -2
- package/dist/types/plugins/table/ui/FloatingContextualButton/styles.d.ts +3 -1
- package/dist/types/plugins/table/ui/consts.d.ts +2 -2
- package/package.json +4 -4
- package/src/__tests__/integration/__snapshots__/floating-toolbar.ts.snap +321 -0
- package/src/__tests__/integration/delete-last-column-in-full-width.ts +6 -5
- package/src/__tests__/integration/floating-toolbar.ts +169 -0
- package/src/__tests__/unit/get-toolbar-config.ts +1 -0
- package/src/__tests__/unit/nodeviews/TableComponent.tsx +146 -4
- package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +82 -31
- package/src/__tests__/unit/toolbar.ts +165 -4
- package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +2 -2
- package/src/plugins/table/commands/hover.ts +1 -0
- package/src/plugins/table/event-handlers.ts +3 -16
- package/src/plugins/table/index.tsx +1 -0
- package/src/plugins/table/nodeviews/TableComponent.tsx +10 -2
- package/src/plugins/table/nodeviews/tableCell.tsx +1 -1
- package/src/plugins/table/pm-plugins/default-table-selection.ts +0 -1
- package/src/plugins/table/pm-plugins/main.ts +26 -28
- package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +44 -9
- package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +1 -1
- package/src/plugins/table/toolbar.tsx +60 -13
- package/src/plugins/table/ui/FloatingContextualButton/index.tsx +12 -2
- package/src/plugins/table/ui/FloatingContextualButton/styles.ts +51 -7
- package/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx +3 -0
- package/src/plugins/table/ui/common-styles.ts +24 -9
- package/src/plugins/table/ui/consts.ts +7 -5
- package/src/plugins/table/ui/ui-styles.ts +20 -5
|
@@ -25,9 +25,17 @@ import { canMergeCells } from '../../plugins/table/transforms';
|
|
|
25
25
|
import { Rect } from '@atlaskit/editor-tables/table-map';
|
|
26
26
|
import tablePlugin from '../../plugins/table';
|
|
27
27
|
import { pluginKey } from '../../plugins/table/pm-plugins/plugin-key';
|
|
28
|
+
import { getMergedCellsPositions } from '../../plugins/table/utils';
|
|
29
|
+
import { getNewResizeStateFromSelectedColumns } from '../../plugins/table/pm-plugins/table-resizing/utils/resize-state';
|
|
28
30
|
|
|
29
31
|
jest.mock('@atlaskit/editor-tables/utils');
|
|
30
32
|
jest.mock('../../plugins/table/transforms');
|
|
33
|
+
jest.mock('../../plugins/table/utils');
|
|
34
|
+
jest.mock('../../plugins/table/pm-plugins/table-resizing/utils/resize-state');
|
|
35
|
+
|
|
36
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
37
|
+
() => () => [],
|
|
38
|
+
);
|
|
31
39
|
|
|
32
40
|
const formatMessage: (t: unknown) => string = (id) => 'Lorem ipsum';
|
|
33
41
|
const ctx = { formatMessage };
|
|
@@ -138,13 +146,21 @@ describe('getToolbarMenuConfig', () => {
|
|
|
138
146
|
|
|
139
147
|
describe('getToolbarCellOptionsConfig', () => {
|
|
140
148
|
const createEditor = createProsemirrorEditorFactory();
|
|
141
|
-
const {
|
|
142
|
-
editorView: { state },
|
|
143
|
-
} = createEditor({
|
|
149
|
+
const { editorView } = createEditor({
|
|
144
150
|
doc: doc(table()(row(td()(p('1{cursor}'))))),
|
|
145
|
-
preset: new Preset<LightEditorPlugin>().add(
|
|
151
|
+
preset: new Preset<LightEditorPlugin>().add([
|
|
152
|
+
tablePlugin,
|
|
153
|
+
{
|
|
154
|
+
tableOptions: {
|
|
155
|
+
allowDistributeColumns: true,
|
|
156
|
+
allowColumnResizing: true,
|
|
157
|
+
allowColumnSorting: true,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
]),
|
|
146
161
|
pluginKey,
|
|
147
162
|
});
|
|
163
|
+
const { state } = editorView;
|
|
148
164
|
const getEditorContainerWidth = () => ({ width: 500 });
|
|
149
165
|
|
|
150
166
|
const formatMessage: (t: { id: string }) => string = (message) =>
|
|
@@ -152,6 +168,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
152
168
|
const rect = new Rect(1, 1, 1, 1);
|
|
153
169
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
154
170
|
state,
|
|
171
|
+
editorView,
|
|
155
172
|
rect,
|
|
156
173
|
{
|
|
157
174
|
formatMessage,
|
|
@@ -193,6 +210,21 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
193
210
|
disabled: true,
|
|
194
211
|
});
|
|
195
212
|
expect(items[6]).toMatchObject({
|
|
213
|
+
title: 'fabric.editor.distributeColumns',
|
|
214
|
+
selected: false,
|
|
215
|
+
disabled: true,
|
|
216
|
+
});
|
|
217
|
+
expect(items[7]).toMatchObject({
|
|
218
|
+
title: 'fabric.editor.sortColumnASC',
|
|
219
|
+
selected: false,
|
|
220
|
+
disabled: false,
|
|
221
|
+
});
|
|
222
|
+
expect(items[8]).toMatchObject({
|
|
223
|
+
title: 'fabric.editor.sortColumnDESC',
|
|
224
|
+
selected: false,
|
|
225
|
+
disabled: false,
|
|
226
|
+
});
|
|
227
|
+
expect(items[9]).toMatchObject({
|
|
196
228
|
title: 'fabric.editor.clearCells',
|
|
197
229
|
selected: false,
|
|
198
230
|
disabled: false,
|
|
@@ -206,6 +238,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
206
238
|
//
|
|
207
239
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
208
240
|
state,
|
|
241
|
+
editorView,
|
|
209
242
|
rect,
|
|
210
243
|
{
|
|
211
244
|
formatMessage,
|
|
@@ -230,6 +263,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
230
263
|
//
|
|
231
264
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
232
265
|
state,
|
|
266
|
+
editorView,
|
|
233
267
|
rect,
|
|
234
268
|
{
|
|
235
269
|
formatMessage,
|
|
@@ -246,4 +280,131 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
246
280
|
disabled: false,
|
|
247
281
|
});
|
|
248
282
|
});
|
|
283
|
+
|
|
284
|
+
it('should disable sorting when merged cells are detected', () => {
|
|
285
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
286
|
+
() => [1, 2, 3],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
290
|
+
state,
|
|
291
|
+
editorView,
|
|
292
|
+
rect,
|
|
293
|
+
{
|
|
294
|
+
formatMessage,
|
|
295
|
+
},
|
|
296
|
+
getEditorContainerWidth,
|
|
297
|
+
undefined,
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
301
|
+
const sortItems = items.filter((item) =>
|
|
302
|
+
item.id?.startsWith('editor.table.sortColumn'),
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
const isDisabled = sortItems.every((item) => item.disabled);
|
|
306
|
+
const hasTooltip = sortItems.every((item) => item.tooltip);
|
|
307
|
+
|
|
308
|
+
expect(isDisabled).toBeTruthy();
|
|
309
|
+
expect(hasTooltip).toBeTruthy();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should allow sorting when there are no merged cells detected', () => {
|
|
313
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
314
|
+
() => [],
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
318
|
+
state,
|
|
319
|
+
editorView,
|
|
320
|
+
rect,
|
|
321
|
+
{
|
|
322
|
+
formatMessage,
|
|
323
|
+
},
|
|
324
|
+
getEditorContainerWidth,
|
|
325
|
+
undefined,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
329
|
+
const sortItems = items.filter((item) =>
|
|
330
|
+
item.id?.startsWith('editor.table.sortColumn'),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const isDisabled = sortItems.every((item) => item.disabled);
|
|
334
|
+
const hasTooltip = sortItems.every((item) => item.tooltip);
|
|
335
|
+
|
|
336
|
+
expect(isDisabled).toBeFalsy();
|
|
337
|
+
expect(hasTooltip).toBeFalsy();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should disable distribute columns when no resize detected', () => {
|
|
341
|
+
(
|
|
342
|
+
getNewResizeStateFromSelectedColumns as Function as jest.Mock<{}>
|
|
343
|
+
).mockImplementation(() => ({ changed: false }));
|
|
344
|
+
|
|
345
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
346
|
+
state,
|
|
347
|
+
editorView,
|
|
348
|
+
rect,
|
|
349
|
+
{
|
|
350
|
+
formatMessage,
|
|
351
|
+
},
|
|
352
|
+
getEditorContainerWidth,
|
|
353
|
+
undefined,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
357
|
+
const distributeColumns = items.filter((item) =>
|
|
358
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
362
|
+
expect(isDisabled).toBeTruthy();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should allow distribute columns when resize detected', () => {
|
|
366
|
+
(
|
|
367
|
+
getNewResizeStateFromSelectedColumns as Function as jest.Mock<{}>
|
|
368
|
+
).mockImplementation(() => ({ changed: true }));
|
|
369
|
+
|
|
370
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
371
|
+
state,
|
|
372
|
+
editorView,
|
|
373
|
+
rect,
|
|
374
|
+
{
|
|
375
|
+
formatMessage,
|
|
376
|
+
},
|
|
377
|
+
getEditorContainerWidth,
|
|
378
|
+
undefined,
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
382
|
+
const distributeColumns = items.filter((item) =>
|
|
383
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
387
|
+
expect(isDisabled).toBeFalsy();
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('should disable distribute columns when editorView is undefined', () => {
|
|
391
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
392
|
+
state,
|
|
393
|
+
undefined,
|
|
394
|
+
rect,
|
|
395
|
+
{
|
|
396
|
+
formatMessage,
|
|
397
|
+
},
|
|
398
|
+
getEditorContainerWidth,
|
|
399
|
+
undefined,
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
403
|
+
const distributeColumns = items.filter((item) =>
|
|
404
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
408
|
+
expect(isDisabled).toBeTruthy();
|
|
409
|
+
});
|
|
249
410
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
version https://git-lfs.github.com/spec/v1
|
|
2
|
-
oid sha256:
|
|
3
|
-
size
|
|
2
|
+
oid sha256:5cd747accdc40bfc52f004ff689a3df00173ee2f27d15c68f3a76172c11050fd
|
|
3
|
+
size 13990
|
|
@@ -298,7 +298,6 @@ export const handleMouseMove =
|
|
|
298
298
|
(
|
|
299
299
|
view: EditorView,
|
|
300
300
|
event: Event,
|
|
301
|
-
tableCellOptimization?: boolean,
|
|
302
301
|
elementContentRects?: ElementContentRects,
|
|
303
302
|
) => {
|
|
304
303
|
if (!(event.target instanceof HTMLElement)) {
|
|
@@ -314,7 +313,7 @@ export const handleMouseMove =
|
|
|
314
313
|
const positionColumn =
|
|
315
314
|
getMousePositionHorizontalRelativeByElement(
|
|
316
315
|
event as MouseEvent,
|
|
317
|
-
|
|
316
|
+
false,
|
|
318
317
|
elementContentRects,
|
|
319
318
|
) === 'right'
|
|
320
319
|
? endIndex
|
|
@@ -342,15 +341,11 @@ export const handleMouseMove =
|
|
|
342
341
|
}
|
|
343
342
|
|
|
344
343
|
const { mouseMoveOptimization } = getEditorFeatureFlags();
|
|
345
|
-
// we only want to allow mouseMoveOptimisation when tableCellOptimization is enabled
|
|
346
|
-
// because it relies on tableCell node view that is added via tableCellOptimization
|
|
347
|
-
const useMouseMoveOptimisation =
|
|
348
|
-
tableCellOptimization && mouseMoveOptimization;
|
|
349
344
|
|
|
350
345
|
if (!isResizeHandleDecoration(element) && isCell(element)) {
|
|
351
346
|
const positionColumn = getMousePositionHorizontalRelativeByElement(
|
|
352
347
|
event as MouseEvent,
|
|
353
|
-
|
|
348
|
+
mouseMoveOptimization,
|
|
354
349
|
elementContentRects,
|
|
355
350
|
RESIZE_HANDLE_AREA_DECORATION_GAP,
|
|
356
351
|
);
|
|
@@ -487,7 +482,6 @@ export const whenTableInFocus =
|
|
|
487
482
|
eventHandler: (
|
|
488
483
|
view: EditorView,
|
|
489
484
|
mouseEvent: Event,
|
|
490
|
-
tableCellOptimization?: boolean,
|
|
491
485
|
elementContentRects?: ElementContentRects,
|
|
492
486
|
) => boolean,
|
|
493
487
|
elementContentRects?: ElementContentRects,
|
|
@@ -498,17 +492,10 @@ export const whenTableInFocus =
|
|
|
498
492
|
const isDragging =
|
|
499
493
|
tableResizePluginState && !!tableResizePluginState.dragging;
|
|
500
494
|
const hasTableNode = tablePluginState && tablePluginState.tableNode;
|
|
501
|
-
const tableCellOptimization =
|
|
502
|
-
tablePluginState?.pluginConfig?.tableCellOptimization;
|
|
503
495
|
|
|
504
496
|
if (!hasTableNode || isDragging) {
|
|
505
497
|
return false;
|
|
506
498
|
}
|
|
507
499
|
|
|
508
|
-
return eventHandler(
|
|
509
|
-
view,
|
|
510
|
-
mouseEvent,
|
|
511
|
-
tableCellOptimization,
|
|
512
|
-
elementContentRects,
|
|
513
|
-
);
|
|
500
|
+
return eventHandler(view, mouseEvent, elementContentRects);
|
|
514
501
|
};
|
|
@@ -458,6 +458,7 @@ const tablesPlugin = (options?: TablePluginOptions): EditorPlugin => {
|
|
|
458
458
|
defaultGetEditorContainerWidth,
|
|
459
459
|
options?.editorAnalyticsAPI,
|
|
460
460
|
options?.getEditorFeatureFlags || defaultGetEditorFeatureFlags,
|
|
461
|
+
() => editorViewRef.current,
|
|
461
462
|
)(pluginConfig(options?.tableOptions)),
|
|
462
463
|
},
|
|
463
464
|
};
|
|
@@ -4,6 +4,7 @@ import { Node as PmNode } from 'prosemirror-model';
|
|
|
4
4
|
import { isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
5
5
|
import { EditorView } from 'prosemirror-view';
|
|
6
6
|
import rafSchedule from 'raf-schd';
|
|
7
|
+
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
calcTableWidth,
|
|
@@ -19,7 +20,7 @@ import { getParentNodeWidth } from '@atlaskit/editor-common/node-width';
|
|
|
19
20
|
import type { EditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
20
21
|
import { parsePx } from '@atlaskit/editor-common/utils';
|
|
21
22
|
|
|
22
|
-
import { autoSizeTable } from '../commands';
|
|
23
|
+
import { autoSizeTable, clearHoverSelection } from '../commands';
|
|
23
24
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
24
25
|
import {
|
|
25
26
|
findStickyHeaderForTable,
|
|
@@ -196,7 +197,14 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
componentDidUpdate(prevProps: ComponentProps) {
|
|
199
|
-
const { getNode, isMediaFullscreen, allowColumnResizing } =
|
|
200
|
+
const { view, getNode, isMediaFullscreen, allowColumnResizing } =
|
|
201
|
+
this.props;
|
|
202
|
+
const { isInDanger } = getPluginState(view.state);
|
|
203
|
+
const table = findTable(view.state.selection);
|
|
204
|
+
|
|
205
|
+
if (isInDanger && !table) {
|
|
206
|
+
clearHoverSelection()(view.state, view.dispatch);
|
|
207
|
+
}
|
|
200
208
|
|
|
201
209
|
const { tableOverflowShadowsOptimization } =
|
|
202
210
|
this.props.getEditorFeatureFlags();
|
|
@@ -125,34 +125,32 @@ export const createPlugin = (
|
|
|
125
125
|
})
|
|
126
126
|
: undefined;
|
|
127
127
|
|
|
128
|
-
const tableCellNodeview =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
: {};
|
|
128
|
+
const tableCellNodeview = {
|
|
129
|
+
tableCell: (
|
|
130
|
+
node: ProseMirrorNode,
|
|
131
|
+
view: EditorView,
|
|
132
|
+
getPos: getPosHandler,
|
|
133
|
+
) =>
|
|
134
|
+
new TableCellNodeView(
|
|
135
|
+
node,
|
|
136
|
+
view,
|
|
137
|
+
getPos,
|
|
138
|
+
getEditorFeatureFlags,
|
|
139
|
+
observer,
|
|
140
|
+
),
|
|
141
|
+
tableHeader: (
|
|
142
|
+
node: ProseMirrorNode,
|
|
143
|
+
view: EditorView,
|
|
144
|
+
getPos: getPosHandler,
|
|
145
|
+
) =>
|
|
146
|
+
new TableCellNodeView(
|
|
147
|
+
node,
|
|
148
|
+
view,
|
|
149
|
+
getPos,
|
|
150
|
+
getEditorFeatureFlags,
|
|
151
|
+
observer,
|
|
152
|
+
),
|
|
153
|
+
};
|
|
156
154
|
|
|
157
155
|
// Used to prevent invalid table cell spans being reported more than once per editor/document
|
|
158
156
|
const invalidTableIds: string[] = [];
|
|
@@ -33,19 +33,51 @@ import throttle from 'lodash/throttle';
|
|
|
33
33
|
const HEADER_ROW_SCROLL_THROTTLE_TIMEOUT = 200;
|
|
34
34
|
|
|
35
35
|
// timeout for resetting the scroll class - if it’s too long then users won’t be able to click on the header cells,
|
|
36
|
-
// if too short it would trigger too many dom
|
|
36
|
+
// if too short it would trigger too many dom updates.
|
|
37
37
|
const HEADER_ROW_SCROLL_RESET_DEBOUNCE_TIMEOUT = 400;
|
|
38
38
|
|
|
39
|
+
const anyChildCellMergedAcrossRow = (node: PmNode) =>
|
|
40
|
+
mapChildren(node, (child) => child.attrs.rowspan || 0).some(
|
|
41
|
+
(rowspan) => rowspan > 1,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Compare two table row nodes and return true if the two table rows have a
|
|
46
|
+
* different number of table cells or if table cell row spans are different
|
|
47
|
+
*/
|
|
48
|
+
const rowHasDifferentMergedCells = (prevNode: PmNode, incomingNode: PmNode) => {
|
|
49
|
+
const incomingNodeChildrenRowSpan = mapChildren(
|
|
50
|
+
prevNode,
|
|
51
|
+
(child) => child.attrs.rowspan || 0,
|
|
52
|
+
);
|
|
53
|
+
const currentNodeChildrenRowSpan = mapChildren(
|
|
54
|
+
incomingNode,
|
|
55
|
+
(child) => child.attrs.rowspan || 0,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
incomingNodeChildrenRowSpan.length !== currentNodeChildrenRowSpan.length ||
|
|
60
|
+
currentNodeChildrenRowSpan.some(
|
|
61
|
+
(child, index) => child !== incomingNodeChildrenRowSpan[index],
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check if a given node is a header row with this definition:
|
|
68
|
+
* - all children are tableHeader cells
|
|
69
|
+
* - no table cells have been have merged with other table row cells
|
|
70
|
+
*
|
|
71
|
+
* @param node ProseMirror node
|
|
72
|
+
* @return boolean if it meets definition
|
|
73
|
+
*/
|
|
39
74
|
export const supportedHeaderRow = (node: PmNode) => {
|
|
40
75
|
const allHeaders = mapChildren(
|
|
41
76
|
node,
|
|
42
77
|
(child) => child.type.name === 'tableHeader',
|
|
43
78
|
).every(Boolean);
|
|
44
79
|
|
|
45
|
-
const someMerged =
|
|
46
|
-
node,
|
|
47
|
-
(child) => child.attrs.rowspan || 0,
|
|
48
|
-
).some((rowspan) => rowspan > 1);
|
|
80
|
+
const someMerged = anyChildCellMergedAcrossRow(node);
|
|
49
81
|
|
|
50
82
|
return allHeaders && !someMerged;
|
|
51
83
|
};
|
|
@@ -297,8 +329,8 @@ export class TableRowNodeView implements NodeView {
|
|
|
297
329
|
{ root: this.editorScrollableElement as Element },
|
|
298
330
|
);
|
|
299
331
|
}
|
|
300
|
-
/* paint/update loop */
|
|
301
332
|
|
|
333
|
+
/* paint/update loop */
|
|
302
334
|
previousDomTop: number | undefined;
|
|
303
335
|
previousPadding: number | undefined;
|
|
304
336
|
|
|
@@ -367,7 +399,6 @@ export class TableRowNodeView implements NodeView {
|
|
|
367
399
|
};
|
|
368
400
|
|
|
369
401
|
/* nodeview lifecycle */
|
|
370
|
-
|
|
371
402
|
update(node: PmNode, ..._args: any[]) {
|
|
372
403
|
// do nothing if nodes were identical
|
|
373
404
|
if (node === this.node) {
|
|
@@ -376,11 +407,15 @@ export class TableRowNodeView implements NodeView {
|
|
|
376
407
|
|
|
377
408
|
// see if we're changing into a header row or
|
|
378
409
|
// changing away from one
|
|
379
|
-
const
|
|
380
|
-
if (this.isHeaderRow !==
|
|
410
|
+
const newNodeIsHeaderRow = supportedHeaderRow(node);
|
|
411
|
+
if (this.isHeaderRow !== newNodeIsHeaderRow) {
|
|
381
412
|
return false; // re-create nodeview
|
|
382
413
|
}
|
|
383
414
|
|
|
415
|
+
if (rowHasDifferentMergedCells(this.node, node)) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
384
419
|
// node is different but no need to re-create nodeview
|
|
385
420
|
this.node = node;
|
|
386
421
|
|
|
@@ -33,7 +33,7 @@ export const shrinkColumn = (
|
|
|
33
33
|
selectedColumns?: number[],
|
|
34
34
|
): ResizeState => {
|
|
35
35
|
// can't shrink if columns don't exist
|
|
36
|
-
if (!state.cols[colIndex]
|
|
36
|
+
if (!state.cols[colIndex]) {
|
|
37
37
|
return state;
|
|
38
38
|
}
|
|
39
39
|
// try to shrink dragging column by giving from the column to the right first
|