@atlaskit/editor-plugin-table 3.1.3 → 3.2.0
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 +10 -0
- package/dist/cjs/plugins/table/nodeviews/TableComponent.js +36 -2
- package/dist/cjs/plugins/table/nodeviews/TableStickyScrollbar.js +154 -0
- package/dist/cjs/plugins/table/toolbar.js +6 -0
- package/dist/cjs/plugins/table/ui/common-styles.js +9 -2
- package/dist/es2019/plugins/table/nodeviews/TableComponent.js +37 -3
- package/dist/es2019/plugins/table/nodeviews/TableStickyScrollbar.js +112 -0
- package/dist/es2019/plugins/table/toolbar.js +6 -0
- package/dist/es2019/plugins/table/ui/common-styles.js +33 -1
- package/dist/esm/plugins/table/nodeviews/TableComponent.js +37 -3
- package/dist/esm/plugins/table/nodeviews/TableStickyScrollbar.js +146 -0
- package/dist/esm/plugins/table/toolbar.js +6 -0
- package/dist/esm/plugins/table/ui/common-styles.js +8 -2
- package/dist/types/plugins/table/nodeviews/TableComponent.d.ts +1 -0
- package/dist/types/plugins/table/nodeviews/TableStickyScrollbar.d.ts +24 -0
- package/dist/types/plugins/table/toolbar.d.ts +4 -4
- package/dist/types/plugins/table/types.d.ts +3 -0
- package/dist/types/plugins/table/ui/common-styles.d.ts +1 -0
- package/dist/types-ts4.5/plugins/table/nodeviews/TableComponent.d.ts +1 -0
- package/dist/types-ts4.5/plugins/table/nodeviews/TableStickyScrollbar.d.ts +24 -0
- package/dist/types-ts4.5/plugins/table/toolbar.d.ts +4 -4
- package/dist/types-ts4.5/plugins/table/types.d.ts +3 -0
- package/dist/types-ts4.5/plugins/table/ui/common-styles.d.ts +1 -0
- package/package.json +6 -3
- package/src/plugins/table/nodeviews/TableComponent.tsx +54 -3
- package/src/plugins/table/nodeviews/TableStickyScrollbar.ts +204 -0
- package/src/plugins/table/toolbar.tsx +10 -6
- package/src/plugins/table/ui/common-styles.ts +38 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@atlaskit/adf-schema": "^29.1.0",
|
|
31
|
-
"@atlaskit/editor-common": "^75.
|
|
31
|
+
"@atlaskit/editor-common": "^75.8.0",
|
|
32
32
|
"@atlaskit/editor-palette": "1.5.1",
|
|
33
33
|
"@atlaskit/editor-plugin-analytics": "^0.2.0",
|
|
34
34
|
"@atlaskit/editor-plugin-content-insertion": "^0.1.0",
|
|
35
35
|
"@atlaskit/editor-prosemirror": "1.1.0",
|
|
36
|
-
"@atlaskit/editor-shared-styles": "^2.
|
|
36
|
+
"@atlaskit/editor-shared-styles": "^2.8.0",
|
|
37
37
|
"@atlaskit/editor-tables": "^2.3.0",
|
|
38
38
|
"@atlaskit/icon": "^21.12.0",
|
|
39
39
|
"@atlaskit/platform-feature-flags": "^0.2.1",
|
|
@@ -102,6 +102,9 @@
|
|
|
102
102
|
"platform.editor.custom-table-width": {
|
|
103
103
|
"type": "boolean"
|
|
104
104
|
},
|
|
105
|
+
"platform.editor.table-sticky-scrollbar": {
|
|
106
|
+
"type": "boolean"
|
|
107
|
+
},
|
|
105
108
|
"platform.editor.update-table-cell-width-via-step": {
|
|
106
109
|
"type": "boolean"
|
|
107
110
|
},
|
|
@@ -27,7 +27,10 @@ import {
|
|
|
27
27
|
} from '@atlaskit/editor-common/utils';
|
|
28
28
|
import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
|
|
29
29
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
MAX_BROWSER_SCROLLBAR_HEIGHT,
|
|
32
|
+
akEditorTableToolbarSize as tableToolbarSize,
|
|
33
|
+
} from '@atlaskit/editor-shared-styles';
|
|
31
34
|
import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
32
35
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
33
36
|
|
|
@@ -65,6 +68,7 @@ import {
|
|
|
65
68
|
|
|
66
69
|
import { OverflowShadowsObserver } from './OverflowShadowsObserver';
|
|
67
70
|
import { TableContainer } from './TableContainer';
|
|
71
|
+
import { TableStickyScrollbar } from './TableStickyScrollbar';
|
|
68
72
|
import type { TableOptions } from './types';
|
|
69
73
|
|
|
70
74
|
const isIE11 = browser.ie_version === 11;
|
|
@@ -72,6 +76,7 @@ const isIE11 = browser.ie_version === 11;
|
|
|
72
76
|
// componentDidUpdate is called multiple times. The isOverflowing value is correct only on the last update.
|
|
73
77
|
// To make sure we capture the last update, we use setTimeout.
|
|
74
78
|
const initialOverflowCaptureTimeroutDelay = 300;
|
|
79
|
+
|
|
75
80
|
export interface ComponentProps {
|
|
76
81
|
view: EditorView;
|
|
77
82
|
getNode: () => PmNode;
|
|
@@ -117,6 +122,7 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
117
122
|
private containerWidth?: EditorContainerWidth;
|
|
118
123
|
private layoutSize?: number;
|
|
119
124
|
private overflowShadowsObserver?: OverflowShadowsObserver;
|
|
125
|
+
private stickyScrollbar?: TableStickyScrollbar;
|
|
120
126
|
|
|
121
127
|
private isInitialOverflowSent: boolean;
|
|
122
128
|
private initialOverflowCaptureTimerId?: ReturnType<typeof setTimeout>;
|
|
@@ -154,7 +160,18 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
154
160
|
componentDidMount() {
|
|
155
161
|
const { allowColumnResizing, eventDispatcher, options } = this.props;
|
|
156
162
|
if (allowColumnResizing && this.wrapper && !isIE11) {
|
|
157
|
-
this.wrapper.addEventListener('scroll', this.handleScrollDebounced
|
|
163
|
+
this.wrapper.addEventListener('scroll', this.handleScrollDebounced, {
|
|
164
|
+
passive: true,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (getBooleanFF('platform.editor.table-sticky-scrollbar')) {
|
|
168
|
+
if (this.table) {
|
|
169
|
+
this.stickyScrollbar = new TableStickyScrollbar(
|
|
170
|
+
this.wrapper,
|
|
171
|
+
this.props.view,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
158
175
|
}
|
|
159
176
|
|
|
160
177
|
if (allowColumnResizing) {
|
|
@@ -193,6 +210,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
193
210
|
this.wrapper.removeEventListener('scroll', this.handleScrollDebounced);
|
|
194
211
|
}
|
|
195
212
|
|
|
213
|
+
if (getBooleanFF('platform.editor.table-sticky-scrollbar')) {
|
|
214
|
+
if (this.stickyScrollbar) {
|
|
215
|
+
this.stickyScrollbar.dispose();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
196
219
|
this.handleScrollDebounced.cancel();
|
|
197
220
|
this.scaleTableDebounced.cancel();
|
|
198
221
|
this.handleTableResizingDebounced.cancel();
|
|
@@ -453,6 +476,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
453
476
|
className={ClassName.TABLE_STICKY_SENTINEL_TOP}
|
|
454
477
|
data-testid="sticky-sentinel-top"
|
|
455
478
|
/>
|
|
479
|
+
{getBooleanFF('platform.editor.table-sticky-scrollbar') && (
|
|
480
|
+
<div
|
|
481
|
+
className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP}
|
|
482
|
+
data-testid="sticky-scrollbar-sentinel-top"
|
|
483
|
+
/>
|
|
484
|
+
)}
|
|
456
485
|
{allowControls && rowControls}
|
|
457
486
|
<div
|
|
458
487
|
style={shadowStyle(showBeforeShadow)}
|
|
@@ -473,7 +502,6 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
473
502
|
}}
|
|
474
503
|
/>
|
|
475
504
|
)}
|
|
476
|
-
|
|
477
505
|
<div
|
|
478
506
|
className={classnames(ClassName.TABLE_NODE_WRAPPER)}
|
|
479
507
|
ref={(elem) => {
|
|
@@ -488,6 +516,17 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
488
516
|
}
|
|
489
517
|
}}
|
|
490
518
|
/>
|
|
519
|
+
{getBooleanFF('platform.editor.table-sticky-scrollbar') && (
|
|
520
|
+
<div
|
|
521
|
+
className={ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER}
|
|
522
|
+
style={{
|
|
523
|
+
height: MAX_BROWSER_SCROLLBAR_HEIGHT,
|
|
524
|
+
display: 'none',
|
|
525
|
+
}}
|
|
526
|
+
>
|
|
527
|
+
<div style={{ width: tableRef?.clientWidth }}></div>
|
|
528
|
+
</div>
|
|
529
|
+
)}
|
|
491
530
|
<div
|
|
492
531
|
style={shadowStyle(showAfterShadow)}
|
|
493
532
|
className={ClassName.TABLE_RIGHT_SHADOW}
|
|
@@ -526,6 +565,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
526
565
|
className={ClassName.TABLE_STICKY_SENTINEL_BOTTOM}
|
|
527
566
|
data-testid="sticky-sentinel-bottom"
|
|
528
567
|
/>
|
|
568
|
+
{getBooleanFF('platform.editor.table-sticky-scrollbar') && (
|
|
569
|
+
<div
|
|
570
|
+
className={ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM}
|
|
571
|
+
data-testid="sticky-scrollbar-sentinel-bottom"
|
|
572
|
+
/>
|
|
573
|
+
)}
|
|
529
574
|
</TableContainer>
|
|
530
575
|
);
|
|
531
576
|
}
|
|
@@ -535,6 +580,12 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
535
580
|
return;
|
|
536
581
|
}
|
|
537
582
|
|
|
583
|
+
if (getBooleanFF('platform.editor.table-sticky-scrollbar')) {
|
|
584
|
+
if (this.stickyScrollbar) {
|
|
585
|
+
this.stickyScrollbar.scrollLeft(this.wrapper.scrollLeft);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
538
589
|
if (this.table) {
|
|
539
590
|
// sync sticky header row to table scroll
|
|
540
591
|
const headers = this.table.querySelectorAll('tr[data-header-row]');
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import rafSchedule from 'raf-schd';
|
|
2
|
+
|
|
3
|
+
import { findOverflowScrollParent } from '@atlaskit/editor-common/ui';
|
|
4
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
|
|
6
|
+
import { TableCssClassName as ClassName } from '../types';
|
|
7
|
+
|
|
8
|
+
type SentinelState = 'above' | 'visible' | 'below';
|
|
9
|
+
|
|
10
|
+
export class TableStickyScrollbar {
|
|
11
|
+
private wrapper: HTMLDivElement;
|
|
12
|
+
private view: EditorView;
|
|
13
|
+
private editorScrollableElement?: HTMLElement | Document;
|
|
14
|
+
private intersectionObserver?: IntersectionObserver;
|
|
15
|
+
private stickyScrollbarContainerElement?: HTMLDivElement | null;
|
|
16
|
+
|
|
17
|
+
private sentinels: {
|
|
18
|
+
bottom?: HTMLElement | null;
|
|
19
|
+
top?: HTMLElement | null;
|
|
20
|
+
} = {};
|
|
21
|
+
|
|
22
|
+
private topSentinelState?: SentinelState;
|
|
23
|
+
private bottomSentinelState?: SentinelState;
|
|
24
|
+
|
|
25
|
+
constructor(wrapper: HTMLDivElement, view: EditorView) {
|
|
26
|
+
this.wrapper = wrapper;
|
|
27
|
+
this.view = view;
|
|
28
|
+
|
|
29
|
+
this.init();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dispose() {
|
|
33
|
+
if (this.stickyScrollbarContainerElement) {
|
|
34
|
+
this.stickyScrollbarContainerElement.removeEventListener(
|
|
35
|
+
'scroll',
|
|
36
|
+
this.handleScrollDebounced,
|
|
37
|
+
);
|
|
38
|
+
this.handleScrollDebounced.cancel();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.deleteIntesactionObserver();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
scrollLeft(left: number) {
|
|
45
|
+
if (this.stickyScrollbarContainerElement) {
|
|
46
|
+
this.stickyScrollbarContainerElement.scrollLeft = left;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private init() {
|
|
51
|
+
if (!this.wrapper) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.stickyScrollbarContainerElement =
|
|
56
|
+
this.wrapper.parentElement?.querySelector(
|
|
57
|
+
`.${ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER}`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (this.stickyScrollbarContainerElement) {
|
|
61
|
+
this.stickyScrollbarContainerElement.addEventListener(
|
|
62
|
+
'scroll',
|
|
63
|
+
this.handleScrollDebounced,
|
|
64
|
+
{ passive: true },
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.createIntersectionObserver();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private createIntersectionObserver() {
|
|
72
|
+
this.editorScrollableElement =
|
|
73
|
+
(findOverflowScrollParent(this.view.dom) as HTMLElement) ||
|
|
74
|
+
window.document;
|
|
75
|
+
|
|
76
|
+
if (!this.editorScrollableElement || !this.wrapper) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.intersectionObserver = new IntersectionObserver(
|
|
81
|
+
(entries: IntersectionObserverEntry[], _: IntersectionObserver) => {
|
|
82
|
+
if (!this.stickyScrollbarContainerElement) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
entries.forEach((entry) => {
|
|
87
|
+
const target = entry.target as HTMLElement;
|
|
88
|
+
// if the rootBounds has 0 height, e.g. confluence preview mode, we do nothing.
|
|
89
|
+
if (entry.rootBounds?.height === 0) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
target.classList.contains(
|
|
95
|
+
ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM,
|
|
96
|
+
)
|
|
97
|
+
) {
|
|
98
|
+
this.sentenialBottomCallback(entry);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (
|
|
102
|
+
target.classList.contains(
|
|
103
|
+
ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP,
|
|
104
|
+
)
|
|
105
|
+
) {
|
|
106
|
+
this.sentenialTopCallback(entry);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
{ root: this.editorScrollableElement },
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
this.sentinels.bottom = this.wrapper?.parentElement
|
|
114
|
+
?.getElementsByClassName(ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM)
|
|
115
|
+
?.item(0) as HTMLElement;
|
|
116
|
+
|
|
117
|
+
this.sentinels.top = this.wrapper?.parentElement
|
|
118
|
+
?.getElementsByClassName(ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP)
|
|
119
|
+
?.item(0) as HTMLElement;
|
|
120
|
+
|
|
121
|
+
[this.sentinels.bottom, this.sentinels.top].forEach((el) =>
|
|
122
|
+
this.intersectionObserver!.observe(el),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private deleteIntesactionObserver() {
|
|
127
|
+
if (this.intersectionObserver) {
|
|
128
|
+
if (this.sentinels.bottom) {
|
|
129
|
+
this.intersectionObserver.unobserve(this.sentinels.bottom);
|
|
130
|
+
}
|
|
131
|
+
this.intersectionObserver.disconnect();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private sentenialBottomCallback(entry: IntersectionObserverEntry) {
|
|
136
|
+
const sentinelIsAboveScrollArea =
|
|
137
|
+
entry.boundingClientRect.top < (entry.rootBounds?.top || 0);
|
|
138
|
+
|
|
139
|
+
this.bottomSentinelState = sentinelIsAboveScrollArea
|
|
140
|
+
? 'above'
|
|
141
|
+
: entry.isIntersecting
|
|
142
|
+
? 'visible'
|
|
143
|
+
: 'below';
|
|
144
|
+
|
|
145
|
+
this.toggle();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private sentenialTopCallback(entry: IntersectionObserverEntry) {
|
|
149
|
+
const sentinelIsBelowScrollArea =
|
|
150
|
+
(entry.rootBounds?.bottom || 0) < entry.boundingClientRect.top;
|
|
151
|
+
|
|
152
|
+
this.topSentinelState = sentinelIsBelowScrollArea
|
|
153
|
+
? 'below'
|
|
154
|
+
: entry.isIntersecting
|
|
155
|
+
? 'visible'
|
|
156
|
+
: 'above';
|
|
157
|
+
|
|
158
|
+
this.toggle();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private toggle() {
|
|
162
|
+
if (
|
|
163
|
+
(this.topSentinelState === 'visible' ||
|
|
164
|
+
this.topSentinelState === 'above') &&
|
|
165
|
+
this.bottomSentinelState === 'below'
|
|
166
|
+
) {
|
|
167
|
+
this.show();
|
|
168
|
+
} else {
|
|
169
|
+
this.hide();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private hide() {
|
|
174
|
+
if (
|
|
175
|
+
this.stickyScrollbarContainerElement &&
|
|
176
|
+
this.stickyScrollbarContainerElement.style.display !== 'none'
|
|
177
|
+
) {
|
|
178
|
+
this.stickyScrollbarContainerElement.style.display = 'none';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private show() {
|
|
183
|
+
if (
|
|
184
|
+
this.stickyScrollbarContainerElement &&
|
|
185
|
+
this.stickyScrollbarContainerElement.style.display !== 'block'
|
|
186
|
+
) {
|
|
187
|
+
this.stickyScrollbarContainerElement.style.display = 'block';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private handleScroll = (event: Event) => {
|
|
192
|
+
if (
|
|
193
|
+
!this.stickyScrollbarContainerElement ||
|
|
194
|
+
!this.wrapper ||
|
|
195
|
+
event.target !== this.stickyScrollbarContainerElement
|
|
196
|
+
) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
this.wrapper.scrollLeft = this.stickyScrollbarContainerElement.scrollLeft;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
private handleScrollDebounced = rafSchedule(this.handleScroll);
|
|
204
|
+
}
|
|
@@ -33,13 +33,13 @@ import {
|
|
|
33
33
|
getNodeName,
|
|
34
34
|
isReferencedSource,
|
|
35
35
|
} from '@atlaskit/editor-common/utils';
|
|
36
|
-
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
37
|
-
import { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
36
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
37
|
+
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
38
38
|
import { findParentDomRefOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
39
|
-
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
39
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
40
40
|
import { akEditorFloatingPanelZIndex } from '@atlaskit/editor-shared-styles';
|
|
41
41
|
import { shortcutStyle } from '@atlaskit/editor-shared-styles/shortcut';
|
|
42
|
-
import { Rect } from '@atlaskit/editor-tables/table-map';
|
|
42
|
+
import type { Rect } from '@atlaskit/editor-tables/table-map';
|
|
43
43
|
import {
|
|
44
44
|
findCellRectClosestToPos,
|
|
45
45
|
findTable,
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
splitCell,
|
|
49
49
|
} from '@atlaskit/editor-tables/utils';
|
|
50
50
|
import RemoveIcon from '@atlaskit/icon/glyph/editor/remove';
|
|
51
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
51
52
|
|
|
52
53
|
import {
|
|
53
54
|
clearHoverSelection,
|
|
@@ -79,13 +80,13 @@ import { pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing
|
|
|
79
80
|
import { getNewResizeStateFromSelectedColumns } from './pm-plugins/table-resizing/utils/resize-state';
|
|
80
81
|
import { pluginKey as tableWidthPluginKey } from './pm-plugins/table-width';
|
|
81
82
|
import { canMergeCells } from './transforms';
|
|
82
|
-
import {
|
|
83
|
+
import type {
|
|
83
84
|
PluginConfig,
|
|
84
|
-
TableCssClassName,
|
|
85
85
|
ToolbarMenuConfig,
|
|
86
86
|
ToolbarMenuContext,
|
|
87
87
|
ToolbarMenuState,
|
|
88
88
|
} from './types';
|
|
89
|
+
import { TableCssClassName } from './types';
|
|
89
90
|
import { messages as ContextualMenuMessages } from './ui/FloatingContextualMenu/ContextualMenu';
|
|
90
91
|
import tableMessages from './ui/messages';
|
|
91
92
|
import {
|
|
@@ -520,6 +521,9 @@ export const getToolbarConfig =
|
|
|
520
521
|
getDomRef,
|
|
521
522
|
nodeType,
|
|
522
523
|
offset: [0, 18],
|
|
524
|
+
absoluteOffset: getBooleanFF('platform.editor.table-sticky-scrollbar')
|
|
525
|
+
? { top: -6 }
|
|
526
|
+
: { top: 0 },
|
|
523
527
|
zIndex: akEditorFloatingPanelZIndex + 1, // Place the context menu slightly above the others
|
|
524
528
|
items: [
|
|
525
529
|
menu,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
akEditorTableToolbarSize,
|
|
15
15
|
akEditorUnitZIndex,
|
|
16
16
|
getSelectionStyles,
|
|
17
|
+
MAX_BROWSER_SCROLLBAR_HEIGHT,
|
|
17
18
|
relativeFontSizeToBase16,
|
|
18
19
|
SelectionStyle,
|
|
19
20
|
} from '@atlaskit/editor-shared-styles';
|
|
@@ -75,6 +76,7 @@ const cornerControlHeight = tableToolbarSize + 1;
|
|
|
75
76
|
its center should be aligned with the edge
|
|
76
77
|
*/
|
|
77
78
|
export const insertColumnButtonOffset = tableInsertColumnButtonSize / 2;
|
|
79
|
+
export const tableRowHeight = 44;
|
|
78
80
|
|
|
79
81
|
const rangeSelectionStyles = `
|
|
80
82
|
.${ClassName.NODEVIEW_WRAPPER}.${akEditorSelectedNodeClassName} table tbody tr {
|
|
@@ -114,6 +116,41 @@ const sentinelStyles = `.${ClassName.TABLE_CONTAINER} {
|
|
|
114
116
|
}
|
|
115
117
|
}`;
|
|
116
118
|
|
|
119
|
+
const stickyScrollbarSentinelStyles = `.${ClassName.TABLE_CONTAINER} {
|
|
120
|
+
> .${ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM},
|
|
121
|
+
> .${ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP} {
|
|
122
|
+
position: absolute;
|
|
123
|
+
width: 100%;
|
|
124
|
+
height: 1px;
|
|
125
|
+
margin-top: -1px;
|
|
126
|
+
// need this to avoid sentinel being focused via keyboard
|
|
127
|
+
// this still allows it to be detected by intersection observer
|
|
128
|
+
visibility: hidden;
|
|
129
|
+
}
|
|
130
|
+
> .${ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_TOP} {
|
|
131
|
+
top: ${columnControlsDecorationHeight + tableRowHeight * 3}px;
|
|
132
|
+
}
|
|
133
|
+
> .${ClassName.TABLE_STICKY_SCROLLBAR_SENTINEL_BOTTOM} {
|
|
134
|
+
bottom: ${MAX_BROWSER_SCROLLBAR_HEIGHT}px;
|
|
135
|
+
}
|
|
136
|
+
}`;
|
|
137
|
+
|
|
138
|
+
const stickyScrollbarContainerStyles = `.${ClassName.TABLE_CONTAINER} {
|
|
139
|
+
> .${ClassName.TABLE_STICKY_SCROLLBAR_CONTAINER} {
|
|
140
|
+
width: 100%;
|
|
141
|
+
display: none;
|
|
142
|
+
overflow-x: auto;
|
|
143
|
+
position: sticky;
|
|
144
|
+
bottom: 0;
|
|
145
|
+
}
|
|
146
|
+
}`;
|
|
147
|
+
|
|
148
|
+
const stickyScrollbarStyles = () => {
|
|
149
|
+
return getBooleanFF('platform.editor.table-sticky-scrollbar')
|
|
150
|
+
? `${stickyScrollbarContainerStyles} ${stickyScrollbarSentinelStyles}`
|
|
151
|
+
: '';
|
|
152
|
+
};
|
|
153
|
+
|
|
117
154
|
const shadowSentinelStyles = `
|
|
118
155
|
.${ClassName.TABLE_SHADOW_SENTINEL_LEFT},
|
|
119
156
|
.${ClassName.TABLE_SHADOW_SENTINEL_RIGHT} {
|
|
@@ -417,6 +454,7 @@ export const tableStyles = (
|
|
|
417
454
|
|
|
418
455
|
${sentinelStyles}
|
|
419
456
|
${OverflowShadow(props)}
|
|
457
|
+
${stickyScrollbarStyles()}
|
|
420
458
|
|
|
421
459
|
.${ClassName.TABLE_STICKY} .${ClassName.TABLE_STICKY_SHADOW} {
|
|
422
460
|
height: 0; // stop overflow flash & set correct height in update-overflow-shadows.ts
|