@atlaskit/editor-plugin-table 0.2.5 → 1.0.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/cjs/plugins/table/commands/index.js +9 -1
  3. package/dist/cjs/plugins/table/commands/referentiality.js +23 -0
  4. package/dist/cjs/plugins/table/event-handlers.js +5 -1
  5. package/dist/cjs/plugins/table/nodeviews/table.js +10 -1
  6. package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  7. package/dist/cjs/plugins/table/toolbar.js +78 -35
  8. package/dist/cjs/plugins/table/ui/common-styles.js +6 -3
  9. package/dist/cjs/plugins/table/ui/messages.js +17 -2
  10. package/dist/cjs/plugins/table/ui/ui-styles.js +2 -7
  11. package/dist/cjs/version.json +1 -1
  12. package/dist/es2019/plugins/table/commands/index.js +2 -1
  13. package/dist/es2019/plugins/table/commands/referentiality.js +10 -0
  14. package/dist/es2019/plugins/table/event-handlers.js +3 -1
  15. package/dist/es2019/plugins/table/nodeviews/table.js +13 -1
  16. package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +16 -11
  17. package/dist/es2019/plugins/table/toolbar.js +65 -29
  18. package/dist/es2019/plugins/table/ui/common-styles.js +15 -5
  19. package/dist/es2019/plugins/table/ui/messages.js +17 -2
  20. package/dist/es2019/plugins/table/ui/ui-styles.js +24 -16
  21. package/dist/es2019/version.json +1 -1
  22. package/dist/esm/plugins/table/commands/index.js +2 -1
  23. package/dist/esm/plugins/table/commands/referentiality.js +12 -0
  24. package/dist/esm/plugins/table/event-handlers.js +5 -1
  25. package/dist/esm/plugins/table/nodeviews/table.js +10 -1
  26. package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  27. package/dist/esm/plugins/table/toolbar.js +74 -29
  28. package/dist/esm/plugins/table/ui/common-styles.js +6 -3
  29. package/dist/esm/plugins/table/ui/messages.js +17 -2
  30. package/dist/esm/plugins/table/ui/ui-styles.js +2 -6
  31. package/dist/esm/version.json +1 -1
  32. package/dist/types/plugins/table/commands/index.d.ts +1 -0
  33. package/dist/types/plugins/table/commands/referentiality.d.ts +2 -0
  34. package/dist/types/plugins/table/index.d.ts +2 -3
  35. package/dist/types/plugins/table/nodeviews/table.d.ts +4 -1
  36. package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +0 -1
  37. package/dist/types/plugins/table/ui/common-styles.d.ts +4 -1
  38. package/dist/types/plugins/table/ui/messages.d.ts +15 -0
  39. package/package.json +7 -7
  40. package/report.api.md +6 -6
  41. package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +130 -0
  42. package/src/__tests__/integration/floating-toolbar.ts +54 -0
  43. package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +37 -0
  44. package/src/__tests__/unit/color-picker.ts +100 -0
  45. package/src/__tests__/unit/get-toolbar-config.ts +1 -4
  46. package/src/__tests__/unit/keymap.ts +1 -1
  47. package/src/__tests__/unit/nodeviews/cell.ts +52 -57
  48. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +90 -8
  49. package/src/__tests__/unit/transforms/delete-columns.ts +1 -1
  50. package/src/__tests__/unit/transforms/delete-rows.ts +1 -1
  51. package/src/__tests__/unit/utils/collapse.ts +2 -2
  52. package/src/plugins/table/commands/index.ts +1 -0
  53. package/src/plugins/table/commands/referentiality.ts +14 -0
  54. package/src/plugins/table/event-handlers.ts +7 -1
  55. package/src/plugins/table/index.tsx +6 -1
  56. package/src/plugins/table/nodeviews/table.tsx +16 -1
  57. package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +12 -10
  58. package/src/plugins/table/toolbar.tsx +84 -28
  59. package/src/plugins/table/ui/common-styles.ts +20 -4
  60. package/src/plugins/table/ui/messages.ts +18 -3
  61. package/src/plugins/table/ui/ui-styles.ts +23 -14
  62. package/dist/cjs/plugins/table/utils/referentiality.js +0 -29
  63. package/dist/es2019/plugins/table/utils/referentiality.js +0 -18
  64. package/dist/esm/plugins/table/utils/referentiality.js +0 -20
  65. package/dist/types/plugins/table/utils/referentiality.d.ts +0 -2
  66. package/src/plugins/table/utils/referentiality.ts +0 -24
@@ -0,0 +1,130 @@
1
+ {
2
+ "version": 1,
3
+ "type": "doc",
4
+ "content": [
5
+ {
6
+ "type": "table",
7
+ "attrs": {
8
+ "isNumberColumnEnabled": false,
9
+ "layout": "default",
10
+ "localId": "e1365400-6226-4bb9-b3f1-b80fd3ae640a"
11
+ },
12
+ "content": [
13
+ {
14
+ "type": "tableRow",
15
+ "content": [
16
+ {
17
+ "type": "tableHeader",
18
+ "attrs": {},
19
+ "content": [
20
+ {
21
+ "type": "paragraph",
22
+ "content": []
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "type": "tableHeader",
28
+ "attrs": {},
29
+ "content": [
30
+ {
31
+ "type": "paragraph",
32
+ "content": []
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "type": "tableHeader",
38
+ "attrs": {},
39
+ "content": [
40
+ {
41
+ "type": "paragraph",
42
+ "content": []
43
+ }
44
+ ]
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "type": "tableRow",
50
+ "content": [
51
+ {
52
+ "type": "tableCell",
53
+ "attrs": {},
54
+ "content": [
55
+ {
56
+ "type": "paragraph",
57
+ "content": []
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "type": "tableCell",
63
+ "attrs": {},
64
+ "content": [
65
+ {
66
+ "type": "paragraph",
67
+ "content": []
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ "type": "tableCell",
73
+ "attrs": {},
74
+ "content": [
75
+ {
76
+ "type": "paragraph",
77
+ "content": []
78
+ }
79
+ ]
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ "type": "tableRow",
85
+ "content": [
86
+ {
87
+ "type": "tableCell",
88
+ "attrs": {},
89
+ "content": [
90
+ {
91
+ "type": "paragraph",
92
+ "content": []
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ "type": "tableCell",
98
+ "attrs": {},
99
+ "content": [
100
+ {
101
+ "type": "paragraph",
102
+ "content": []
103
+ }
104
+ ]
105
+ },
106
+ {
107
+ "type": "tableCell",
108
+ "attrs": {},
109
+ "content": [
110
+ {
111
+ "type": "paragraph",
112
+ "content": []
113
+ }
114
+ ]
115
+ }
116
+ ]
117
+ }
118
+ ]
119
+ },
120
+ {
121
+ "type": "paragraph",
122
+ "content": [
123
+ {
124
+ "type": "text",
125
+ "text": "text"
126
+ }
127
+ ]
128
+ }
129
+ ]
130
+ }
@@ -16,6 +16,7 @@ import {
16
16
  import { BrowserTestCase } from '@atlaskit/webdriver-runner/runner';
17
17
  import { TableCssClassName } from '../../plugins/table/types';
18
18
  import basicTable from './__fixtures__/basic-table';
19
+ import { documentWithMergedCells } from './__fixtures__/merged-rows-and-cols-document';
19
20
 
20
21
  BrowserTestCase(
21
22
  'should floating toolbar context menu sit above other context menu layers',
@@ -167,3 +168,56 @@ BrowserTestCase(
167
168
  expect(doc).toMatchCustomDocSnapshot(testName);
168
169
  },
169
170
  );
171
+
172
+ BrowserTestCase(
173
+ 'should show tooltip on hover on disabled sort button then remove it on mouse out',
174
+ { skip: ['safari'] }, // The test does not pass on CI but works on physical browser
175
+ async (client: any, testName: string) => {
176
+ const page = await goToEditorTestingWDExample(
177
+ client,
178
+ 'editor-plugin-table',
179
+ );
180
+ await mountEditor(page, {
181
+ appearance: fullpage.appearance,
182
+ allowTables: {
183
+ allowColumnSorting: true,
184
+ allowDistributeColumns: true,
185
+ allowCellOptionsInFloatingToolbar: true,
186
+ },
187
+ defaultValue: documentWithMergedCells,
188
+ });
189
+ const tableFloatingToolbarContextMenuSelector = `div[aria-label="Table floating controls"][data-editor-popup=true]`;
190
+ const sortAtoZButtonSelector =
191
+ 'div[data-role=droplistContent] div[role=presentation]';
192
+ const sortZtoAButtonSelector =
193
+ 'div[data-role=droplistContent] div[role=presentation]:nth-of-type(2)';
194
+ const tooltipSelector = 'div.atlaskit-portal div[role=tooltip]';
195
+
196
+ // Click on the cell on the table
197
+ await clickFirstCell(page);
198
+
199
+ // Table floating toolbar should appear, then hover on "Cell Options", which brings up another context menu
200
+ const cellOptionsMenuItem = await (
201
+ await page.$(tableFloatingToolbarContextMenuSelector)
202
+ ).$(`button=${tableSelectors.cellOptionsFloatingToolbarText}`);
203
+ await cellOptionsMenuItem.waitForClickable();
204
+ await cellOptionsMenuItem.click();
205
+
206
+ // No tooltip is shown
207
+ expect((await page.$$(tooltipSelector)).length).toBe(0);
208
+
209
+ // Hover Sort column A -> Z button then it should show tooltip
210
+ const sortAtoZButton = await page.$(sortAtoZButtonSelector);
211
+ await sortAtoZButton.moveTo();
212
+ const tooltip = await page.$(tooltipSelector);
213
+ await tooltip.waitForExist();
214
+ expect((await page.$$(tooltipSelector)).length).toBe(1);
215
+
216
+ // Tooltip should be removed after mouseout to next button
217
+ const sortZtoAButton = await page.$(sortZtoAButtonSelector);
218
+ await sortZtoAButton.moveTo();
219
+ await tooltip.waitUntil(async () => {
220
+ return (await page.$$(tooltipSelector)).length === 0;
221
+ });
222
+ },
223
+ );
@@ -0,0 +1,37 @@
1
+ import { BrowserTestCase } from '@atlaskit/webdriver-runner/runner';
2
+ import {
3
+ fullpage,
4
+ setProseMirrorTextSelection,
5
+ expectToMatchSelection,
6
+ } from '@atlaskit/editor-test-helpers/integration/helpers';
7
+ import {
8
+ goToEditorTestingWDExample,
9
+ mountEditor,
10
+ } from '@atlaskit/editor-test-helpers/testing-example-page';
11
+ import tableAdf from './__fixtures__/table-and-paragraph-adf.json';
12
+
13
+ BrowserTestCase(
14
+ 'meta-arrowup-cursor-in-first-row.ts: pressing command/ctrl + arrow up should move cursor into first row',
15
+ {},
16
+ async (client: any) => {
17
+ const page = await goToEditorTestingWDExample(
18
+ client,
19
+ 'editor-plugin-table',
20
+ );
21
+ await mountEditor(page, {
22
+ appearance: fullpage.appearance,
23
+ allowTables: {},
24
+ defaultValue: tableAdf,
25
+ });
26
+
27
+ await setProseMirrorTextSelection(page, { anchor: 49 });
28
+
29
+ const keys = page.isWindowsPlatform()
30
+ ? ['Control', 'Home']
31
+ : ['Meta', 'ArrowUp'];
32
+
33
+ await page.keys(keys, true);
34
+
35
+ await expectToMatchSelection(page, { type: 'text', to: 4, from: 4 });
36
+ },
37
+ );
@@ -0,0 +1,100 @@
1
+ import {
2
+ doc,
3
+ DocBuilder,
4
+ p,
5
+ table,
6
+ tdCursor,
7
+ tdEmpty,
8
+ tr,
9
+ } from '@atlaskit/editor-test-helpers/doc-builder';
10
+ import {
11
+ createProsemirrorEditorFactory,
12
+ LightEditorPlugin,
13
+ Preset,
14
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
15
+ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
16
+ import type {
17
+ FloatingToolbarButton,
18
+ FloatingToolbarItem,
19
+ GetEditorFeatureFlags,
20
+ } from '@atlaskit/editor-common/types';
21
+ import dataConsumerPlugin from '@atlaskit/editor-core/src/plugins/data-consumer';
22
+ import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
23
+ import tablePlugin from '../../plugins/table';
24
+ import { setEditorFocus, setTableRef } from '../../plugins/table/commands';
25
+ import { getToolbarConfig } from '../../plugins/table/toolbar';
26
+
27
+ const formatMessage: (t: { id: string }) => string = (message) =>
28
+ `${message.id}`;
29
+
30
+ describe('color picker', () => {
31
+ /**
32
+ * Use `createEditorFactory` here to enable referentiality as
33
+ * `createProsemirrorEditorFactory` has some issues with correctly mimicking
34
+ * old state for the unique localId plugin
35
+ */
36
+ const createEditorFn = createProsemirrorEditorFactory();
37
+ const createEditor = (doc: DocBuilder) => {
38
+ const output = createEditorFn({
39
+ doc,
40
+
41
+ attachTo: document.body,
42
+ preset: new Preset<LightEditorPlugin>()
43
+ .add(dataConsumerPlugin)
44
+ .add(extensionPlugin)
45
+ .add(tablePlugin),
46
+ });
47
+
48
+ // Prep the table plugin state a little
49
+ const { editorView } = output;
50
+ const { dispatch } = editorView;
51
+ const tableRef = document.querySelector(
52
+ '.ProseMirror table',
53
+ ) as HTMLTableElement;
54
+ setEditorFocus(true)(output.editorView.state, dispatch);
55
+ setTableRef(tableRef)(output.editorView.state, dispatch);
56
+
57
+ return output;
58
+ };
59
+
60
+ it('should return a corect color picker option if allowBackgroundColor enabled', async () => {
61
+ const { editorView } = createEditor(
62
+ doc(p('text'), table()(tr(tdCursor, tdEmpty))),
63
+ );
64
+ const getEditorContainerWidth = () => ({ width: 500 });
65
+ const editorAnalyticsAPIFake: EditorAnalyticsAPI = {
66
+ attachAnalyticsEvent: jest.fn().mockReturnValue(() => jest.fn()),
67
+ };
68
+
69
+ // Enable tableCellOptionsInFloatingToolbar
70
+ const getEditorFeatureFlags: GetEditorFeatureFlags = jest
71
+ .fn()
72
+ .mockReturnValue({
73
+ tableCellOptionsInFloatingToolbar: true,
74
+ });
75
+
76
+ // Enable allowBackgroundColor feature flag
77
+ const { state } = editorView;
78
+ (state as any).tablePlugin$.pluginConfig.allowBackgroundColor = true;
79
+
80
+ // Create the editor
81
+ const config = getToolbarConfig(
82
+ getEditorContainerWidth,
83
+ editorAnalyticsAPIFake,
84
+ getEditorFeatureFlags,
85
+ () => editorView,
86
+ )({})(state, { formatMessage } as any, {} as any)!;
87
+
88
+ // Let's find the colorPicker from the option items list
89
+ const items =
90
+ typeof config.items === 'function'
91
+ ? config.items(state.doc.firstChild!)
92
+ : config.items;
93
+
94
+ const option = items.find(
95
+ (item: FloatingToolbarItem<any>) =>
96
+ item.type === 'select' && item.id === 'editor.table.colorPicker',
97
+ )! as FloatingToolbarButton<any>;
98
+ expect(option).not.toBeUndefined();
99
+ });
100
+ });
@@ -132,10 +132,7 @@ describe('getToolbarConfig', () => {
132
132
  );
133
133
 
134
134
  const button = getButton(editorView);
135
- expect(button.confirmDialog).toEqual({
136
- message: 'fabric.editor.tables.confirmDeleteLinkedModalMessage',
137
- okButtonLabel: 'fabric.editor.tables.confirmDeleteLinkedModalOKButton',
138
- });
135
+ expect(typeof button.confirmDialog).toBe('function');
139
136
  });
140
137
  });
141
138
  });
@@ -101,7 +101,7 @@ describe('table keymap', () => {
101
101
  .add([statusPlugin, { menuDisabled: false }])
102
102
  .add([mediaPlugin, { allowMediaSingle: true }])
103
103
  .add([analyticsPlugin, { createAnalyticsEvent }])
104
- .add([featureFlagsPlugin]);
104
+ .add([featureFlagsPlugin, {}]);
105
105
 
106
106
  const editor = (doc: DocBuilder) =>
107
107
  createEditor<TablePluginState, PluginKey>({
@@ -100,70 +100,65 @@ describe('table -> nodeviews -> tableCell.tsx', () => {
100
100
  });
101
101
  });
102
102
 
103
- describe('with tableCellOptimization on', () => {
104
- describe('nodeview update', () => {
105
- it('should not recreate nodeviews on attrs update', () => {
106
- const {
107
- editorView,
108
- refs: { pos },
109
- } = editor(
110
- doc(p('text'), table()(tr(td()(p('{pos}text')), tdEmpty, tdEmpty))),
111
- {
112
- tableCellOptimization: true,
113
- },
114
- );
115
- const { state, dispatch } = editorView;
116
- const cell = findCellClosestToPos(state.doc.resolve(pos))!;
117
- const background = tableBackgroundColorNames.get('red');
118
- const updateSpy = jest.spyOn(TableCellViews.prototype, 'update');
119
- dispatch(setCellAttrs(cell, { background })(state.tr));
120
- expect(updateSpy).toHaveReturnedWith(true);
121
- const cellDomNode = document.querySelector('td')!;
122
- expect(rgbToHex(cellDomNode.style.backgroundColor!)).toEqual(
123
- background,
124
- );
125
- });
103
+ describe('nodeview update', () => {
104
+ it('should not recreate nodeviews on attrs update', () => {
105
+ const {
106
+ editorView,
107
+ refs: { pos },
108
+ } = editor(
109
+ doc(p('text'), table()(tr(td()(p('{pos}text')), tdEmpty, tdEmpty))),
110
+ {
111
+ tableCellOptimization: true,
112
+ },
113
+ );
114
+ const { state, dispatch } = editorView;
115
+ const cell = findCellClosestToPos(state.doc.resolve(pos))!;
116
+ const background = tableBackgroundColorNames.get('red');
117
+ const updateSpy = jest.spyOn(TableCellViews.prototype, 'update');
118
+ dispatch(setCellAttrs(cell, { background })(state.tr));
119
+ expect(updateSpy).toHaveReturnedWith(true);
120
+ const cellDomNode = document.querySelector('td')!;
121
+ expect(rgbToHex(cellDomNode.style.backgroundColor!)).toEqual(background);
122
+ });
126
123
 
127
- it('preserves correct rowspan and colspan after merge cells and undo', () => {
128
- jest.spyOn(domHelpers, 'getTop').mockImplementation(() => 0);
124
+ it('should preserve the correct rowspan and colspan after merge cells and undo', () => {
125
+ jest.spyOn(domHelpers, 'getTop').mockImplementation(() => 0);
129
126
 
130
- const originalDoc = doc(
127
+ const originalDoc = doc(
128
+ table({ localId: TABLE_LOCAL_ID })(
129
+ tr(th()(p('{<cell}')), thEmpty, thEmpty),
130
+ tr(td()(p('{cell>}')), tdEmpty, tdEmpty),
131
+ tr(tdEmpty, tdEmpty, tdEmpty),
132
+ ),
133
+ );
134
+ const { editorView } = editor(originalDoc, {
135
+ stickyHeaders: true,
136
+ });
137
+ const { state, dispatch } = editorView;
138
+
139
+ dispatch(mergeCells(state.tr));
140
+ expect(editorView.state.doc).toEqualDocument(
141
+ doc(
131
142
  table({ localId: TABLE_LOCAL_ID })(
132
- tr(th()(p('{<cell}')), thEmpty, thEmpty),
133
- tr(td()(p('{cell>}')), tdEmpty, tdEmpty),
143
+ tr(th({ rowspan: 2 })(p('')), thEmpty, thEmpty),
144
+ tr(tdEmpty, tdEmpty),
134
145
  tr(tdEmpty, tdEmpty, tdEmpty),
135
146
  ),
136
- );
137
- const { editorView } = editor(originalDoc, {
138
- stickyHeaders: true,
139
- tableCellOptimization: true,
140
- });
141
- const { state, dispatch } = editorView;
147
+ ),
148
+ );
142
149
 
143
- dispatch(mergeCells(state.tr));
144
- expect(editorView.state.doc).toEqualDocument(
145
- doc(
146
- table({ localId: TABLE_LOCAL_ID })(
147
- tr(th({ rowspan: 2 })(p('')), thEmpty, thEmpty),
148
- tr(tdEmpty, tdEmpty),
149
- tr(tdEmpty, tdEmpty, tdEmpty),
150
- ),
151
- ),
152
- );
150
+ sendKeyToPm(editorView, 'Mod-z');
151
+ validateUnmergedDomCells();
152
+ expect(editorView.state.doc).toEqualDocument(originalDoc);
153
+ });
153
154
 
154
- sendKeyToPm(editorView, 'Mod-z');
155
- validateUnmergedDomCells();
156
- expect(editorView.state.doc).toEqualDocument(originalDoc);
155
+ // make sure all colspan/rowspan attributes are removed from cells
156
+ function validateUnmergedDomCells() {
157
+ const cells = document.querySelectorAll('table td, table th');
158
+ Array.from(cells).forEach((cell) => {
159
+ expect(cell.getAttribute('rowspan')).toBeFalsy();
160
+ expect(cell.getAttribute('colspan')).toBeFalsy();
157
161
  });
158
-
159
- // make sure all colspan/rowspan attributes are removed from cells
160
- function validateUnmergedDomCells() {
161
- const cells = document.querySelectorAll('table td, table th');
162
- Array.from(cells).forEach((cell) => {
163
- expect(cell.getAttribute('rowspan')).toBeFalsy();
164
- expect(cell.getAttribute('colspan')).toBeFalsy();
165
- });
166
- }
167
- });
162
+ }
168
163
  });
169
164
  });
@@ -54,9 +54,10 @@ describe('TableRowNodeView', () => {
54
54
  return createEditor({
55
55
  doc,
56
56
  preset: new Preset<LightEditorPlugin>()
57
- .add([tablePlugin])
57
+ .add(tablePlugin)
58
58
  .add([featureFlagsPlugin, featureFlags]),
59
59
  pluginKey,
60
+ attachTo: document.body,
60
61
  });
61
62
  };
62
63
  let editorView: EditorView;
@@ -81,7 +82,7 @@ describe('TableRowNodeView', () => {
81
82
  const editorWithTableSticky = (doc: DocBuilder) =>
82
83
  createEditor({
83
84
  doc,
84
- preset: new Preset<LightEditorPlugin>().add([tablePlugin]),
85
+ preset: new Preset<LightEditorPlugin>().add(tablePlugin),
85
86
  pluginKey,
86
87
  });
87
88
  const editorData = editorWithTableSticky(
@@ -349,44 +350,42 @@ describe('TableRowNodeView', () => {
349
350
  tableRowNodeView.dom = tableRowDom;
350
351
  });
351
352
 
353
+ afterEach(() => {
354
+ jest.clearAllMocks();
355
+ });
356
+
352
357
  function getTableElements(tableRowDom: HTMLTableRowElement) {
353
358
  const tableWrapper = tableRowDom.closest(
354
359
  `.${TableCssClassName.NODEVIEW_WRAPPER}`,
355
360
  );
356
361
  const tableElement = tableRowDom.closest('table');
357
362
  const tableParent = tableElement?.parentElement;
358
-
359
363
  const scrollContainer = tableWrapper?.parentElement;
360
364
  return { tableWrapper, tableElement, tableParent, scrollContainer };
361
365
  }
362
-
363
366
  function mockScrollPositions(tableRowDom: HTMLTableRowElement) {
364
367
  const { tableWrapper, tableParent, scrollContainer } =
365
368
  getTableElements(tableRowDom);
366
369
  (findOverflowScrollParent as unknown as jest.SpyInstance).mockReturnValue(
367
370
  scrollContainer,
368
371
  );
369
-
370
372
  jest
371
373
  .spyOn(scrollContainer as HTMLElement, 'getBoundingClientRect')
372
374
  .mockImplementationOnce(() => ({
373
375
  ...baseBoundingRect,
374
376
  top: -50,
375
377
  }));
376
-
377
378
  jest
378
379
  .spyOn(tableParent as HTMLElement, 'getBoundingClientRect')
379
380
  .mockImplementationOnce(() => ({
380
381
  ...baseBoundingRect,
381
382
  }));
382
-
383
383
  jest
384
384
  .spyOn(tableWrapper as HTMLElement, 'getBoundingClientRect')
385
385
  .mockImplementationOnce(() => ({
386
386
  ...baseBoundingRect,
387
387
  top: -100,
388
388
  }));
389
-
390
389
  return scrollContainer;
391
390
  }
392
391
 
@@ -580,4 +579,87 @@ describe('TableRowNodeView', () => {
580
579
  expect(sentinelBottom.dataset.isObserved).toBeUndefined();
581
580
  });
582
581
  });
582
+
583
+ describe('makeRowHeaderNotSticky', () => {
584
+ let makeRowHeaderNotStickySpy: jest.SpyInstance;
585
+ let tableRef: HTMLElement;
586
+ beforeEach(() => {
587
+ const editorData = editor(
588
+ doc(table()(tr(thEmpty, thEmpty), tr(tdEmpty, tdEmpty))),
589
+ true, // toggle to enable optimization
590
+ );
591
+ editorView = editorData.editorView;
592
+ eventDispatcher = editorData.eventDispatcher;
593
+ tableRowNode = editorView.state.doc.firstChild!.firstChild!;
594
+ tableRowDom = editorView.dom.getElementsByTagName('tr')[0];
595
+
596
+ tableRowNodeView = new TableRowNodeView(
597
+ tableRowNode,
598
+ editorView,
599
+ jest.fn(),
600
+ eventDispatcher,
601
+ fakeGetEditorFeatureFlags,
602
+ );
603
+ tableRowNodeView.dom = tableRowDom;
604
+
605
+ // Initialize with sticky off
606
+ tableRowNodeView.isSticky = false;
607
+ tableRowNodeView.top = 0;
608
+ tableRowNodeView.padding = 0;
609
+
610
+ makeRowHeaderNotStickySpy = jest.spyOn(
611
+ tableRowNodeView as any,
612
+ 'makeRowHeaderNotSticky',
613
+ );
614
+ tableRef = document.querySelector(
615
+ '.ProseMirror table',
616
+ ) as HTMLTableElement;
617
+ });
618
+
619
+ afterEach(() => {
620
+ jest.clearAllMocks();
621
+ });
622
+
623
+ it('should not be called if table is not selected', () => {
624
+ eventDispatcher.emit((pluginKey as any).key, {
625
+ isHeaderRowEnabled: false,
626
+ tableRef: null,
627
+ });
628
+ expect(makeRowHeaderNotStickySpy).not.toHaveBeenCalled();
629
+ });
630
+
631
+ it('should not be called if header row is enabled', () => {
632
+ eventDispatcher.emit((pluginKey as any).key, {
633
+ isHeaderRowEnabled: true,
634
+ tableRef,
635
+ });
636
+ expect(makeRowHeaderNotStickySpy).not.toHaveBeenCalled();
637
+ });
638
+
639
+ it('should be called if header row is disabled and table is selected', () => {
640
+ eventDispatcher.emit((pluginKey as any).key, {
641
+ isHeaderRowEnabled: false,
642
+ tableRef,
643
+ });
644
+ expect(makeRowHeaderNotStickySpy).toHaveBeenCalled();
645
+ });
646
+
647
+ it('should cause isSticky state to be set to false when called', () => {
648
+ // Begin test with stickyheaders state on
649
+ tableRowNodeView.isSticky = true;
650
+ tableRowNodeView.top = 1;
651
+ tableRowNodeView.padding = 1;
652
+
653
+ tableRowNodeView.makeRowHeaderNotSticky(tableRef);
654
+
655
+ expect(updateStickyState).toHaveBeenCalledWith(
656
+ expect.objectContaining({
657
+ sticky: false,
658
+ }),
659
+ );
660
+ expect(tableRowNodeView.isSticky).toBe(false);
661
+ expect(tableRowNodeView.top).toBe(0);
662
+ expect(tableRowNodeView.padding).toBe(0);
663
+ });
664
+ });
583
665
  });
@@ -41,7 +41,7 @@ describe('table plugin -> transforms -> delete columns', () => {
41
41
  });
42
42
 
43
43
  const createEditor = createProsemirrorEditorFactory();
44
- const preset = new Preset<LightEditorPlugin>().add([tablePlugin]);
44
+ const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
45
45
 
46
46
  const editor = (doc: DocBuilder) =>
47
47
  createEditor<TablePluginState, PluginKey>({
@@ -41,7 +41,7 @@ describe('table plugin -> transforms -> delete rows', () => {
41
41
  uuid.setStatic(false);
42
42
  });
43
43
  const createEditor = createProsemirrorEditorFactory();
44
- const preset = new Preset<LightEditorPlugin>().add([tablePlugin]);
44
+ const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
45
45
 
46
46
  const editor = (doc: DocBuilder) =>
47
47
  createEditor<TablePluginState, PluginKey>({
@@ -23,9 +23,9 @@ describe('collapse', () => {
23
23
  const createEditor = createProsemirrorEditorFactory();
24
24
 
25
25
  const editor = (doc: DocBuilder, expandInPlugins?: boolean) => {
26
- const preset = new Preset<LightEditorPlugin>().add([tablePlugin]);
26
+ const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
27
27
 
28
- const finalPreset = expandInPlugins ? preset.add([expandPlugin]) : preset;
28
+ const finalPreset = expandInPlugins ? preset.add(expandPlugin) : preset;
29
29
 
30
30
  return createEditor({ doc, preset: finalPreset });
31
31
  };
@@ -38,3 +38,4 @@ export {
38
38
  } from './misc';
39
39
  export { sortByColumn } from './sort';
40
40
  export { goToNextCell } from './go-to-next-cell';
41
+ export { removeDescendantNodes } from './referentiality';