@atlaskit/editor-plugin-table 10.8.0 → 10.8.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 +22 -0
- package/dist/cjs/nodeviews/TableRow.js +68 -28
- package/dist/cjs/nodeviews/table.js +1 -1
- package/dist/cjs/nodeviews/toDOM.js +4 -2
- package/dist/cjs/pm-plugins/table-size-selector.js +40 -0
- package/dist/cjs/tablePlugin.js +63 -32
- package/dist/cjs/ui/SizeSelector/index.js +65 -0
- package/dist/es2019/nodeviews/TableRow.js +65 -24
- package/dist/es2019/nodeviews/table.js +1 -1
- package/dist/es2019/nodeviews/toDOM.js +4 -2
- package/dist/es2019/pm-plugins/table-size-selector.js +31 -0
- package/dist/es2019/tablePlugin.js +33 -3
- package/dist/es2019/ui/SizeSelector/index.js +61 -0
- package/dist/esm/nodeviews/TableRow.js +68 -28
- package/dist/esm/nodeviews/table.js +1 -1
- package/dist/esm/nodeviews/toDOM.js +4 -2
- package/dist/esm/pm-plugins/table-size-selector.js +33 -0
- package/dist/esm/tablePlugin.js +63 -32
- package/dist/esm/ui/SizeSelector/index.js +58 -0
- package/dist/types/nodeviews/TableRow.d.ts +1 -0
- package/dist/types/pm-plugins/table-size-selector.d.ts +10 -0
- package/dist/types/ui/SizeSelector/index.d.ts +9 -0
- package/dist/types-ts4.5/nodeviews/TableRow.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/table-size-selector.d.ts +10 -0
- package/dist/types-ts4.5/ui/SizeSelector/index.d.ts +9 -0
- package/package.json +10 -4
- package/src/nodeviews/TableRow.ts +72 -30
- package/src/nodeviews/table.tsx +1 -1
- package/src/nodeviews/toDOM.ts +2 -0
- package/src/pm-plugins/table-size-selector.ts +39 -0
- package/src/tablePlugin.tsx +49 -0
- package/src/ui/SizeSelector/index.tsx +74 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jsxRuntime classic
|
|
3
|
+
* @jsx jsx
|
|
4
|
+
*/
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
|
|
8
|
+
import { jsx } from '@emotion/react';
|
|
9
|
+
import { TableSelectorPopup } from '@atlaskit/editor-common/ui';
|
|
10
|
+
import { pluginKey } from '../../pm-plugins/table-size-selector';
|
|
11
|
+
var DEFAULT_TABLE_SELECTOR_COLS = 3;
|
|
12
|
+
var DEFAULT_TABLE_SELECTOR_ROWS = 3;
|
|
13
|
+
export var SizeSelector = function SizeSelector(_ref) {
|
|
14
|
+
var api = _ref.api,
|
|
15
|
+
target = _ref.target,
|
|
16
|
+
popupsMountPoint = _ref.popupsMountPoint,
|
|
17
|
+
popupsBoundariesElement = _ref.popupsBoundariesElement,
|
|
18
|
+
popupsScrollableElement = _ref.popupsScrollableElement;
|
|
19
|
+
var closeSelectorPopup = useCallback(function () {
|
|
20
|
+
api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
|
|
21
|
+
var tr = _ref2.tr;
|
|
22
|
+
tr.setMeta(pluginKey, {
|
|
23
|
+
isSelectorOpen: false
|
|
24
|
+
});
|
|
25
|
+
return tr;
|
|
26
|
+
});
|
|
27
|
+
}, [api]);
|
|
28
|
+
var onSelection = useCallback(function (rowsCount, colsCount) {
|
|
29
|
+
api === null || api === void 0 || api.core.actions.execute(function (_ref3) {
|
|
30
|
+
var tr = _ref3.tr;
|
|
31
|
+
api === null || api === void 0 || api.table.commands.insertTableWithSize(rowsCount, colsCount)({
|
|
32
|
+
tr: tr
|
|
33
|
+
});
|
|
34
|
+
tr.setMeta(pluginKey, {
|
|
35
|
+
isSelectorOpen: false
|
|
36
|
+
});
|
|
37
|
+
return tr;
|
|
38
|
+
});
|
|
39
|
+
}, [api]);
|
|
40
|
+
var onUnmount = function onUnmount() {
|
|
41
|
+
api === null || api === void 0 || api.core.actions.focus();
|
|
42
|
+
};
|
|
43
|
+
return jsx(TableSelectorPopup, {
|
|
44
|
+
defaultSize: {
|
|
45
|
+
row: DEFAULT_TABLE_SELECTOR_ROWS,
|
|
46
|
+
col: DEFAULT_TABLE_SELECTOR_COLS
|
|
47
|
+
},
|
|
48
|
+
target: target,
|
|
49
|
+
onUnmount: onUnmount,
|
|
50
|
+
onSelection: onSelection,
|
|
51
|
+
popupsMountPoint: popupsMountPoint,
|
|
52
|
+
popupsScrollableElement: popupsScrollableElement,
|
|
53
|
+
popupsBoundariesElement: popupsBoundariesElement,
|
|
54
|
+
isOpenedByKeyboard: true,
|
|
55
|
+
handleClickOutside: closeSelectorPopup,
|
|
56
|
+
handleEscapeKeydown: closeSelectorPopup
|
|
57
|
+
});
|
|
58
|
+
};
|
|
@@ -17,6 +17,7 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
17
17
|
private isSticky;
|
|
18
18
|
private intersectionObserver?;
|
|
19
19
|
private resizeObserver?;
|
|
20
|
+
private tableContainerObserver?;
|
|
20
21
|
private sentinels;
|
|
21
22
|
private sentinelData;
|
|
22
23
|
private stickyRowHeight?;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
type SizeSelectorPluginState = {
|
|
5
|
+
isSelectorOpen: boolean;
|
|
6
|
+
targetRef?: HTMLElement;
|
|
7
|
+
};
|
|
8
|
+
export declare const pluginKey: PluginKey<SizeSelectorPluginState>;
|
|
9
|
+
export declare const createPlugin: (dispatch: Dispatch) => SafePlugin<SizeSelectorPluginState>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from '@emotion/react';
|
|
2
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
+
import { type TableSelectorPopupProps } from '@atlaskit/editor-common/ui';
|
|
4
|
+
import { TablePlugin } from '../../tablePluginType';
|
|
5
|
+
interface SizeSelectorProps extends Omit<TableSelectorPopupProps, 'handleClickOutside' | 'onSelection' | 'unUnmount'> {
|
|
6
|
+
api?: ExtractInjectionAPI<TablePlugin>;
|
|
7
|
+
}
|
|
8
|
+
export declare const SizeSelector: ({ api, target, popupsMountPoint, popupsBoundariesElement, popupsScrollableElement, }: SizeSelectorProps) => jsx.JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -17,6 +17,7 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
17
17
|
private isSticky;
|
|
18
18
|
private intersectionObserver?;
|
|
19
19
|
private resizeObserver?;
|
|
20
|
+
private tableContainerObserver?;
|
|
20
21
|
private sentinels;
|
|
21
22
|
private sentinelData;
|
|
22
23
|
private stickyRowHeight?;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
type SizeSelectorPluginState = {
|
|
5
|
+
isSelectorOpen: boolean;
|
|
6
|
+
targetRef?: HTMLElement;
|
|
7
|
+
};
|
|
8
|
+
export declare const pluginKey: PluginKey<SizeSelectorPluginState>;
|
|
9
|
+
export declare const createPlugin: (dispatch: Dispatch) => SafePlugin<SizeSelectorPluginState>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from '@emotion/react';
|
|
2
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
+
import { type TableSelectorPopupProps } from '@atlaskit/editor-common/ui';
|
|
4
|
+
import { TablePlugin } from '../../tablePluginType';
|
|
5
|
+
interface SizeSelectorProps extends Omit<TableSelectorPopupProps, 'handleClickOutside' | 'onSelection' | 'unUnmount'> {
|
|
6
|
+
api?: ExtractInjectionAPI<TablePlugin>;
|
|
7
|
+
}
|
|
8
|
+
export declare const SizeSelector: ({ api, target, popupsMountPoint, popupsBoundariesElement, popupsScrollableElement, }: SizeSelectorProps) => jsx.JSX.Element;
|
|
9
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-table",
|
|
3
|
-
"version": "10.8.
|
|
3
|
+
"version": "10.8.2",
|
|
4
4
|
"description": "Table plugin for the @atlaskit/editor",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@atlaskit/adf-schema": "^47.6.0",
|
|
33
33
|
"@atlaskit/button": "^23.0.0",
|
|
34
34
|
"@atlaskit/custom-steps": "^0.11.0",
|
|
35
|
-
"@atlaskit/editor-common": "^103.
|
|
35
|
+
"@atlaskit/editor-common": "^103.12.0",
|
|
36
36
|
"@atlaskit/editor-palette": "^2.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-accessibility-utils": "^2.0.0",
|
|
38
38
|
"@atlaskit/editor-plugin-analytics": "^2.2.0",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.0",
|
|
55
55
|
"@atlaskit/primitives": "^14.4.0",
|
|
56
56
|
"@atlaskit/theme": "^18.0.0",
|
|
57
|
-
"@atlaskit/tmp-editor-statsig": "^4.
|
|
57
|
+
"@atlaskit/tmp-editor-statsig": "^4.12.0",
|
|
58
58
|
"@atlaskit/toggle": "^15.0.0",
|
|
59
|
-
"@atlaskit/tokens": "^4.
|
|
59
|
+
"@atlaskit/tokens": "^4.8.0",
|
|
60
60
|
"@atlaskit/tooltip": "^20.0.0",
|
|
61
61
|
"@babel/runtime": "^7.0.0",
|
|
62
62
|
"@emotion/react": "^11.7.1",
|
|
@@ -197,6 +197,12 @@
|
|
|
197
197
|
},
|
|
198
198
|
"platform_editor_controls_patch_4": {
|
|
199
199
|
"type": "boolean"
|
|
200
|
+
},
|
|
201
|
+
"platform_editor_tables_table_selector": {
|
|
202
|
+
"type": "boolean"
|
|
203
|
+
},
|
|
204
|
+
"platform_editor_controls_table_picker": {
|
|
205
|
+
"type": "boolean"
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
}
|
|
@@ -39,7 +39,7 @@ interface SentinelData {
|
|
|
39
39
|
// limit scroll event calls
|
|
40
40
|
const HEADER_ROW_SCROLL_THROTTLE_TIMEOUT = 200;
|
|
41
41
|
|
|
42
|
-
// timeout for resetting the scroll class - if it
|
|
42
|
+
// timeout for resetting the scroll class - if it's too long then users won't be able to click on the header cells,
|
|
43
43
|
// if too short it would trigger too many dom updates.
|
|
44
44
|
const HEADER_ROW_SCROLL_RESET_DEBOUNCE_TIMEOUT = 400;
|
|
45
45
|
|
|
@@ -86,6 +86,7 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
86
86
|
private isSticky: boolean;
|
|
87
87
|
private intersectionObserver?: IntersectionObserver;
|
|
88
88
|
private resizeObserver?: ResizeObserver;
|
|
89
|
+
private tableContainerObserver?: MutationObserver;
|
|
89
90
|
private sentinels: {
|
|
90
91
|
top?: HTMLElement | null;
|
|
91
92
|
bottom?: HTMLElement | null;
|
|
@@ -157,6 +158,10 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
157
158
|
|
|
158
159
|
this.emitOff(true);
|
|
159
160
|
}
|
|
161
|
+
|
|
162
|
+
if (this.tableContainerObserver) {
|
|
163
|
+
this.tableContainerObserver.disconnect();
|
|
164
|
+
}
|
|
160
165
|
}
|
|
161
166
|
|
|
162
167
|
ignoreMutation(mutationRecord: MutationRecord | { type: 'selection'; target: Node }) {
|
|
@@ -289,32 +294,36 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
289
294
|
}
|
|
290
295
|
|
|
291
296
|
window.requestAnimationFrame(() => {
|
|
297
|
+
const getTableContainer = () =>
|
|
298
|
+
getTree(this.dom)?.wrapper.closest(`.${TableCssClassName.NODEVIEW_WRAPPER}`);
|
|
299
|
+
|
|
292
300
|
// we expect tree to be defined after animation frame
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
);
|
|
301
|
+
let tableContainer = getTableContainer();
|
|
302
|
+
|
|
296
303
|
if (tableContainer) {
|
|
297
304
|
const getSentinelTop = () =>
|
|
305
|
+
tableContainer &&
|
|
298
306
|
// Ignored via go/ees005
|
|
299
307
|
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
300
|
-
tableContainer
|
|
308
|
+
(tableContainer
|
|
301
309
|
.getElementsByClassName(ClassName.TABLE_STICKY_SENTINEL_TOP)
|
|
302
|
-
.item(0) as HTMLElement;
|
|
310
|
+
.item(0) as HTMLElement);
|
|
303
311
|
const getSentinelBottom = () => {
|
|
304
312
|
// Multiple bottom sentinels may be found if there are nested tables.
|
|
305
313
|
// We need to make sure we get the last one which will belong to the parent table.
|
|
306
|
-
const bottomSentinels =
|
|
307
|
-
|
|
308
|
-
|
|
314
|
+
const bottomSentinels =
|
|
315
|
+
tableContainer &&
|
|
316
|
+
tableContainer.getElementsByClassName(ClassName.TABLE_STICKY_SENTINEL_BOTTOM);
|
|
309
317
|
// Ignored via go/ees005
|
|
310
318
|
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
311
319
|
return fg('platform_editor_nested_tables_bottom_sentinel')
|
|
312
320
|
? // eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
313
|
-
(bottomSentinels.item(bottomSentinels.length - 1) as HTMLElement)
|
|
314
|
-
:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
321
|
+
bottomSentinels && (bottomSentinels.item(bottomSentinels.length - 1) as HTMLElement)
|
|
322
|
+
: tableContainer &&
|
|
323
|
+
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
324
|
+
(tableContainer
|
|
325
|
+
.getElementsByClassName(ClassName.TABLE_STICKY_SENTINEL_BOTTOM)
|
|
326
|
+
.item(0) as HTMLElement);
|
|
318
327
|
};
|
|
319
328
|
|
|
320
329
|
const sentinelsInDom = () => getSentinelTop() !== null && getSentinelBottom() !== null;
|
|
@@ -333,24 +342,57 @@ export default class TableRow extends TableNodeView<HTMLTableRowElement> impleme
|
|
|
333
342
|
});
|
|
334
343
|
};
|
|
335
344
|
|
|
336
|
-
if (
|
|
337
|
-
|
|
338
|
-
|
|
345
|
+
if (fg('platform_editor_table_initial_load_fix')) {
|
|
346
|
+
const isInitialProsemirrorToDomRender = tableContainer.hasAttribute(
|
|
347
|
+
'data-prosemirror-initial-toDOM-render',
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
// Sentinels may be in the DOM but they're part of the prosemirror placeholder structure which is replaced with the fully rendered React node.
|
|
351
|
+
if (sentinelsInDom() && !isInitialProsemirrorToDomRender) {
|
|
352
|
+
// great - DOM ready, observe as normal
|
|
353
|
+
observeStickySentinels();
|
|
354
|
+
} else {
|
|
355
|
+
// concurrent loading issue - here TableRow is too eager trying to
|
|
356
|
+
// observe sentinels before they are in the DOM, use MutationObserver
|
|
357
|
+
// to wait for sentinels to be added to the parent Table node DOM
|
|
358
|
+
// then attach the IntersectionObserver
|
|
359
|
+
this.tableContainerObserver = new MutationObserver(() => {
|
|
360
|
+
// Check if the tableContainer is still connected to the DOM. It can become disconnected when the placholder
|
|
361
|
+
// prosemirror node is replaced with the fully rendered React node (see _handleTableRef).
|
|
362
|
+
if (!tableContainer || !tableContainer.isConnected) {
|
|
363
|
+
tableContainer = getTableContainer();
|
|
364
|
+
}
|
|
365
|
+
if (sentinelsInDom()) {
|
|
366
|
+
observeStickySentinels();
|
|
367
|
+
this.tableContainerObserver?.disconnect();
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const mutatingNode = tableContainer;
|
|
372
|
+
if (mutatingNode && this.tableContainerObserver) {
|
|
373
|
+
this.tableContainerObserver.observe(mutatingNode, { subtree: true, childList: true });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
339
376
|
} else {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
377
|
+
if (sentinelsInDom()) {
|
|
378
|
+
// great - DOM ready, observe as normal
|
|
379
|
+
observeStickySentinels();
|
|
380
|
+
} else {
|
|
381
|
+
// concurrent loading issue - here TableRow is too eager trying to
|
|
382
|
+
// observe sentinels before they are in the DOM, use MutationObserver
|
|
383
|
+
// to wait for sentinels to be added to the parent Table node DOM
|
|
384
|
+
// then attach the IntersectionObserver
|
|
385
|
+
const tableContainerObserver = new MutationObserver(() => {
|
|
386
|
+
if (sentinelsInDom()) {
|
|
387
|
+
observeStickySentinels();
|
|
388
|
+
tableContainerObserver.disconnect();
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const mutatingNode = tableContainer;
|
|
393
|
+
if (mutatingNode) {
|
|
394
|
+
tableContainerObserver.observe(mutatingNode, { subtree: true, childList: true });
|
|
348
395
|
}
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
const mutatingNode = tableContainer;
|
|
352
|
-
if (mutatingNode) {
|
|
353
|
-
tableContainerObserver.observe(mutatingNode, { subtree: true, childList: true });
|
|
354
396
|
}
|
|
355
397
|
}
|
|
356
398
|
}
|
package/src/nodeviews/table.tsx
CHANGED
|
@@ -81,7 +81,7 @@ const handleInlineTableWidth = (table: HTMLElement, width: number | undefined) =
|
|
|
81
81
|
table.style.setProperty('width', `${width}px`);
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
//
|
|
84
|
+
// Remove after removing the platform_editor_table_initial_load_fix flag.
|
|
85
85
|
const toDOM = (node: PmNode, props: Props) => {
|
|
86
86
|
let colgroup: DOMOutputSpec = '';
|
|
87
87
|
if (props.allowColumnResizing) {
|
package/src/nodeviews/toDOM.ts
CHANGED
|
@@ -111,6 +111,7 @@ export const tableNodeSpecWithFixedToDOM = (
|
|
|
111
111
|
'div',
|
|
112
112
|
{
|
|
113
113
|
class: 'tableView-content-wrap',
|
|
114
|
+
'data-prosemirror-initial-toDOM-render': 'true',
|
|
114
115
|
},
|
|
115
116
|
tableContainerDiv,
|
|
116
117
|
];
|
|
@@ -161,6 +162,7 @@ export const tableNodeSpecWithFixedToDOM = (
|
|
|
161
162
|
'div',
|
|
162
163
|
{
|
|
163
164
|
class: 'tableView-content-wrap',
|
|
165
|
+
'data-prosemirror-initial-toDOM-render': 'true',
|
|
164
166
|
},
|
|
165
167
|
tableResizingDiv,
|
|
166
168
|
];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
|
|
5
|
+
type SizeSelectorPluginState = {
|
|
6
|
+
isSelectorOpen: boolean;
|
|
7
|
+
targetRef?: HTMLElement;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const pluginKey = new PluginKey<SizeSelectorPluginState>('tableSizeSelectorPlugin');
|
|
11
|
+
|
|
12
|
+
export const createPlugin = (dispatch: Dispatch) => {
|
|
13
|
+
return new SafePlugin<SizeSelectorPluginState>({
|
|
14
|
+
key: pluginKey,
|
|
15
|
+
state: {
|
|
16
|
+
init: () => ({
|
|
17
|
+
isSelectorOpen: false,
|
|
18
|
+
}),
|
|
19
|
+
apply: (tr, currentPluginState) => {
|
|
20
|
+
const meta = tr.getMeta(pluginKey);
|
|
21
|
+
|
|
22
|
+
if (meta) {
|
|
23
|
+
const keys = Object.keys(meta) as Array<keyof SizeSelectorPluginState>;
|
|
24
|
+
const changed = keys.some((key) => {
|
|
25
|
+
return currentPluginState[key] !== meta[key];
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (changed) {
|
|
29
|
+
const newState = { ...currentPluginState, ...meta };
|
|
30
|
+
|
|
31
|
+
dispatch(pluginKey, newState);
|
|
32
|
+
return newState;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return currentPluginState;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
};
|
package/src/tablePlugin.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '@atlaskit/editor-common/analytics';
|
|
19
19
|
import { browser } from '@atlaskit/editor-common/browser';
|
|
20
20
|
import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
|
|
21
|
+
import { getDomRefFromSelection } from '@atlaskit/editor-common/get-dom-ref-from-selection';
|
|
21
22
|
import { useSharedPluginState } from '@atlaskit/editor-common/hooks';
|
|
22
23
|
import { IconTable } from '@atlaskit/editor-common/icons';
|
|
23
24
|
import { toggleTable, tooltip } from '@atlaskit/editor-common/keymaps';
|
|
@@ -61,6 +62,10 @@ import { createPlugin as createFlexiResizingPlugin } from './pm-plugins/table-re
|
|
|
61
62
|
import { getPluginState as getFlexiResizingPlugin } from './pm-plugins/table-resizing/plugin-factory';
|
|
62
63
|
import { pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing/plugin-key';
|
|
63
64
|
import { tableSelectionKeymapPlugin } from './pm-plugins/table-selection-keymap';
|
|
65
|
+
import {
|
|
66
|
+
createPlugin as createSizeSelectorPlugin,
|
|
67
|
+
pluginKey as sizeSelectorPluginKey,
|
|
68
|
+
} from './pm-plugins/table-size-selector';
|
|
64
69
|
import {
|
|
65
70
|
createPlugin as createTableWidthPlugin,
|
|
66
71
|
pluginKey as tableWidthPluginKey,
|
|
@@ -79,6 +84,7 @@ import FloatingDragMenu from './ui/FloatingDragMenu';
|
|
|
79
84
|
import FloatingInsertButton from './ui/FloatingInsertButton';
|
|
80
85
|
import { FloatingToolbarLabel } from './ui/FloatingToolbarLabel/FloatingToolbarLabel';
|
|
81
86
|
import { GlobalStylesWrapper } from './ui/global-styles';
|
|
87
|
+
import { SizeSelector } from './ui/SizeSelector';
|
|
82
88
|
import { FullWidthDisplay } from './ui/TableFullWidthLabel';
|
|
83
89
|
import { getToolbarConfig } from './ui/toolbar';
|
|
84
90
|
|
|
@@ -109,6 +115,14 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
109
115
|
// When in comment editor, we need the scaling percent to be 40% while tableWithFixedColumnWidthsOption is not visible
|
|
110
116
|
options?.isCommentEditor);
|
|
111
117
|
|
|
118
|
+
const isTableSelectorEnabled =
|
|
119
|
+
// eslint-disable-next-line @atlaskit/platform/no-preconditioning
|
|
120
|
+
!options?.isChromelessEditor &&
|
|
121
|
+
!options?.isCommentEditor &&
|
|
122
|
+
options?.getEditorFeatureFlags?.().tableSelector &&
|
|
123
|
+
editorExperiment('platform_editor_controls', 'variant1') &&
|
|
124
|
+
fg('platform_editor_controls_table_picker');
|
|
125
|
+
|
|
112
126
|
return {
|
|
113
127
|
name: 'table',
|
|
114
128
|
|
|
@@ -487,6 +501,11 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
487
501
|
});
|
|
488
502
|
},
|
|
489
503
|
},
|
|
504
|
+
{
|
|
505
|
+
name: 'tableSizeSelectorPlugin',
|
|
506
|
+
plugin: ({ dispatch }) =>
|
|
507
|
+
isTableSelectorEnabled ? createSizeSelectorPlugin(dispatch) : undefined,
|
|
508
|
+
},
|
|
490
509
|
];
|
|
491
510
|
|
|
492
511
|
// Workaround for table element breaking issue caused by composition event with an inputType of deleteCompositionText.
|
|
@@ -529,6 +548,7 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
529
548
|
tableResizingPluginState: tableResizingPluginKey,
|
|
530
549
|
stickyHeadersState: stickyHeadersPluginKey,
|
|
531
550
|
dragAndDropState: dragAndDropPluginKey,
|
|
551
|
+
sizeSelectorPluginState: sizeSelectorPluginKey,
|
|
532
552
|
}}
|
|
533
553
|
render={({
|
|
534
554
|
tableResizingPluginState: resizingPluginState,
|
|
@@ -536,6 +556,7 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
536
556
|
tablePluginState,
|
|
537
557
|
tableWidthPluginState,
|
|
538
558
|
dragAndDropState,
|
|
559
|
+
sizeSelectorPluginState,
|
|
539
560
|
}) => {
|
|
540
561
|
const isColumnResizing = resizingPluginState?.dragging;
|
|
541
562
|
const isTableResizing = tableWidthPluginState?.resizing;
|
|
@@ -543,6 +564,7 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
543
564
|
const resizingTableRef = tableWidthPluginState?.tableRef;
|
|
544
565
|
const isResizing = isColumnResizing || isTableResizing;
|
|
545
566
|
const widthToWidest = tablePluginState?.widthToWidest;
|
|
567
|
+
const isSizeSelectorOpen = sizeSelectorPluginState?.isSelectorOpen;
|
|
546
568
|
|
|
547
569
|
const {
|
|
548
570
|
tableNode,
|
|
@@ -695,6 +717,24 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
695
717
|
offset={[0, 10]}
|
|
696
718
|
/>
|
|
697
719
|
)}
|
|
720
|
+
|
|
721
|
+
{isTableSelectorEnabled && isSizeSelectorOpen && (
|
|
722
|
+
<SizeSelector
|
|
723
|
+
api={api}
|
|
724
|
+
isOpenedByKeyboard={false}
|
|
725
|
+
popupsMountPoint={popupsMountPoint}
|
|
726
|
+
target={
|
|
727
|
+
sizeSelectorPluginState?.targetRef ??
|
|
728
|
+
getDomRefFromSelection(
|
|
729
|
+
editorView,
|
|
730
|
+
ACTION_SUBJECT_ID.PICKER_TABLE_SIZE,
|
|
731
|
+
api?.analytics?.actions.fireAnalyticsEvent,
|
|
732
|
+
)
|
|
733
|
+
}
|
|
734
|
+
popupsBoundariesElement={popupsBoundariesElement}
|
|
735
|
+
popupsScrollableElement={popupsScrollableElement}
|
|
736
|
+
/>
|
|
737
|
+
)}
|
|
698
738
|
</>
|
|
699
739
|
);
|
|
700
740
|
}}
|
|
@@ -714,6 +754,15 @@ const tablePlugin: TablePlugin = ({ config: options, api }) => {
|
|
|
714
754
|
keyshortcut: tooltip(toggleTable),
|
|
715
755
|
icon: () => <IconTable />,
|
|
716
756
|
action(insert, state) {
|
|
757
|
+
if (isTableSelectorEnabled) {
|
|
758
|
+
const tr = insert('');
|
|
759
|
+
tr.setMeta(sizeSelectorPluginKey, {
|
|
760
|
+
isSelectorOpen: true,
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
return tr;
|
|
764
|
+
}
|
|
765
|
+
|
|
717
766
|
// see comment on tablesPlugin.getSharedState on usage
|
|
718
767
|
const tableState = api?.table?.sharedState.currentState();
|
|
719
768
|
const tableNodeProps = {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jsxRuntime classic
|
|
3
|
+
* @jsx jsx
|
|
4
|
+
*/
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
|
|
8
|
+
import { jsx } from '@emotion/react';
|
|
9
|
+
|
|
10
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
11
|
+
import { TableSelectorPopup, type TableSelectorPopupProps } from '@atlaskit/editor-common/ui';
|
|
12
|
+
|
|
13
|
+
import { pluginKey } from '../../pm-plugins/table-size-selector';
|
|
14
|
+
import { TablePlugin } from '../../tablePluginType';
|
|
15
|
+
|
|
16
|
+
interface SizeSelectorProps
|
|
17
|
+
extends Omit<TableSelectorPopupProps, 'handleClickOutside' | 'onSelection' | 'unUnmount'> {
|
|
18
|
+
api?: ExtractInjectionAPI<TablePlugin>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const DEFAULT_TABLE_SELECTOR_COLS = 3;
|
|
22
|
+
const DEFAULT_TABLE_SELECTOR_ROWS = 3;
|
|
23
|
+
|
|
24
|
+
export const SizeSelector = ({
|
|
25
|
+
api,
|
|
26
|
+
target,
|
|
27
|
+
popupsMountPoint,
|
|
28
|
+
popupsBoundariesElement,
|
|
29
|
+
popupsScrollableElement,
|
|
30
|
+
}: SizeSelectorProps) => {
|
|
31
|
+
const closeSelectorPopup = useCallback(() => {
|
|
32
|
+
api?.core.actions.execute(({ tr }) => {
|
|
33
|
+
tr.setMeta(pluginKey, {
|
|
34
|
+
isSelectorOpen: false,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return tr;
|
|
38
|
+
});
|
|
39
|
+
}, [api]);
|
|
40
|
+
|
|
41
|
+
const onSelection = useCallback(
|
|
42
|
+
(rowsCount: number, colsCount: number) => {
|
|
43
|
+
api?.core.actions.execute(({ tr }) => {
|
|
44
|
+
api?.table.commands.insertTableWithSize(rowsCount, colsCount)({ tr });
|
|
45
|
+
|
|
46
|
+
tr.setMeta(pluginKey, {
|
|
47
|
+
isSelectorOpen: false,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return tr;
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
[api],
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const onUnmount = () => {
|
|
57
|
+
api?.core.actions.focus();
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<TableSelectorPopup
|
|
62
|
+
defaultSize={{ row: DEFAULT_TABLE_SELECTOR_ROWS, col: DEFAULT_TABLE_SELECTOR_COLS }}
|
|
63
|
+
target={target}
|
|
64
|
+
onUnmount={onUnmount}
|
|
65
|
+
onSelection={onSelection}
|
|
66
|
+
popupsMountPoint={popupsMountPoint}
|
|
67
|
+
popupsScrollableElement={popupsScrollableElement}
|
|
68
|
+
popupsBoundariesElement={popupsBoundariesElement}
|
|
69
|
+
isOpenedByKeyboard={true}
|
|
70
|
+
handleClickOutside={closeSelectorPopup}
|
|
71
|
+
handleEscapeKeydown={closeSelectorPopup}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
};
|