@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.
- package/CHANGELOG.md +40 -0
- package/dist/cjs/plugins/table/commands/index.js +9 -1
- package/dist/cjs/plugins/table/commands/referentiality.js +23 -0
- package/dist/cjs/plugins/table/event-handlers.js +5 -1
- package/dist/cjs/plugins/table/nodeviews/table.js +10 -1
- package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
- package/dist/cjs/plugins/table/toolbar.js +78 -35
- package/dist/cjs/plugins/table/ui/common-styles.js +6 -3
- package/dist/cjs/plugins/table/ui/messages.js +17 -2
- package/dist/cjs/plugins/table/ui/ui-styles.js +2 -7
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/plugins/table/commands/index.js +2 -1
- package/dist/es2019/plugins/table/commands/referentiality.js +10 -0
- package/dist/es2019/plugins/table/event-handlers.js +3 -1
- package/dist/es2019/plugins/table/nodeviews/table.js +13 -1
- package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +16 -11
- package/dist/es2019/plugins/table/toolbar.js +65 -29
- package/dist/es2019/plugins/table/ui/common-styles.js +15 -5
- package/dist/es2019/plugins/table/ui/messages.js +17 -2
- package/dist/es2019/plugins/table/ui/ui-styles.js +24 -16
- package/dist/es2019/version.json +1 -1
- package/dist/esm/plugins/table/commands/index.js +2 -1
- package/dist/esm/plugins/table/commands/referentiality.js +12 -0
- package/dist/esm/plugins/table/event-handlers.js +5 -1
- package/dist/esm/plugins/table/nodeviews/table.js +10 -1
- package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
- package/dist/esm/plugins/table/toolbar.js +74 -29
- package/dist/esm/plugins/table/ui/common-styles.js +6 -3
- package/dist/esm/plugins/table/ui/messages.js +17 -2
- package/dist/esm/plugins/table/ui/ui-styles.js +2 -6
- package/dist/esm/version.json +1 -1
- package/dist/types/plugins/table/commands/index.d.ts +1 -0
- package/dist/types/plugins/table/commands/referentiality.d.ts +2 -0
- package/dist/types/plugins/table/index.d.ts +2 -3
- package/dist/types/plugins/table/nodeviews/table.d.ts +4 -1
- package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +0 -1
- package/dist/types/plugins/table/ui/common-styles.d.ts +4 -1
- package/dist/types/plugins/table/ui/messages.d.ts +15 -0
- package/package.json +7 -7
- package/report.api.md +6 -6
- package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +130 -0
- package/src/__tests__/integration/floating-toolbar.ts +54 -0
- package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +37 -0
- package/src/__tests__/unit/color-picker.ts +100 -0
- package/src/__tests__/unit/get-toolbar-config.ts +1 -4
- package/src/__tests__/unit/keymap.ts +1 -1
- package/src/__tests__/unit/nodeviews/cell.ts +52 -57
- package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +90 -8
- package/src/__tests__/unit/transforms/delete-columns.ts +1 -1
- package/src/__tests__/unit/transforms/delete-rows.ts +1 -1
- package/src/__tests__/unit/utils/collapse.ts +2 -2
- package/src/plugins/table/commands/index.ts +1 -0
- package/src/plugins/table/commands/referentiality.ts +14 -0
- package/src/plugins/table/event-handlers.ts +7 -1
- package/src/plugins/table/index.tsx +6 -1
- package/src/plugins/table/nodeviews/table.tsx +16 -1
- package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +12 -10
- package/src/plugins/table/toolbar.tsx +84 -28
- package/src/plugins/table/ui/common-styles.ts +20 -4
- package/src/plugins/table/ui/messages.ts +18 -3
- package/src/plugins/table/ui/ui-styles.ts +23 -14
- package/dist/cjs/plugins/table/utils/referentiality.js +0 -29
- package/dist/es2019/plugins/table/utils/referentiality.js +0 -18
- package/dist/esm/plugins/table/utils/referentiality.js +0 -20
- package/dist/types/plugins/table/utils/referentiality.d.ts +0 -2
- 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).
|
|
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('
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
128
|
-
|
|
124
|
+
it('should preserve the correct rowspan and colspan after merge cells and undo', () => {
|
|
125
|
+
jest.spyOn(domHelpers, 'getTop').mockImplementation(() => 0);
|
|
129
126
|
|
|
130
|
-
|
|
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('
|
|
133
|
-
tr(
|
|
143
|
+
tr(th({ rowspan: 2 })(p('')), thEmpty, thEmpty),
|
|
144
|
+
tr(tdEmpty, tdEmpty),
|
|
134
145
|
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
135
146
|
),
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
stickyHeaders: true,
|
|
139
|
-
tableCellOptimization: true,
|
|
140
|
-
});
|
|
141
|
-
const { state, dispatch } = editorView;
|
|
147
|
+
),
|
|
148
|
+
);
|
|
142
149
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
26
|
+
const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
|
|
27
27
|
|
|
28
|
-
const finalPreset = expandInPlugins ? preset.add(
|
|
28
|
+
const finalPreset = expandInPlugins ? preset.add(expandPlugin) : preset;
|
|
29
29
|
|
|
30
30
|
return createEditor({ doc, preset: finalPreset });
|
|
31
31
|
};
|