@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.
Files changed (32) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/nodeviews/TableRow.js +68 -28
  3. package/dist/cjs/nodeviews/table.js +1 -1
  4. package/dist/cjs/nodeviews/toDOM.js +4 -2
  5. package/dist/cjs/pm-plugins/table-size-selector.js +40 -0
  6. package/dist/cjs/tablePlugin.js +63 -32
  7. package/dist/cjs/ui/SizeSelector/index.js +65 -0
  8. package/dist/es2019/nodeviews/TableRow.js +65 -24
  9. package/dist/es2019/nodeviews/table.js +1 -1
  10. package/dist/es2019/nodeviews/toDOM.js +4 -2
  11. package/dist/es2019/pm-plugins/table-size-selector.js +31 -0
  12. package/dist/es2019/tablePlugin.js +33 -3
  13. package/dist/es2019/ui/SizeSelector/index.js +61 -0
  14. package/dist/esm/nodeviews/TableRow.js +68 -28
  15. package/dist/esm/nodeviews/table.js +1 -1
  16. package/dist/esm/nodeviews/toDOM.js +4 -2
  17. package/dist/esm/pm-plugins/table-size-selector.js +33 -0
  18. package/dist/esm/tablePlugin.js +63 -32
  19. package/dist/esm/ui/SizeSelector/index.js +58 -0
  20. package/dist/types/nodeviews/TableRow.d.ts +1 -0
  21. package/dist/types/pm-plugins/table-size-selector.d.ts +10 -0
  22. package/dist/types/ui/SizeSelector/index.d.ts +9 -0
  23. package/dist/types-ts4.5/nodeviews/TableRow.d.ts +1 -0
  24. package/dist/types-ts4.5/pm-plugins/table-size-selector.d.ts +10 -0
  25. package/dist/types-ts4.5/ui/SizeSelector/index.d.ts +9 -0
  26. package/package.json +10 -4
  27. package/src/nodeviews/TableRow.ts +72 -30
  28. package/src/nodeviews/table.tsx +1 -1
  29. package/src/nodeviews/toDOM.ts +2 -0
  30. package/src/pm-plugins/table-size-selector.ts +39 -0
  31. package/src/tablePlugin.tsx +49 -0
  32. 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.0",
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.7.0",
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.8.0",
57
+ "@atlaskit/tmp-editor-statsig": "^4.12.0",
58
58
  "@atlaskit/toggle": "^15.0.0",
59
- "@atlaskit/tokens": "^4.7.0",
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 its too long then users wont be able to click on the header cells,
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
- const tableContainer = getTree(this.dom)?.wrapper.closest(
294
- `.${TableCssClassName.NODEVIEW_WRAPPER}`,
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 = tableContainer.getElementsByClassName(
307
- ClassName.TABLE_STICKY_SENTINEL_BOTTOM,
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
- : // eslint-disable-next-line @atlaskit/editor/no-as-casting
315
- (tableContainer
316
- .getElementsByClassName(ClassName.TABLE_STICKY_SENTINEL_BOTTOM)
317
- .item(0) as HTMLElement);
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 (sentinelsInDom()) {
337
- // great - DOM ready, observe as normal
338
- observeStickySentinels();
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
- // concurrent loading issue - here TableRow is too eager trying to
341
- // observe sentinels before they are in the DOM, use MutationObserver
342
- // to wait for sentinels to be added to the parent Table node DOM
343
- // then attach the IntersectionObserver
344
- const tableContainerObserver = new MutationObserver(() => {
345
- if (sentinelsInDom()) {
346
- observeStickySentinels();
347
- tableContainerObserver.disconnect();
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
  }
@@ -81,7 +81,7 @@ const handleInlineTableWidth = (table: HTMLElement, width: number | undefined) =
81
81
  table.style.setProperty('width', `${width}px`);
82
82
  };
83
83
 
84
- // Leave as a fallback incase the table's NodeSpec.toDOM is not defined.
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) {
@@ -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
+ };
@@ -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
+ };