@atlaskit/editor-plugin-table 1.2.0 → 1.2.2
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 +26 -0
- package/dist/cjs/i18n/en.js +43 -0
- package/dist/cjs/i18n/en_GB.js +43 -0
- package/dist/cjs/plugins/table/index.js +2 -1
- package/dist/cjs/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
- package/dist/cjs/plugins/table/nodeviews/TableComponent.js +18 -3
- package/dist/cjs/plugins/table/nodeviews/table.js +7 -0
- package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/misc.js +3 -38
- package/dist/cjs/plugins/table/transforms/delete-rows.js +1 -1
- package/dist/cjs/plugins/table/transforms/index.js +3 -3
- package/dist/cjs/plugins/table/transforms/merge.js +39 -54
- package/dist/cjs/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +16 -3
- package/dist/cjs/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
- package/dist/cjs/plugins/table/ui/common-styles.js +2 -2
- package/dist/cjs/plugins/table/utils/row-controls.js +3 -2
- package/dist/cjs/types/i18n.js +5 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/i18n/en.js +36 -0
- package/dist/es2019/i18n/en_GB.js +36 -0
- package/dist/es2019/plugins/table/index.js +2 -1
- package/dist/es2019/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
- package/dist/es2019/plugins/table/nodeviews/TableComponent.js +22 -3
- package/dist/es2019/plugins/table/nodeviews/table.js +7 -0
- package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/misc.js +1 -37
- package/dist/es2019/plugins/table/transforms/delete-rows.js +2 -2
- package/dist/es2019/plugins/table/transforms/index.js +1 -1
- package/dist/es2019/plugins/table/transforms/merge.js +39 -43
- package/dist/es2019/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +18 -4
- package/dist/es2019/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
- package/dist/es2019/plugins/table/ui/common-styles.js +21 -1
- package/dist/es2019/plugins/table/utils/row-controls.js +3 -2
- package/dist/es2019/types/i18n.js +1 -0
- package/dist/es2019/version.json +1 -1
- package/dist/esm/i18n/en.js +36 -0
- package/dist/esm/i18n/en_GB.js +36 -0
- package/dist/esm/plugins/table/index.js +2 -1
- package/dist/esm/plugins/table/nodeviews/OverflowShadowsObserver.js +13 -26
- package/dist/esm/plugins/table/nodeviews/TableComponent.js +18 -3
- package/dist/esm/plugins/table/nodeviews/table.js +7 -0
- package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +32 -17
- package/dist/esm/plugins/table/pm-plugins/table-resizing/event-handlers.js +1 -5
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/misc.js +1 -35
- package/dist/esm/plugins/table/transforms/delete-rows.js +2 -2
- package/dist/esm/plugins/table/transforms/index.js +1 -1
- package/dist/esm/plugins/table/transforms/merge.js +38 -53
- package/dist/esm/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +17 -4
- package/dist/esm/plugins/table/ui/FloatingContextualMenu/index.js +6 -3
- package/dist/esm/plugins/table/ui/common-styles.js +2 -2
- package/dist/esm/plugins/table/utils/row-controls.js +3 -2
- package/dist/esm/types/i18n.js +1 -0
- package/dist/esm/version.json +1 -1
- package/dist/types/i18n/en.d.ts +35 -0
- package/dist/types/i18n/en_GB.d.ts +35 -0
- package/dist/types/plugins/table/nodeviews/OverflowShadowsObserver.d.ts +4 -5
- package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +1 -0
- package/dist/types/plugins/table/nodeviews/__mocks__/OverflowShadowsObserver.d.ts +3 -3
- package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +2 -2
- package/dist/types/plugins/table/pm-plugins/table-resizing/utils/misc.d.ts +1 -2
- package/dist/types/plugins/table/transforms/index.d.ts +1 -1
- package/dist/types/plugins/table/transforms/merge.d.ts +1 -1
- package/dist/types/plugins/table/types.d.ts +2 -0
- package/dist/types/plugins/table/ui/FloatingContextualMenu/ContextualMenu.d.ts +2 -1
- package/dist/types/plugins/table/ui/FloatingContextualMenu/index.d.ts +3 -2
- package/dist/types/types/i18n.d.ts +5 -0
- package/package.json +10 -9
- package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.ts +130 -0
- package/src/__tests__/integration/horizontal-scroll-shadows.ts +199 -0
- package/src/__tests__/integration/horizontal-scroll.ts +4 -9
- package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +4 -2
- package/src/__tests__/integration/sticky-header.ts +61 -1
- package/src/__tests__/unit/commands/insert.ts +8 -8
- package/src/__tests__/unit/commands/sort.ts +4 -0
- package/src/__tests__/unit/commands.ts +2 -0
- package/src/__tests__/unit/index.ts +2 -0
- package/src/__tests__/unit/keymap.ts +4 -2
- package/src/__tests__/unit/layout.ts +2 -0
- package/src/__tests__/unit/nodeviews/OverflowShadowsObserver.ts +20 -11
- package/src/__tests__/unit/nodeviews/cell.ts +14 -0
- package/src/__tests__/unit/pm-plugins/main-with-allow-collapse.ts +2 -0
- package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +2 -2
- package/src/__tests__/unit/transforms/delete-rows.ts +45 -0
- package/src/__tests__/unit/ui/ContextualMenu.tsx +2 -0
- package/src/__tests__/unit/ui/FloatingContextualMenu.tsx +1 -0
- package/src/__tests__/unit/utils/collapse.ts +4 -1
- package/src/i18n/en.ts +36 -0
- package/src/i18n/en_GB.ts +36 -0
- package/src/plugins/table/index.tsx +4 -0
- package/src/plugins/table/nodeviews/OverflowShadowsObserver.ts +24 -40
- package/src/plugins/table/nodeviews/TableComponent.tsx +20 -4
- package/src/plugins/table/nodeviews/__mocks__/OverflowShadowsObserver.ts +3 -3
- package/src/plugins/table/nodeviews/table.tsx +12 -0
- package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +40 -23
- package/src/plugins/table/pm-plugins/table-resizing/event-handlers.ts +1 -9
- package/src/plugins/table/pm-plugins/table-resizing/utils/misc.ts +1 -57
- package/src/plugins/table/transforms/delete-rows.ts +2 -2
- package/src/plugins/table/transforms/index.ts +1 -1
- package/src/plugins/table/transforms/merge.ts +41 -43
- package/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx +21 -2
- package/src/plugins/table/ui/FloatingContextualMenu/index.tsx +8 -1
- package/src/plugins/table/ui/common-styles.ts +21 -0
- package/src/plugins/table/utils/row-controls.ts +3 -2
- package/src/types/i18n.ts +5 -0
- package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +0 -130
|
@@ -55,7 +55,6 @@ import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
|
|
|
55
55
|
|
|
56
56
|
import memoizeOne from 'memoize-one';
|
|
57
57
|
import { OverflowShadowsObserver } from './OverflowShadowsObserver';
|
|
58
|
-
import { getParentWidthWithoutPadding } from '../pm-plugins/table-resizing/utils/misc';
|
|
59
58
|
|
|
60
59
|
const isIE11 = browser.ie_version === 11;
|
|
61
60
|
const NOOP = () => undefined;
|
|
@@ -226,9 +225,8 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
226
225
|
}
|
|
227
226
|
|
|
228
227
|
if (this.overflowShadowsObserver) {
|
|
229
|
-
this.overflowShadowsObserver.
|
|
228
|
+
this.overflowShadowsObserver.observeShadowSentinels(
|
|
230
229
|
this.state.stickyHeader?.sticky,
|
|
231
|
-
containsHeaderRow(getNode()),
|
|
232
230
|
);
|
|
233
231
|
}
|
|
234
232
|
}
|
|
@@ -288,6 +286,17 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
288
286
|
this.setState({ [shadowKey]: value });
|
|
289
287
|
};
|
|
290
288
|
|
|
289
|
+
private createShadowSentinels = (table: HTMLTableElement | null) => {
|
|
290
|
+
if (table) {
|
|
291
|
+
const shadowSentinelLeft = document.createElement('span');
|
|
292
|
+
shadowSentinelLeft.className = ClassName.TABLE_SHADOW_SENTINEL_LEFT;
|
|
293
|
+
const shadowSentinelRight = document.createElement('span');
|
|
294
|
+
shadowSentinelRight.className = ClassName.TABLE_SHADOW_SENTINEL_RIGHT;
|
|
295
|
+
table.prepend(shadowSentinelLeft);
|
|
296
|
+
table.prepend(shadowSentinelRight);
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
291
300
|
onStickyState = (state: StickyPluginState) => {
|
|
292
301
|
const { tableOverflowShadowsOptimization } =
|
|
293
302
|
this.props.getEditorFeatureFlags();
|
|
@@ -441,6 +450,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
441
450
|
const tableElement = elem.querySelector('table');
|
|
442
451
|
if (tableElement !== this.table) {
|
|
443
452
|
this.table = tableElement;
|
|
453
|
+
this.createShadowSentinels(this.table);
|
|
444
454
|
}
|
|
445
455
|
}
|
|
446
456
|
}}
|
|
@@ -520,6 +530,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
520
530
|
if (!tableOverflowShadowsOptimization) {
|
|
521
531
|
this.updateShadows();
|
|
522
532
|
}
|
|
533
|
+
|
|
534
|
+
if (this.wrapper.scrollLeft === 0) {
|
|
535
|
+
this.setState({ [ShadowEvent.SHOW_BEFORE_SHADOW]: false });
|
|
536
|
+
} else {
|
|
537
|
+
this.setState({ [ShadowEvent.SHOW_BEFORE_SHADOW]: true });
|
|
538
|
+
}
|
|
523
539
|
};
|
|
524
540
|
|
|
525
541
|
private handleTableResizing = () => {
|
|
@@ -689,7 +705,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
689
705
|
options && options.isFullWidthModeEnabled,
|
|
690
706
|
);
|
|
691
707
|
|
|
692
|
-
return
|
|
708
|
+
return parentNodeWith;
|
|
693
709
|
};
|
|
694
710
|
|
|
695
711
|
private updateParentWidth = (width?: number) => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { OverridableMock } from './OverridableMock';
|
|
2
2
|
|
|
3
3
|
export class OverflowShadowsObserver extends OverridableMock {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
leftShadowSentinel: HTMLElement | null = null;
|
|
5
|
+
rightShadowSentinel: HTMLElement | null = null;
|
|
6
6
|
constructor(...inputs: any[]) {
|
|
7
7
|
super(...inputs);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
observeShadowSentinels = this.getMock('observeShadowSentinels');
|
|
11
11
|
updateStickyShadows = this.getMock('updateStickyShadows');
|
|
12
12
|
dispose = this.getMock('dispose');
|
|
13
13
|
}
|
|
@@ -225,6 +225,18 @@ export default class TableView extends ReactNodeView<Props> {
|
|
|
225
225
|
return false;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// ED-16668
|
|
229
|
+
// Do not remove this fixes an issue with windows firefox that relates to
|
|
230
|
+
// the addition of the shadow sentinels
|
|
231
|
+
if (
|
|
232
|
+
type === 'selection' &&
|
|
233
|
+
nodeName?.toUpperCase() === 'TABLE' &&
|
|
234
|
+
(firstChild?.nodeName.toUpperCase() === 'COLGROUP' ||
|
|
235
|
+
firstChild?.nodeName.toUpperCase() === 'SPAN')
|
|
236
|
+
) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
228
240
|
return true;
|
|
229
241
|
}
|
|
230
242
|
|
|
@@ -170,7 +170,7 @@ export class TableRowNodeView implements NodeView {
|
|
|
170
170
|
this.topPosEditorElement = getTop(this.editorScrollableElement);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
this.eventDispatcher.on('widthPlugin', this.
|
|
173
|
+
this.eventDispatcher.on('widthPlugin', this.updateStickyHeaderWidth);
|
|
174
174
|
|
|
175
175
|
this.eventDispatcher.on(
|
|
176
176
|
(tablePluginKey as any).key,
|
|
@@ -209,7 +209,7 @@ export class TableRowNodeView implements NodeView {
|
|
|
209
209
|
this.editorScrollableElement.removeEventListener('scroll', this.onScroll);
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
this.eventDispatcher.off('widthPlugin', this.
|
|
212
|
+
this.eventDispatcher.off('widthPlugin', this.updateStickyHeaderWidth);
|
|
213
213
|
this.eventDispatcher.off(
|
|
214
214
|
(tablePluginKey as any).key,
|
|
215
215
|
this.onTablePluginState,
|
|
@@ -235,6 +235,9 @@ export class TableRowNodeView implements NodeView {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
this.resizeObserver.observe(this.dom);
|
|
238
|
+
if (this.editorScrollableElement) {
|
|
239
|
+
this.resizeObserver.observe(this.editorScrollableElement as HTMLElement);
|
|
240
|
+
}
|
|
238
241
|
|
|
239
242
|
window.requestAnimationFrame(() => {
|
|
240
243
|
// we expect tree to be defined after animation frame
|
|
@@ -268,22 +271,31 @@ export class TableRowNodeView implements NodeView {
|
|
|
268
271
|
}
|
|
269
272
|
const { table } = this.tree;
|
|
270
273
|
entries.forEach((entry) => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
: (entry.target as HTMLElement).offsetHeight;
|
|
274
|
-
|
|
274
|
+
// On resize of the parent scroll element we need to adjust the width
|
|
275
|
+
// of the sticky header
|
|
275
276
|
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// So we adding this check to allow a 1px difference.
|
|
279
|
-
Math.abs(newHeight - (this.stickyRowHeight || 0)) >
|
|
280
|
-
stickyHeaderBorderBottomWidth
|
|
277
|
+
entry.target.className ===
|
|
278
|
+
(this.editorScrollableElement as HTMLElement)?.className
|
|
281
279
|
) {
|
|
282
|
-
this.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
280
|
+
this.updateStickyHeaderWidth();
|
|
281
|
+
} else {
|
|
282
|
+
const newHeight = entry.contentRect
|
|
283
|
+
? entry.contentRect.height
|
|
284
|
+
: (entry.target as HTMLElement).offsetHeight;
|
|
285
|
+
|
|
286
|
+
if (
|
|
287
|
+
this.sentinels.bottom &&
|
|
288
|
+
// When the table header is sticky, it would be taller by a 1px (border-bottom),
|
|
289
|
+
// So we adding this check to allow a 1px difference.
|
|
290
|
+
Math.abs(newHeight - (this.stickyRowHeight || 0)) >
|
|
291
|
+
stickyHeaderBorderBottomWidth
|
|
292
|
+
) {
|
|
293
|
+
this.stickyRowHeight = newHeight;
|
|
294
|
+
this.sentinels.bottom.style.bottom = `${
|
|
295
|
+
tableScrollbarOffset + stickyRowOffsetTop + newHeight
|
|
296
|
+
}px`;
|
|
297
|
+
updateTableMargin(table);
|
|
298
|
+
}
|
|
287
299
|
}
|
|
288
300
|
});
|
|
289
301
|
});
|
|
@@ -309,7 +321,8 @@ export class TableRowNodeView implements NodeView {
|
|
|
309
321
|
(entry.rootBounds?.bottom || 0) < entry.boundingClientRect.bottom;
|
|
310
322
|
|
|
311
323
|
if (!entry.isIntersecting && !sentinelIsBelowScrollArea) {
|
|
312
|
-
this.tree &&
|
|
324
|
+
this.tree &&
|
|
325
|
+
this.makeHeaderRowSticky(this.tree, entry.rootBounds?.top);
|
|
313
326
|
} else {
|
|
314
327
|
table && this.makeRowHeaderNotSticky(table);
|
|
315
328
|
}
|
|
@@ -325,7 +338,8 @@ export class TableRowNodeView implements NodeView {
|
|
|
325
338
|
if (table && !entry.isIntersecting && sentinelIsAboveScrollArea) {
|
|
326
339
|
this.makeRowHeaderNotSticky(table);
|
|
327
340
|
} else if (entry.isIntersecting && sentinelIsAboveScrollArea) {
|
|
328
|
-
this.tree &&
|
|
341
|
+
this.tree &&
|
|
342
|
+
this.makeHeaderRowSticky(this.tree, entry?.rootBounds?.top);
|
|
329
343
|
}
|
|
330
344
|
}
|
|
331
345
|
});
|
|
@@ -549,7 +563,7 @@ export class TableRowNodeView implements NodeView {
|
|
|
549
563
|
}, 0);
|
|
550
564
|
};
|
|
551
565
|
|
|
552
|
-
|
|
566
|
+
updateStickyHeaderWidth = () => {
|
|
553
567
|
// table width might have changed, sync that back to sticky row
|
|
554
568
|
const tree = this.tree;
|
|
555
569
|
if (!tree) {
|
|
@@ -591,7 +605,7 @@ export class TableRowNodeView implements NodeView {
|
|
|
591
605
|
return false;
|
|
592
606
|
};
|
|
593
607
|
|
|
594
|
-
makeHeaderRowSticky = (tree: TableDOMElements) => {
|
|
608
|
+
makeHeaderRowSticky = (tree: TableDOMElements, scrollTop?: number) => {
|
|
595
609
|
// If header row height is more than 50% of viewport height don't do this
|
|
596
610
|
if (this.stickyRowHeight && this.stickyRowHeight > window.innerHeight / 2) {
|
|
597
611
|
return;
|
|
@@ -607,10 +621,13 @@ export class TableRowNodeView implements NodeView {
|
|
|
607
621
|
}
|
|
608
622
|
|
|
609
623
|
const currentTableTop = this.getCurrentTableTop(tree);
|
|
624
|
+
|
|
625
|
+
if (!scrollTop) {
|
|
626
|
+
scrollTop = getTop(this.editorScrollableElement);
|
|
627
|
+
}
|
|
628
|
+
|
|
610
629
|
const domTop =
|
|
611
|
-
currentTableTop > 0
|
|
612
|
-
? this.topPosEditorElement
|
|
613
|
-
: this.topPosEditorElement + currentTableTop;
|
|
630
|
+
currentTableTop > 0 ? scrollTop : scrollTop + currentTableTop;
|
|
614
631
|
|
|
615
632
|
if (!this.isSticky) {
|
|
616
633
|
syncStickyRowToTable(table);
|
|
@@ -31,7 +31,6 @@ import type {
|
|
|
31
31
|
GetEditorContainerWidth,
|
|
32
32
|
GetEditorFeatureFlags,
|
|
33
33
|
} from '@atlaskit/editor-common/types';
|
|
34
|
-
import { getParentWidthWithoutPadding } from './utils/misc';
|
|
35
34
|
|
|
36
35
|
export const handleMouseDown = (
|
|
37
36
|
view: EditorView,
|
|
@@ -68,15 +67,8 @@ export const handleMouseDown = (
|
|
|
68
67
|
const containerWidth = getEditorContainerWidth();
|
|
69
68
|
const parentWidth = getParentNodeWidth(start, state, containerWidth);
|
|
70
69
|
|
|
71
|
-
// TODO - refactor this logic into getParentNodeWidth() in editor-common [ED-16718]
|
|
72
|
-
const parentActualWidth = getParentWidthWithoutPadding(
|
|
73
|
-
parentWidth,
|
|
74
|
-
start,
|
|
75
|
-
state,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
70
|
let maxSize =
|
|
79
|
-
|
|
71
|
+
parentWidth ||
|
|
80
72
|
getLayoutSize(
|
|
81
73
|
dom.getAttribute('data-layout') as TableLayout,
|
|
82
74
|
containerWidth.width,
|
|
@@ -21,8 +21,6 @@ import { Node as PMNode } from 'prosemirror-model';
|
|
|
21
21
|
import { EditorState } from 'prosemirror-state';
|
|
22
22
|
import type { GetEditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
23
23
|
import { getParentNodeWidth } from '@atlaskit/editor-common/node-width';
|
|
24
|
-
import { gridSize } from '@atlaskit/theme/constants';
|
|
25
|
-
import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
|
|
26
24
|
|
|
27
25
|
export const tableLayoutToSize: Record<string, number> = {
|
|
28
26
|
default: akEditorDefaultLayoutWidth,
|
|
@@ -124,15 +122,7 @@ export const getTableMaxWidth = ({
|
|
|
124
122
|
const containerWidth = getEditorContainerWidth();
|
|
125
123
|
const parentWidth = getParentNodeWidth(tableStart, state, containerWidth);
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
const parentActualWidth = getParentWidthWithoutPadding(
|
|
129
|
-
parentWidth,
|
|
130
|
-
tableStart,
|
|
131
|
-
state,
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
let maxWidth =
|
|
135
|
-
parentActualWidth || getLayoutSize(layout, containerWidth.width, {});
|
|
125
|
+
let maxWidth = parentWidth || getLayoutSize(layout, containerWidth.width, {});
|
|
136
126
|
|
|
137
127
|
if (table.attrs.isNumberColumnEnabled) {
|
|
138
128
|
maxWidth -= akEditorTableNumberColumnWidth;
|
|
@@ -140,49 +130,3 @@ export const getTableMaxWidth = ({
|
|
|
140
130
|
|
|
141
131
|
return maxWidth;
|
|
142
132
|
};
|
|
143
|
-
|
|
144
|
-
export const getParentWidthWithoutPadding = (
|
|
145
|
-
parentWidth: number,
|
|
146
|
-
tableStartPos: number,
|
|
147
|
-
state: EditorState,
|
|
148
|
-
) => {
|
|
149
|
-
const node = getNestedParentNode(tableStartPos, state);
|
|
150
|
-
if (!node) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const { schema } = state;
|
|
155
|
-
|
|
156
|
-
if (node.type === schema.nodes.expand) {
|
|
157
|
-
// padding
|
|
158
|
-
parentWidth -= gridSize() * 2;
|
|
159
|
-
// gutter offset
|
|
160
|
-
parentWidth += gridSize() * 1.5 * 2;
|
|
161
|
-
// padding right
|
|
162
|
-
parentWidth -= gridSize();
|
|
163
|
-
// padding left
|
|
164
|
-
parentWidth -= gridSize() * 4 - gridSize() / 2;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return parentWidth;
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// copy of getNestedParentNode() from packages/editor/editor-common/src/node-width/index.ts
|
|
171
|
-
// to be removed later when we will move getParentWidthWithoutPadding() logic to editor-common
|
|
172
|
-
const getNestedParentNode = (
|
|
173
|
-
tablePos: number,
|
|
174
|
-
state: EditorState,
|
|
175
|
-
): PMNode | null => {
|
|
176
|
-
if (tablePos === undefined) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const $pos = state.doc.resolve(tablePos);
|
|
181
|
-
const parent = findParentNodeOfTypeClosestToPos($pos, [
|
|
182
|
-
state.schema.nodes.bodiedExtension,
|
|
183
|
-
state.schema.nodes.layoutSection,
|
|
184
|
-
state.schema.nodes.expand,
|
|
185
|
-
]);
|
|
186
|
-
|
|
187
|
-
return parent ? parent.node : null;
|
|
188
|
-
};
|
|
@@ -5,7 +5,7 @@ import { findTable } from '@atlaskit/editor-tables/utils';
|
|
|
5
5
|
|
|
6
6
|
import { CellAttributes } from '@atlaskit/adf-schema';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { mergeEmptyColumns } from './merge';
|
|
9
9
|
import { setMeta } from './metadata';
|
|
10
10
|
|
|
11
11
|
export const deleteRows =
|
|
@@ -125,7 +125,7 @@ export const deleteRows =
|
|
|
125
125
|
rows,
|
|
126
126
|
table.node.marks,
|
|
127
127
|
);
|
|
128
|
-
const fixedTable =
|
|
128
|
+
const fixedTable = mergeEmptyColumns(newTable);
|
|
129
129
|
if (fixedTable === null) {
|
|
130
130
|
return setMeta({ type: 'DELETE_ROWS', problem: 'REMOVE_EMPTY_COLUMNS' })(
|
|
131
131
|
tr,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { mergeCells, canMergeCells, removeEmptyColumns } from './merge';
|
|
2
1
|
export { fireAnalytics, fixTables, fixAutoSizedTable } from './fix-tables';
|
|
2
|
+
export { mergeCells, canMergeCells, mergeEmptyColumns } from './merge';
|
|
3
3
|
export { deleteColumns } from './delete-columns';
|
|
4
4
|
export { deleteRows } from './delete-rows';
|
|
5
5
|
export { updateColumnWidths } from './column-width';
|
|
@@ -131,7 +131,8 @@ export function mergeCells(tr: Transaction): Transaction {
|
|
|
131
131
|
rows,
|
|
132
132
|
table.node.marks,
|
|
133
133
|
);
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
const fixedTable = mergeEmptyColumns(newTable);
|
|
135
136
|
if (fixedTable === null) {
|
|
136
137
|
return setMeta({ type: 'MERGE_CELLS', problem: 'REMOVE_EMPTY_COLUMNS' })(
|
|
137
138
|
tr,
|
|
@@ -227,77 +228,74 @@ function cellsOverlapRectangle({ width, height, map }: TableMap, rect: Rect) {
|
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
// returns an array of numbers, each number indicates the minimum colSpan in each column
|
|
230
|
-
function
|
|
231
|
+
function getEmptyColumnIndexes(table: PMNode): Set<number> {
|
|
231
232
|
const map = TableMap.get(table);
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
const emptyColumnIndexes = new Set<number>();
|
|
234
|
+
|
|
235
|
+
// Loop throuh each column
|
|
236
|
+
for (let colIndex = 0; colIndex < map.width; colIndex++) {
|
|
237
|
+
// Get the cells in each row for this column
|
|
238
|
+
const cellPositions = map.cellsInRect({
|
|
235
239
|
left: colIndex,
|
|
236
240
|
right: colIndex + 1,
|
|
237
241
|
top: 0,
|
|
238
242
|
bottom: map.height,
|
|
239
243
|
});
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return cell.attrs.colspan;
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
const minColspan = Math.min(...colspans);
|
|
248
|
-
// only care about the case when the next column is invisible
|
|
249
|
-
if (!minColspans[colIndex + 1]) {
|
|
250
|
-
minColspans[colIndex] = minColspan;
|
|
251
|
-
} else {
|
|
252
|
-
minColspans[colIndex] = 1;
|
|
253
|
-
}
|
|
244
|
+
|
|
245
|
+
// If no cells exist in that column it is empty
|
|
246
|
+
if (!cellPositions.length) {
|
|
247
|
+
emptyColumnIndexes.add(colIndex);
|
|
254
248
|
}
|
|
255
249
|
}
|
|
256
250
|
|
|
257
|
-
return
|
|
251
|
+
return emptyColumnIndexes;
|
|
258
252
|
}
|
|
259
253
|
|
|
260
|
-
export function
|
|
254
|
+
export function mergeEmptyColumns(table: PMNode): PMNode | null {
|
|
255
|
+
const rows: PMNode[] = [];
|
|
261
256
|
const map = TableMap.get(table);
|
|
262
|
-
const
|
|
263
|
-
|
|
257
|
+
const emptyColumnIndexes = getEmptyColumnIndexes(table);
|
|
258
|
+
|
|
259
|
+
// We don't need to remove any so return early.
|
|
260
|
+
if (emptyColumnIndexes.size === 0) {
|
|
264
261
|
return table;
|
|
265
262
|
}
|
|
266
|
-
|
|
263
|
+
|
|
267
264
|
for (let rowIndex = 0; rowIndex < map.height; rowIndex++) {
|
|
268
265
|
const cellsByCols: Record<string, PMNode> = {};
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
|
|
267
|
+
// Work backwards so that calculating colwidths is easier with Array.slice
|
|
268
|
+
for (let colIndex = map.width - 1; colIndex >= 0; colIndex--) {
|
|
272
269
|
const cellPos = map.map[colIndex + rowIndex * map.width];
|
|
273
270
|
const rect = map.findCell(cellPos);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
271
|
+
let cell = cellsByCols[rect.left] || table.nodeAt(cellPos);
|
|
272
|
+
|
|
273
|
+
if (rect.top !== rowIndex) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// If this column is empty, we want to decrement the colspan of its corresponding
|
|
278
|
+
// cell as this column is being "merged"
|
|
279
|
+
if (emptyColumnIndexes.has(colIndex)) {
|
|
280
|
+
const { colspan, colwidth } = cell.attrs;
|
|
281
|
+
|
|
282
|
+
if (colspan > 1) {
|
|
283
|
+
cell = cell.type.createChecked(
|
|
283
284
|
{
|
|
284
285
|
...cell.attrs,
|
|
285
|
-
colspan,
|
|
286
|
+
colspan: colspan - 1,
|
|
286
287
|
colwidth: colwidth ? colwidth.slice(0, colspan) : null,
|
|
287
288
|
},
|
|
288
289
|
cell.content,
|
|
289
290
|
cell.marks,
|
|
290
291
|
);
|
|
291
|
-
cellsByCols[rect.left] = newCell;
|
|
292
|
-
} else {
|
|
293
|
-
cellsByCols[rect.left] = cell;
|
|
294
292
|
}
|
|
295
293
|
}
|
|
294
|
+
|
|
295
|
+
cellsByCols[rect.left] = cell;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
const rowCells
|
|
299
|
-
(col) => cellsByCols[col],
|
|
300
|
-
);
|
|
298
|
+
const rowCells = Object.values(cellsByCols);
|
|
301
299
|
const row = table.child(rowIndex);
|
|
302
300
|
if (row) {
|
|
303
301
|
rows.push(row.type.createChecked(row.attrs, rowCells, row.marks));
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '@atlaskit/editor-common/keymaps';
|
|
19
19
|
import {
|
|
20
20
|
ColorPalette,
|
|
21
|
+
backgroundPaletteTooltipMessages,
|
|
21
22
|
cellBackgroundColorPalette,
|
|
22
23
|
} from '@atlaskit/editor-common/ui-color';
|
|
23
24
|
import { DropdownMenuSharedCssClassName } from '@atlaskit/editor-common/styles';
|
|
@@ -32,7 +33,10 @@ import { cellColourPreviewStyles } from './styles';
|
|
|
32
33
|
import { closestElement } from '@atlaskit/editor-common/utils';
|
|
33
34
|
|
|
34
35
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
35
|
-
import type {
|
|
36
|
+
import type {
|
|
37
|
+
GetEditorContainerWidth,
|
|
38
|
+
GetEditorFeatureFlags,
|
|
39
|
+
} from '@atlaskit/editor-common/types';
|
|
36
40
|
|
|
37
41
|
import type { MenuItem } from '@atlaskit/editor-common/ui-menu';
|
|
38
42
|
type DropdownItem = MenuItem & {
|
|
@@ -131,6 +135,7 @@ export interface Props {
|
|
|
131
135
|
offset?: Array<number>;
|
|
132
136
|
editorAnalyticsAPI?: EditorAnalyticsAPI;
|
|
133
137
|
getEditorContainerWidth: GetEditorContainerWidth;
|
|
138
|
+
getEditorFeatureFlags: GetEditorFeatureFlags;
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
export interface State {
|
|
@@ -209,9 +214,11 @@ export class ContextualMenu extends Component<
|
|
|
209
214
|
selectionRect,
|
|
210
215
|
intl: { formatMessage },
|
|
211
216
|
editorView,
|
|
217
|
+
getEditorFeatureFlags,
|
|
212
218
|
} = this.props;
|
|
213
219
|
const items: any[] = [];
|
|
214
220
|
const { isSubmenuOpen } = this.state;
|
|
221
|
+
const { useSomewhatSemanticTextColorNames } = getEditorFeatureFlags();
|
|
215
222
|
// TargetCellPosition could be outdated: https://product-fabric.atlassian.net/browse/ED-8129
|
|
216
223
|
const {
|
|
217
224
|
targetCellPosition,
|
|
@@ -239,9 +246,21 @@ export class ContextualMenu extends Component<
|
|
|
239
246
|
>
|
|
240
247
|
<ColorPalette
|
|
241
248
|
cols={7}
|
|
242
|
-
palette={cellBackgroundColorPalette}
|
|
243
249
|
onClick={this.setColor}
|
|
244
250
|
selectedColor={background}
|
|
251
|
+
paletteOptions={{
|
|
252
|
+
palette: cellBackgroundColorPalette,
|
|
253
|
+
paletteColorTooltipMessages:
|
|
254
|
+
backgroundPaletteTooltipMessages,
|
|
255
|
+
// We did not want to create new FF or update
|
|
256
|
+
// useSomewhatSemanticTextColorNames name
|
|
257
|
+
// because it is temporary and require extra work.
|
|
258
|
+
// So even though it says text color names,
|
|
259
|
+
// we are going to use for all color pickers
|
|
260
|
+
// such as text, background and table charts.
|
|
261
|
+
showSomewhatSemanticTooltips:
|
|
262
|
+
useSomewhatSemanticTextColorNames,
|
|
263
|
+
}}
|
|
245
264
|
/>
|
|
246
265
|
</div>
|
|
247
266
|
)}
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
import { tablePopupStyles } from './styles';
|
|
24
24
|
import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
25
25
|
|
|
26
|
-
import type {
|
|
26
|
+
import type {
|
|
27
|
+
GetEditorContainerWidth,
|
|
28
|
+
GetEditorFeatureFlags,
|
|
29
|
+
} from '@atlaskit/editor-common/types';
|
|
27
30
|
import ContextualMenu from './ContextualMenu';
|
|
28
31
|
|
|
29
32
|
// offset of the contextual menu dropdown
|
|
@@ -46,6 +49,7 @@ export interface Props {
|
|
|
46
49
|
editorView: EditorView;
|
|
47
50
|
isOpen: boolean;
|
|
48
51
|
getEditorContainerWidth: GetEditorContainerWidth;
|
|
52
|
+
getEditorFeatureFlags: GetEditorFeatureFlags;
|
|
49
53
|
targetCellPosition?: number;
|
|
50
54
|
mountPoint?: HTMLElement;
|
|
51
55
|
boundariesElement?: HTMLElement;
|
|
@@ -63,6 +67,7 @@ const FloatingContextualMenu = ({
|
|
|
63
67
|
pluginConfig,
|
|
64
68
|
editorAnalyticsAPI,
|
|
65
69
|
getEditorContainerWidth,
|
|
70
|
+
getEditorFeatureFlags,
|
|
66
71
|
}: Props) => {
|
|
67
72
|
// TargetCellPosition could be outdated: https://product-fabric.atlassian.net/browse/ED-8129
|
|
68
73
|
const { targetCellPosition } = getPluginState(editorView.state);
|
|
@@ -103,6 +108,7 @@ const FloatingContextualMenu = ({
|
|
|
103
108
|
zIndex={akEditorFloatingOverlapPanelZIndex}
|
|
104
109
|
forcePlacement={true}
|
|
105
110
|
offset={[-7, 0]}
|
|
111
|
+
stick={true}
|
|
106
112
|
>
|
|
107
113
|
<div css={tablePopupStyles}>
|
|
108
114
|
<ContextualMenu
|
|
@@ -120,6 +126,7 @@ const FloatingContextualMenu = ({
|
|
|
120
126
|
boundariesElement={boundariesElement}
|
|
121
127
|
editorAnalyticsAPI={editorAnalyticsAPI}
|
|
122
128
|
getEditorContainerWidth={getEditorContainerWidth}
|
|
129
|
+
getEditorFeatureFlags={getEditorFeatureFlags}
|
|
123
130
|
/>
|
|
124
131
|
</div>
|
|
125
132
|
</Popup>
|
|
@@ -113,6 +113,22 @@ const sentinelStyles = `.${ClassName.TABLE_CONTAINER} {
|
|
|
113
113
|
}
|
|
114
114
|
}`;
|
|
115
115
|
|
|
116
|
+
const shadowSentinelStyles = `
|
|
117
|
+
.${ClassName.TABLE_SHADOW_SENTINEL_LEFT},
|
|
118
|
+
.${ClassName.TABLE_SHADOW_SENTINEL_RIGHT} {
|
|
119
|
+
position: absolute;
|
|
120
|
+
top: 0;
|
|
121
|
+
height: 100%;
|
|
122
|
+
width: 1px;
|
|
123
|
+
visibility: hidden;
|
|
124
|
+
}
|
|
125
|
+
.${ClassName.TABLE_SHADOW_SENTINEL_LEFT} {
|
|
126
|
+
left: 0;
|
|
127
|
+
}
|
|
128
|
+
.${ClassName.TABLE_SHADOW_SENTINEL_RIGHT} {
|
|
129
|
+
right: 0;
|
|
130
|
+
}
|
|
131
|
+
`;
|
|
116
132
|
// previous styles to add spacing to numbered lists with
|
|
117
133
|
// large item markers (e.g. 101, 102, ...) when nested inside tables
|
|
118
134
|
const listLargeNumericMarkersOldStyles = `
|
|
@@ -624,6 +640,8 @@ export const tableStyles = (
|
|
|
624
640
|
border-top: none;
|
|
625
641
|
// 1px border width offset added here to prevent unwanted overflow and scolling - ED-16212
|
|
626
642
|
margin-right: -1px;
|
|
643
|
+
// Allows better positioning for the shadow sentinels - ED-16668
|
|
644
|
+
position: relative;
|
|
627
645
|
|
|
628
646
|
> tbody > tr {
|
|
629
647
|
white-space: pre-wrap;
|
|
@@ -717,6 +735,7 @@ export const tableStyles = (
|
|
|
717
735
|
padding-bottom: 0px;
|
|
718
736
|
/* fixes gap cursor height */
|
|
719
737
|
overflow: auto;
|
|
738
|
+
overflow-y: hidden;
|
|
720
739
|
position: relative;
|
|
721
740
|
}
|
|
722
741
|
}
|
|
@@ -740,6 +759,8 @@ export const tableStyles = (
|
|
|
740
759
|
${props?.featureFlags?.restartNumberedLists
|
|
741
760
|
? ``
|
|
742
761
|
: listLargeNumericMarkersOldStyles}
|
|
762
|
+
|
|
763
|
+
${shadowSentinelStyles}
|
|
743
764
|
`;
|
|
744
765
|
|
|
745
766
|
export const tableFullPageEditorStyles = css`
|
|
@@ -22,8 +22,9 @@ export interface RowParams {
|
|
|
22
22
|
|
|
23
23
|
export const getRowHeights = (tableRef: HTMLTableElement): number[] => {
|
|
24
24
|
const heights: number[] = [];
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const tableBody = tableRef.querySelector('tbody');
|
|
26
|
+
if (tableBody) {
|
|
27
|
+
const rows = tableBody.childNodes;
|
|
27
28
|
for (let i = 0, count = rows.length; i < count; i++) {
|
|
28
29
|
const row = rows[i] as HTMLTableRowElement;
|
|
29
30
|
heights[i] = row.getBoundingClientRect().height + 1;
|