@atlaskit/editor-plugin-table 7.5.5 → 7.5.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 +13 -0
- package/dist/cjs/commands/selection.js +23 -1
- package/dist/cjs/event-handlers.js +25 -9
- package/dist/cjs/nodeviews/OverflowShadowsObserver.js +24 -15
- package/dist/cjs/nodeviews/TableCell.js +5 -30
- package/dist/cjs/nodeviews/TableComponent.js +96 -41
- package/dist/cjs/nodeviews/TableContainer.js +19 -17
- package/dist/cjs/nodeviews/TableResizer.js +1 -1
- package/dist/cjs/plugin.js +2 -3
- package/dist/cjs/pm-plugins/main.js +3 -18
- package/dist/cjs/pm-plugins/sticky-headers/types.js +1 -5
- package/dist/cjs/pm-plugins/table-resizing/utils/colgroup.js +3 -7
- package/dist/cjs/pm-plugins/table-resizing/utils/misc.js +11 -1
- package/dist/cjs/pm-plugins/table-resizing/utils/resize-state.js +22 -23
- package/dist/cjs/pm-plugins/table-resizing/utils/scale-table.js +2 -2
- package/dist/cjs/pm-plugins/table-selection-keymap.js +3 -0
- package/dist/cjs/ui/TableFloatingColumnControls/index.js +8 -48
- package/dist/cjs/ui/TableFloatingControls/index.js +113 -223
- package/dist/cjs/utils/column-controls.js +5 -5
- package/dist/cjs/utils/dom.js +13 -15
- package/dist/es2019/commands/selection.js +22 -0
- package/dist/es2019/event-handlers.js +25 -9
- package/dist/es2019/nodeviews/OverflowShadowsObserver.js +24 -15
- package/dist/es2019/nodeviews/TableCell.js +1 -24
- package/dist/es2019/nodeviews/TableComponent.js +69 -31
- package/dist/es2019/nodeviews/TableContainer.js +16 -18
- package/dist/es2019/nodeviews/TableResizer.js +1 -1
- package/dist/es2019/plugin.js +2 -3
- package/dist/es2019/pm-plugins/main.js +3 -18
- package/dist/es2019/pm-plugins/sticky-headers/types.js +0 -1
- package/dist/es2019/pm-plugins/table-resizing/utils/colgroup.js +3 -7
- package/dist/es2019/pm-plugins/table-resizing/utils/misc.js +10 -0
- package/dist/es2019/pm-plugins/table-resizing/utils/resize-state.js +21 -22
- package/dist/es2019/pm-plugins/table-resizing/utils/scale-table.js +2 -2
- package/dist/es2019/pm-plugins/table-selection-keymap.js +5 -2
- package/dist/es2019/ui/TableFloatingColumnControls/index.js +5 -27
- package/dist/es2019/ui/TableFloatingControls/index.js +119 -193
- package/dist/es2019/utils/column-controls.js +6 -6
- package/dist/es2019/utils/dom.js +13 -15
- package/dist/esm/commands/selection.js +22 -0
- package/dist/esm/event-handlers.js +25 -9
- package/dist/esm/nodeviews/OverflowShadowsObserver.js +24 -15
- package/dist/esm/nodeviews/TableCell.js +5 -30
- package/dist/esm/nodeviews/TableComponent.js +96 -41
- package/dist/esm/nodeviews/TableContainer.js +20 -18
- package/dist/esm/nodeviews/TableResizer.js +1 -1
- package/dist/esm/plugin.js +2 -3
- package/dist/esm/pm-plugins/main.js +3 -18
- package/dist/esm/pm-plugins/sticky-headers/types.js +0 -1
- package/dist/esm/pm-plugins/table-resizing/utils/colgroup.js +3 -7
- package/dist/esm/pm-plugins/table-resizing/utils/misc.js +10 -0
- package/dist/esm/pm-plugins/table-resizing/utils/resize-state.js +23 -24
- package/dist/esm/pm-plugins/table-resizing/utils/scale-table.js +2 -2
- package/dist/esm/pm-plugins/table-selection-keymap.js +5 -2
- package/dist/esm/ui/TableFloatingColumnControls/index.js +8 -48
- package/dist/esm/ui/TableFloatingControls/index.js +113 -224
- package/dist/esm/utils/column-controls.js +6 -6
- package/dist/esm/utils/dom.js +13 -15
- package/dist/types/commands/selection.d.ts +1 -0
- package/dist/types/event-handlers.d.ts +3 -4
- package/dist/types/nodeviews/OverflowShadowsObserver.d.ts +3 -1
- package/dist/types/nodeviews/TableCell.d.ts +1 -5
- package/dist/types/nodeviews/TableComponent.d.ts +4 -0
- package/dist/types/nodeviews/TableContainer.d.ts +4 -2
- package/dist/types/pm-plugins/table-resizing/utils/misc.d.ts +1 -0
- package/dist/types/types.d.ts +0 -3
- package/dist/types/ui/TableFloatingColumnControls/index.d.ts +2 -1
- package/dist/types/ui/TableFloatingControls/index.d.ts +5 -22
- package/dist/types/utils/dom.d.ts +10 -2
- package/dist/types-ts4.5/commands/selection.d.ts +1 -0
- package/dist/types-ts4.5/event-handlers.d.ts +3 -4
- package/dist/types-ts4.5/nodeviews/OverflowShadowsObserver.d.ts +3 -1
- package/dist/types-ts4.5/nodeviews/TableCell.d.ts +1 -5
- package/dist/types-ts4.5/nodeviews/TableComponent.d.ts +4 -0
- package/dist/types-ts4.5/nodeviews/TableContainer.d.ts +4 -2
- package/dist/types-ts4.5/pm-plugins/table-resizing/utils/misc.d.ts +1 -0
- package/dist/types-ts4.5/types.d.ts +0 -3
- package/dist/types-ts4.5/ui/TableFloatingColumnControls/index.d.ts +2 -1
- package/dist/types-ts4.5/ui/TableFloatingControls/index.d.ts +5 -22
- package/dist/types-ts4.5/utils/dom.d.ts +10 -2
- package/package.json +8 -6
- package/src/commands/selection.ts +33 -0
- package/src/event-handlers.ts +105 -103
- package/src/nodeviews/OverflowShadowsObserver.ts +32 -21
- package/src/nodeviews/TableCell.ts +0 -26
- package/src/nodeviews/TableComponent.tsx +81 -34
- package/src/nodeviews/TableContainer.tsx +19 -25
- package/src/nodeviews/TableResizer.tsx +1 -4
- package/src/plugin.tsx +5 -4
- package/src/pm-plugins/main.ts +3 -22
- package/src/pm-plugins/table-resizing/utils/colgroup.ts +3 -6
- package/src/pm-plugins/table-resizing/utils/misc.ts +13 -0
- package/src/pm-plugins/table-resizing/utils/resize-state.ts +22 -28
- package/src/pm-plugins/table-resizing/utils/scale-table.ts +3 -10
- package/src/pm-plugins/table-selection-keymap.ts +10 -0
- package/src/types.ts +0 -4
- package/src/ui/TableFloatingColumnControls/index.tsx +5 -29
- package/src/ui/TableFloatingControls/index.tsx +155 -241
- package/src/utils/column-controls.ts +5 -6
- package/src/utils/dom.ts +12 -19
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import rafSchedule from 'raf-schd';
|
|
2
|
+
|
|
1
3
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
2
4
|
|
|
3
5
|
import { TableCssClassName as ClassName, ShadowEvent } from '../types';
|
|
@@ -82,11 +84,8 @@ export class OverflowShadowsObserver {
|
|
|
82
84
|
if (!stickyCell) {
|
|
83
85
|
return;
|
|
84
86
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
this.stickyRowHeight = newStickyRowHeight;
|
|
88
|
-
this.updateStickyShadows(this.stickyRowHeight);
|
|
89
|
-
}
|
|
87
|
+
|
|
88
|
+
this.updateStickyShadows();
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
private getStickyCell() {
|
|
@@ -96,8 +95,14 @@ export class OverflowShadowsObserver {
|
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
observeShadowSentinels = (isSticky?: boolean) => {
|
|
98
|
+
if (this.isSticky === isSticky) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
99
102
|
this.isSticky = !!isSticky;
|
|
100
103
|
|
|
104
|
+
// reset height
|
|
105
|
+
this.stickyRowHeight = 0;
|
|
101
106
|
// update sticky shadows
|
|
102
107
|
this.updateStickyShadowsHeightIfChanged();
|
|
103
108
|
|
|
@@ -126,7 +131,7 @@ export class OverflowShadowsObserver {
|
|
|
126
131
|
* e.g. bounds on an IntersectionObserverEntry, otherwise proceed with
|
|
127
132
|
* reading it from sticky cell
|
|
128
133
|
*/
|
|
129
|
-
updateStickyShadows = (stickyRowHeight?: number) => {
|
|
134
|
+
updateStickyShadows = rafSchedule((stickyRowHeight?: number) => {
|
|
130
135
|
if (!this.isSticky) {
|
|
131
136
|
return;
|
|
132
137
|
}
|
|
@@ -134,21 +139,27 @@ export class OverflowShadowsObserver {
|
|
|
134
139
|
if (!stickyCell || !this.wrapper?.parentElement) {
|
|
135
140
|
return;
|
|
136
141
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
142
|
+
|
|
143
|
+
// Reflow Warning! - stickyCell.clientHeight
|
|
144
|
+
const newStickyRowHeight = stickyRowHeight || stickyCell.clientHeight + 1;
|
|
145
|
+
|
|
146
|
+
if (newStickyRowHeight !== this.stickyRowHeight) {
|
|
147
|
+
this.stickyRowHeight = newStickyRowHeight;
|
|
148
|
+
const heightStyleOrCompute = `${newStickyRowHeight}px`;
|
|
149
|
+
// Use getElementsByClassName here for a live node list to capture
|
|
150
|
+
// sticky shadows
|
|
151
|
+
const liveRightShadows =
|
|
152
|
+
this.wrapper?.parentElement?.getElementsByClassName(
|
|
153
|
+
`${ClassName.TABLE_RIGHT_SHADOW}`,
|
|
154
|
+
);
|
|
155
|
+
const liveLeftShadows =
|
|
156
|
+
this.wrapper?.parentElement?.getElementsByClassName(
|
|
157
|
+
`${ClassName.TABLE_LEFT_SHADOW}`,
|
|
158
|
+
);
|
|
159
|
+
updateShadowListForStickyStyles(heightStyleOrCompute, liveLeftShadows);
|
|
160
|
+
updateShadowListForStickyStyles(heightStyleOrCompute, liveRightShadows);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
152
163
|
|
|
153
164
|
dispose() {
|
|
154
165
|
if (this.tableIntersectionObserver) {
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import uuid from 'uuid';
|
|
2
|
-
|
|
3
1
|
import type { CellDomAttrs } from '@atlaskit/adf-schema';
|
|
4
2
|
import { getCellAttrs, getCellDomAttrs } from '@atlaskit/adf-schema';
|
|
5
3
|
import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
|
|
6
4
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
7
5
|
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
8
6
|
|
|
9
|
-
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
10
|
-
|
|
11
7
|
import TableNodeView from './TableNodeViewBase';
|
|
12
8
|
|
|
13
9
|
const DEFAULT_COL_SPAN = 1;
|
|
@@ -22,26 +18,10 @@ export default class TableCell
|
|
|
22
18
|
view: EditorView,
|
|
23
19
|
getPos: () => number | undefined,
|
|
24
20
|
eventDispatcher: EventDispatcher,
|
|
25
|
-
private readonly observer?: ResizeObserver,
|
|
26
21
|
) {
|
|
27
22
|
super(node, view, getPos, eventDispatcher);
|
|
28
|
-
|
|
29
|
-
const { pluginConfig, isDragAndDropEnabled } = getPluginState(view.state);
|
|
30
|
-
|
|
31
|
-
this.isStickyHeaderEnabled = !!pluginConfig.stickyHeaders;
|
|
32
|
-
this.isDragAndDropEnabled = !!isDragAndDropEnabled;
|
|
33
|
-
|
|
34
|
-
if (observer) {
|
|
35
|
-
this.contentDOM.id = uuid();
|
|
36
|
-
observer.observe(this.contentDOM);
|
|
37
|
-
}
|
|
38
23
|
}
|
|
39
24
|
|
|
40
|
-
// @ts-ignore
|
|
41
|
-
private isStickyHeaderEnabled: boolean;
|
|
42
|
-
// @ts-ignore
|
|
43
|
-
private isDragAndDropEnabled: boolean;
|
|
44
|
-
|
|
45
25
|
update(node: PMNode) {
|
|
46
26
|
const didUpdate = this.updateNodeView(node);
|
|
47
27
|
if (didUpdate) {
|
|
@@ -50,12 +30,6 @@ export default class TableCell
|
|
|
50
30
|
return didUpdate;
|
|
51
31
|
}
|
|
52
32
|
|
|
53
|
-
destroy() {
|
|
54
|
-
if (this.observer) {
|
|
55
|
-
this.observer.unobserve(this.contentDOM);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
33
|
private updateNodeView(node: PMNode) {
|
|
60
34
|
if (this.node.type !== node.type) {
|
|
61
35
|
return false;
|
|
@@ -84,6 +84,12 @@ const isIE11 = browser.ie_version === 11;
|
|
|
84
84
|
// To make sure we capture the last update, we use setTimeout.
|
|
85
85
|
const initialOverflowCaptureTimeroutDelay = 300;
|
|
86
86
|
|
|
87
|
+
// This is a hard switch for controlling whether the overflow analytics should be dispatched. There has been 6months of data
|
|
88
|
+
// already collected which we could use but have not. This has been disabled rather then removed entirely in the event that
|
|
89
|
+
// the current collected data becomes stale and we want to start collecting fresh data again in future.
|
|
90
|
+
// PLEASE NOTE: that the current way this alaytics has been configured WILL cause reflows to occur. This is why the has been disabled.
|
|
91
|
+
const isOverflowAnalyticsEnabled = false;
|
|
92
|
+
|
|
87
93
|
export interface ComponentProps {
|
|
88
94
|
view: EditorView;
|
|
89
95
|
getNode: () => PmNode;
|
|
@@ -114,6 +120,8 @@ interface TableState {
|
|
|
114
120
|
stickyHeader?: RowStickyState;
|
|
115
121
|
[ShadowEvent.SHOW_BEFORE_SHADOW]: boolean;
|
|
116
122
|
[ShadowEvent.SHOW_AFTER_SHADOW]: boolean;
|
|
123
|
+
tableWrapperWidth?: number;
|
|
124
|
+
tableWrapperHeight?: number;
|
|
117
125
|
}
|
|
118
126
|
|
|
119
127
|
class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
@@ -124,6 +132,8 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
124
132
|
parentWidth: undefined,
|
|
125
133
|
[ShadowEvent.SHOW_BEFORE_SHADOW]: false,
|
|
126
134
|
[ShadowEvent.SHOW_AFTER_SHADOW]: false,
|
|
135
|
+
tableWrapperWidth: undefined,
|
|
136
|
+
tableWrapperHeight: undefined,
|
|
127
137
|
};
|
|
128
138
|
|
|
129
139
|
private wrapper?: HTMLDivElement | null;
|
|
@@ -136,6 +146,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
136
146
|
|
|
137
147
|
private isInitialOverflowSent: boolean;
|
|
138
148
|
private initialOverflowCaptureTimerId?: ReturnType<typeof setTimeout>;
|
|
149
|
+
private resizeObserver?: ResizeObserver;
|
|
139
150
|
|
|
140
151
|
private dragAndDropCleanupFn?: CleanupFn;
|
|
141
152
|
|
|
@@ -158,6 +169,21 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
158
169
|
},
|
|
159
170
|
);
|
|
160
171
|
|
|
172
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
173
|
+
for (let entry of entries) {
|
|
174
|
+
this.setState((prev) => {
|
|
175
|
+
return prev?.tableWrapperWidth === entry.contentRect?.width &&
|
|
176
|
+
prev?.tableWrapperHeight === entry.contentRect?.height
|
|
177
|
+
? prev
|
|
178
|
+
: {
|
|
179
|
+
...prev,
|
|
180
|
+
tableWrapperWidth: entry.contentRect.width,
|
|
181
|
+
tableWrapperHeight: entry.contentRect.height,
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
161
187
|
// Disable inline table editing and resizing controls in Firefox
|
|
162
188
|
// https://github.com/ProseMirror/prosemirror/issues/432
|
|
163
189
|
if ('execCommand' in document) {
|
|
@@ -231,11 +257,13 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
231
257
|
|
|
232
258
|
eventDispatcher.on((stickyHeadersPluginKey as any).key, this.onStickyState);
|
|
233
259
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
260
|
+
if (isOverflowAnalyticsEnabled) {
|
|
261
|
+
const initialIsOveflowing =
|
|
262
|
+
this.state[ShadowEvent.SHOW_BEFORE_SHADOW] ||
|
|
263
|
+
this.state[ShadowEvent.SHOW_AFTER_SHADOW];
|
|
237
264
|
|
|
238
|
-
|
|
265
|
+
this.setTimerToSendInitialOverflowCaptured(initialIsOveflowing);
|
|
266
|
+
}
|
|
239
267
|
}
|
|
240
268
|
|
|
241
269
|
componentWillUnmount() {
|
|
@@ -254,6 +282,8 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
254
282
|
this.dragAndDropCleanupFn();
|
|
255
283
|
}
|
|
256
284
|
|
|
285
|
+
this.resizeObserver?.disconnect();
|
|
286
|
+
|
|
257
287
|
const { stickyScrollbar } = getEditorFeatureFlags();
|
|
258
288
|
|
|
259
289
|
if (stickyScrollbar) {
|
|
@@ -308,7 +338,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
308
338
|
return;
|
|
309
339
|
}
|
|
310
340
|
|
|
311
|
-
const
|
|
341
|
+
const tableNodeWidth = getTableContainerWidth(tableNode);
|
|
312
342
|
const shouldTableScale = tableRenderWidth < tableNodeWidth;
|
|
313
343
|
|
|
314
344
|
const { width: containerWidthValue } = containerWidth;
|
|
@@ -325,7 +355,10 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
325
355
|
isTableScalingEnabled: true,
|
|
326
356
|
});
|
|
327
357
|
|
|
328
|
-
|
|
358
|
+
// Request animation frame required for Firefox
|
|
359
|
+
requestAnimationFrame(() => {
|
|
360
|
+
updateColgroup(resizeState, this.table!, tableNode, true);
|
|
361
|
+
});
|
|
329
362
|
}
|
|
330
363
|
this.containerWidth = containerWidth;
|
|
331
364
|
}
|
|
@@ -418,38 +451,42 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
418
451
|
|
|
419
452
|
this.handleTableResizingDebounced();
|
|
420
453
|
}
|
|
454
|
+
if (isOverflowAnalyticsEnabled) {
|
|
455
|
+
const newIsOverflowing =
|
|
456
|
+
this.state[ShadowEvent.SHOW_BEFORE_SHADOW] ||
|
|
457
|
+
this.state[ShadowEvent.SHOW_AFTER_SHADOW];
|
|
421
458
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const prevIsOverflowing =
|
|
427
|
-
prevState[ShadowEvent.SHOW_BEFORE_SHADOW] ||
|
|
428
|
-
prevState[ShadowEvent.SHOW_AFTER_SHADOW];
|
|
459
|
+
const prevIsOverflowing =
|
|
460
|
+
prevState[ShadowEvent.SHOW_BEFORE_SHADOW] ||
|
|
461
|
+
prevState[ShadowEvent.SHOW_AFTER_SHADOW];
|
|
429
462
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (!this.isInitialOverflowSent) {
|
|
435
|
-
this.setTimerToSendInitialOverflowCaptured(newIsOverflowing);
|
|
436
|
-
}
|
|
463
|
+
if (this.initialOverflowCaptureTimerId) {
|
|
464
|
+
clearTimeout(this.initialOverflowCaptureTimerId);
|
|
465
|
+
}
|
|
437
466
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
state: { tr },
|
|
442
|
-
} = this.props.view;
|
|
467
|
+
if (!this.isInitialOverflowSent) {
|
|
468
|
+
this.setTimerToSendInitialOverflowCaptured(newIsOverflowing);
|
|
469
|
+
}
|
|
443
470
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
|
|
471
|
+
if (
|
|
472
|
+
this.isInitialOverflowSent &&
|
|
473
|
+
prevIsOverflowing !== newIsOverflowing
|
|
474
|
+
) {
|
|
475
|
+
const {
|
|
476
|
+
dispatch,
|
|
477
|
+
state: { tr },
|
|
478
|
+
} = this.props.view;
|
|
479
|
+
|
|
480
|
+
dispatch(
|
|
481
|
+
tr.setMeta(META_KEYS.OVERFLOW_STATE_CHANGED, {
|
|
482
|
+
isOverflowing: newIsOverflowing,
|
|
483
|
+
wasOverflowing: prevIsOverflowing,
|
|
484
|
+
editorWidth: this.props.containerWidth.width || 0,
|
|
485
|
+
width: this.node.attrs.width || 0,
|
|
486
|
+
parentWidth: this.state?.parentWidth || 0,
|
|
487
|
+
}),
|
|
488
|
+
);
|
|
489
|
+
}
|
|
453
490
|
}
|
|
454
491
|
}
|
|
455
492
|
|
|
@@ -471,6 +508,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
471
508
|
}
|
|
472
509
|
};
|
|
473
510
|
|
|
511
|
+
private observeTable(table: HTMLTableElement | null) {
|
|
512
|
+
if (table) {
|
|
513
|
+
this.resizeObserver?.observe(table);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
474
517
|
onStickyState = (state: StickyPluginState) => {
|
|
475
518
|
const pos = this.props.getPos();
|
|
476
519
|
if (!isValidPosition(pos, this.props.view.state)) {
|
|
@@ -539,6 +582,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
539
582
|
selection={view.state.selection}
|
|
540
583
|
headerRowHeight={headerRow ? headerRow.offsetHeight : undefined}
|
|
541
584
|
stickyHeader={this.state.stickyHeader}
|
|
585
|
+
tableWrapperWidth={this.state.tableWrapperWidth}
|
|
542
586
|
/>
|
|
543
587
|
);
|
|
544
588
|
const tableContainerWidth = getTableContainerWidth(node);
|
|
@@ -563,6 +607,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
563
607
|
tableContainerWidth={tableContainerWidth}
|
|
564
608
|
isNumberColumnEnabled={node.attrs.isNumberColumnEnabled}
|
|
565
609
|
getScrollOffset={() => this.wrapper?.scrollLeft || 0}
|
|
610
|
+
tableWrapperHeight={this.state.tableWrapperHeight}
|
|
566
611
|
/>
|
|
567
612
|
) : null;
|
|
568
613
|
|
|
@@ -615,6 +660,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
615
660
|
isBreakoutEnabled={options?.isBreakoutEnabled}
|
|
616
661
|
isNested={isNested}
|
|
617
662
|
pluginInjectionApi={pluginInjectionApi}
|
|
663
|
+
tableWrapperHeight={this.state.tableWrapperHeight}
|
|
618
664
|
isTableResizingEnabled={options?.isTableResizingEnabled}
|
|
619
665
|
isResizing={isResizing}
|
|
620
666
|
isTableScalingEnabled={isTableScalingEnabled}
|
|
@@ -668,6 +714,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
668
714
|
if (tableElement !== this.table) {
|
|
669
715
|
this.table = tableElement;
|
|
670
716
|
this.createShadowSentinels(this.table);
|
|
717
|
+
this.observeTable(this.table);
|
|
671
718
|
}
|
|
672
719
|
}
|
|
673
720
|
}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
|
-
import React, { forwardRef, useCallback, useRef } from 'react';
|
|
2
|
+
import React, { forwardRef, useCallback, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
|
|
@@ -78,6 +78,7 @@ type ResizableTableContainerProps = {
|
|
|
78
78
|
isResizing?: boolean;
|
|
79
79
|
pluginInjectionApi?: PluginInjectionAPI;
|
|
80
80
|
isTableScalingEnabled?: boolean;
|
|
81
|
+
tableWrapperHeight?: number;
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
export const ResizableTableContainer = React.memo(
|
|
@@ -92,9 +93,11 @@ export const ResizableTableContainer = React.memo(
|
|
|
92
93
|
isResizing,
|
|
93
94
|
pluginInjectionApi,
|
|
94
95
|
isTableScalingEnabled,
|
|
96
|
+
tableWrapperHeight,
|
|
95
97
|
}: PropsWithChildren<ResizableTableContainerProps>) => {
|
|
96
98
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
97
99
|
const tableWidthRef = useRef<number>(akEditorDefaultLayoutWidth);
|
|
100
|
+
const [resizing, setIsResizing] = useState(false);
|
|
98
101
|
|
|
99
102
|
const updateContainerHeight = useCallback((height: number | 'auto') => {
|
|
100
103
|
// current StickyHeader State is not stable to be fetch.
|
|
@@ -108,41 +111,26 @@ export const ResizableTableContainer = React.memo(
|
|
|
108
111
|
// 1px is border width but collapse make it 0.5.
|
|
109
112
|
// -- When sticky header appear, we should add first row height but reduce
|
|
110
113
|
// collapsed border
|
|
111
|
-
|
|
112
|
-
'height',
|
|
113
|
-
typeof height === 'number' ? `${height + 40.5}px` : 'auto',
|
|
114
|
-
);
|
|
114
|
+
return typeof height === 'number' ? `${height + 40.5}px` : 'auto';
|
|
115
115
|
} else {
|
|
116
116
|
const stickyHeaderHeight =
|
|
117
117
|
containerRef.current
|
|
118
118
|
?.getElementsByTagName('th')[0]
|
|
119
119
|
.getBoundingClientRect().height || 0;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
: 'auto',
|
|
125
|
-
);
|
|
120
|
+
|
|
121
|
+
return typeof height === 'number'
|
|
122
|
+
? `${height + stickyHeaderHeight + 39.5}px`
|
|
123
|
+
: 'auto';
|
|
126
124
|
}
|
|
127
125
|
}, []);
|
|
128
126
|
|
|
129
|
-
const resizeObserverRef = useRef(
|
|
130
|
-
new ResizeObserver((entries) => {
|
|
131
|
-
updateContainerHeight(entries[entries.length - 1].contentRect.height);
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
|
|
135
127
|
const onResizeStart = useCallback(() => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
}, [tableRef]);
|
|
128
|
+
setIsResizing(true);
|
|
129
|
+
}, []);
|
|
140
130
|
|
|
141
131
|
const onResizeStop = useCallback(() => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
resizeObserverRef.current.disconnect();
|
|
145
|
-
}, [updateContainerHeight]);
|
|
132
|
+
setIsResizing(false);
|
|
133
|
+
}, []);
|
|
146
134
|
|
|
147
135
|
const updateWidth = useCallback((width: number) => {
|
|
148
136
|
if (!containerRef.current) {
|
|
@@ -239,6 +227,9 @@ export const ResizableTableContainer = React.memo(
|
|
|
239
227
|
<div
|
|
240
228
|
style={{
|
|
241
229
|
width: tableWidthRef.current,
|
|
230
|
+
height: resizing
|
|
231
|
+
? updateContainerHeight(tableWrapperHeight ?? 'auto')
|
|
232
|
+
: 'auto',
|
|
242
233
|
}}
|
|
243
234
|
className={ClassName.TABLE_RESIZER_CONTAINER}
|
|
244
235
|
ref={containerRef}
|
|
@@ -267,6 +258,7 @@ type TableContainerProps = {
|
|
|
267
258
|
isResizing?: boolean;
|
|
268
259
|
pluginInjectionApi?: PluginInjectionAPI;
|
|
269
260
|
isTableScalingEnabled?: boolean;
|
|
261
|
+
tableWrapperHeight?: number;
|
|
270
262
|
};
|
|
271
263
|
|
|
272
264
|
export const TableContainer = ({
|
|
@@ -280,6 +272,7 @@ export const TableContainer = ({
|
|
|
280
272
|
getPos,
|
|
281
273
|
tableRef,
|
|
282
274
|
isNested,
|
|
275
|
+
tableWrapperHeight,
|
|
283
276
|
isResizing,
|
|
284
277
|
pluginInjectionApi,
|
|
285
278
|
isTableScalingEnabled,
|
|
@@ -293,6 +286,7 @@ export const TableContainer = ({
|
|
|
293
286
|
editorView={editorView}
|
|
294
287
|
getPos={getPos}
|
|
295
288
|
tableRef={tableRef}
|
|
289
|
+
tableWrapperHeight={tableWrapperHeight}
|
|
296
290
|
isResizing={isResizing}
|
|
297
291
|
pluginInjectionApi={pluginInjectionApi}
|
|
298
292
|
isTableScalingEnabled={isTableScalingEnabled}
|
|
@@ -125,10 +125,7 @@ const getResizerHandleHeight = (
|
|
|
125
125
|
|
|
126
126
|
const getResizerMinWidth = (node: PMNode) => {
|
|
127
127
|
const currentColumnCount = getColgroupChildrenLength(node);
|
|
128
|
-
const minColumnWidth =
|
|
129
|
-
currentColumnCount <= 3
|
|
130
|
-
? currentColumnCount * COLUMN_MIN_WIDTH
|
|
131
|
-
: 3 * COLUMN_MIN_WIDTH;
|
|
128
|
+
const minColumnWidth = Math.min(3, currentColumnCount) * COLUMN_MIN_WIDTH;
|
|
132
129
|
// add an extra pixel as the scale table logic will scale columns to be tableContainerWidth - 1
|
|
133
130
|
// the table can't scale past its min-width, so instead restrict table container min width to avoid that situation
|
|
134
131
|
return minColumnWidth + 1;
|
package/src/plugin.tsx
CHANGED
|
@@ -135,10 +135,11 @@ export type TablePlugin = NextEditorPlugin<
|
|
|
135
135
|
const tablesPlugin: TablePlugin = ({ config: options, api }) => {
|
|
136
136
|
const editorViewRef: Record<'current', EditorView | null> = { current: null };
|
|
137
137
|
const defaultGetEditorContainerWidth: GetEditorContainerWidth = () => {
|
|
138
|
-
|
|
139
|
-
width
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
return (
|
|
139
|
+
api?.width?.sharedState.currentState() ?? {
|
|
140
|
+
width: document?.body?.offsetWidth ?? 500,
|
|
141
|
+
}
|
|
142
|
+
);
|
|
142
143
|
};
|
|
143
144
|
const editorAnalyticsAPI = api?.analytics?.actions;
|
|
144
145
|
|
package/src/pm-plugins/main.ts
CHANGED
|
@@ -77,7 +77,6 @@ import TableRow from '../nodeviews/TableRow';
|
|
|
77
77
|
import { pluginKey as decorationsPluginKey } from '../pm-plugins/decorations/plugin';
|
|
78
78
|
import { fixTables, replaceSelectedTable } from '../transforms';
|
|
79
79
|
import type {
|
|
80
|
-
ElementContentRects,
|
|
81
80
|
InvalidNodeAttr,
|
|
82
81
|
PluginConfig,
|
|
83
82
|
PluginInjectionAPI,
|
|
@@ -134,19 +133,6 @@ export const createPlugin = (
|
|
|
134
133
|
getIntl,
|
|
135
134
|
});
|
|
136
135
|
|
|
137
|
-
let elementContentRects: ElementContentRects = {};
|
|
138
|
-
|
|
139
|
-
const observer = window?.ResizeObserver
|
|
140
|
-
? new ResizeObserver((entries) => {
|
|
141
|
-
entries.forEach((entry) => {
|
|
142
|
-
if (!entry.target.id) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
elementContentRects[entry.target.id] = entry.contentRect;
|
|
146
|
-
});
|
|
147
|
-
})
|
|
148
|
-
: undefined;
|
|
149
|
-
|
|
150
136
|
// Used to prevent invalid table cell spans being reported more than once per editor/document
|
|
151
137
|
const invalidTableIds: string[] = [];
|
|
152
138
|
let editorViewRef: EditorView | null = null;
|
|
@@ -282,11 +268,6 @@ export const createPlugin = (
|
|
|
282
268
|
removeResizeHandleDecorations()(state, dispatch);
|
|
283
269
|
}
|
|
284
270
|
},
|
|
285
|
-
destroy: () => {
|
|
286
|
-
if (observer) {
|
|
287
|
-
observer.disconnect();
|
|
288
|
-
}
|
|
289
|
-
},
|
|
290
271
|
};
|
|
291
272
|
},
|
|
292
273
|
props: {
|
|
@@ -417,9 +398,9 @@ export const createPlugin = (
|
|
|
417
398
|
tableRow: (node, view, getPos) =>
|
|
418
399
|
new TableRow(node, view, getPos, eventDispatcher),
|
|
419
400
|
tableCell: (node, view, getPos) =>
|
|
420
|
-
new TableCell(node, view, getPos, eventDispatcher
|
|
401
|
+
new TableCell(node, view, getPos, eventDispatcher),
|
|
421
402
|
tableHeader: (node, view, getPos) =>
|
|
422
|
-
new TableCell(node, view, getPos, eventDispatcher
|
|
403
|
+
new TableCell(node, view, getPos, eventDispatcher),
|
|
423
404
|
},
|
|
424
405
|
handleDOMEvents: {
|
|
425
406
|
focus: handleFocus,
|
|
@@ -428,7 +409,7 @@ export const createPlugin = (
|
|
|
428
409
|
mouseover: withCellTracking(whenTableInFocus(handleMouseOver)),
|
|
429
410
|
mouseleave: handleMouseLeave,
|
|
430
411
|
mouseout: whenTableInFocus(handleMouseOut),
|
|
431
|
-
mousemove: whenTableInFocus(handleMouseMove
|
|
412
|
+
mousemove: whenTableInFocus(handleMouseMove),
|
|
432
413
|
mouseenter: handleMouseEnter,
|
|
433
414
|
mouseup: whenTableInFocus(handleMouseUp),
|
|
434
415
|
click: withCellTracking(whenTableInFocus(handleClick)),
|
|
@@ -5,7 +5,7 @@ import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
|
5
5
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
6
6
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { getTableScalingPercent } from './misc';
|
|
9
9
|
|
|
10
10
|
type Col = Array<string | { [name: string]: string }>;
|
|
11
11
|
|
|
@@ -29,13 +29,10 @@ export const generateColgroup = (table: PmNode, tableRef?: HTMLElement) => {
|
|
|
29
29
|
// We slice here to guard against our colwidth array having more entries
|
|
30
30
|
// Than the we actually span. We'll patch the document at a later point.
|
|
31
31
|
if (tableRef) {
|
|
32
|
-
const
|
|
33
|
-
let renderWidth = tableRef.parentElement?.clientWidth || 760;
|
|
34
|
-
let scalePercent = renderWidth / tableWidth;
|
|
35
|
-
scalePercent = Math.max(scalePercent, 1 - MAX_SCALING_PERCENT);
|
|
32
|
+
const scalePercent = getTableScalingPercent(table, tableRef);
|
|
36
33
|
cell.attrs.colwidth.slice(0, colspan).forEach((width) => {
|
|
37
34
|
const fixedColWidth = getColWidthFix(width, map.width);
|
|
38
|
-
const scaledWidth = fixedColWidth *
|
|
35
|
+
const scaledWidth = fixedColWidth * scalePercent;
|
|
39
36
|
const finalWidth = Math.max(scaledWidth, tableCellMinWidth);
|
|
40
37
|
cols.push([
|
|
41
38
|
'col',
|
|
@@ -31,6 +31,7 @@ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
|
31
31
|
import type { TableOptions } from '../../../nodeviews/types';
|
|
32
32
|
|
|
33
33
|
import { hasTableBeenResized } from './colgroup';
|
|
34
|
+
import { MAX_SCALING_PERCENT } from './consts';
|
|
34
35
|
|
|
35
36
|
// Translates named layouts in number values.
|
|
36
37
|
export function getLayoutSize(
|
|
@@ -156,3 +157,15 @@ export const getTableElementWidth = (table: PMNode) => {
|
|
|
156
157
|
export const getTableContainerElementWidth = (table: PMNode) => {
|
|
157
158
|
return getTableContainerWidth(table);
|
|
158
159
|
};
|
|
160
|
+
|
|
161
|
+
export const getTableScalingPercent = (
|
|
162
|
+
table: PMNode,
|
|
163
|
+
tableRef: HTMLElement,
|
|
164
|
+
) => {
|
|
165
|
+
const tableWidth = getTableContainerElementWidth(table);
|
|
166
|
+
let renderWidth = tableRef.parentElement?.clientWidth || tableWidth;
|
|
167
|
+
// minus 1 here to avoid any 1px scroll in Firefox
|
|
168
|
+
let scalePercent = (renderWidth - 1) / tableWidth;
|
|
169
|
+
scalePercent = Math.max(scalePercent, 1 - MAX_SCALING_PERCENT);
|
|
170
|
+
return Math.min(scalePercent, 1);
|
|
171
|
+
};
|