@atlaskit/editor-plugin-table 0.2.2 → 0.2.4
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 +26 -0
- package/dist/cjs/plugins/table/commands/hover.js +2 -1
- package/dist/cjs/plugins/table/event-handlers.js +9 -13
- package/dist/cjs/plugins/table/index.js +3 -1
- package/dist/cjs/plugins/table/nodeviews/TableComponent.js +15 -5
- package/dist/cjs/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/cjs/plugins/table/pm-plugins/main.js +2 -2
- package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +42 -8
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/cjs/plugins/table/toolbar.js +42 -10
- package/dist/cjs/plugins/table/ui/FloatingContextualButton/index.js +7 -1
- package/dist/cjs/plugins/table/ui/FloatingContextualButton/styles.js +34 -6
- package/dist/cjs/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/cjs/plugins/table/ui/common-styles.js +1 -1
- package/dist/cjs/plugins/table/ui/consts.js +4 -4
- package/dist/cjs/plugins/table/ui/ui-styles.js +5 -5
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/plugins/table/commands/hover.js +2 -1
- package/dist/es2019/plugins/table/event-handlers.js +10 -13
- package/dist/es2019/plugins/table/index.js +1 -1
- package/dist/es2019/plugins/table/nodeviews/TableComponent.js +12 -1
- package/dist/es2019/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/es2019/plugins/table/pm-plugins/main.js +2 -2
- package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +31 -4
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/es2019/plugins/table/toolbar.js +43 -12
- package/dist/es2019/plugins/table/ui/FloatingContextualButton/index.js +6 -2
- package/dist/es2019/plugins/table/ui/FloatingContextualButton/styles.js +47 -8
- package/dist/es2019/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/es2019/plugins/table/ui/common-styles.js +9 -9
- package/dist/es2019/plugins/table/ui/consts.js +5 -5
- package/dist/es2019/plugins/table/ui/ui-styles.js +5 -5
- package/dist/es2019/version.json +1 -1
- package/dist/esm/plugins/table/commands/hover.js +2 -1
- package/dist/esm/plugins/table/event-handlers.js +10 -14
- package/dist/esm/plugins/table/index.js +3 -1
- package/dist/esm/plugins/table/nodeviews/TableComponent.js +17 -6
- package/dist/esm/plugins/table/pm-plugins/default-table-selection.js +1 -2
- package/dist/esm/plugins/table/pm-plugins/main.js +2 -2
- package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +43 -8
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +1 -1
- package/dist/esm/plugins/table/toolbar.js +43 -12
- package/dist/esm/plugins/table/ui/FloatingContextualButton/index.js +8 -2
- package/dist/esm/plugins/table/ui/FloatingContextualButton/styles.js +28 -5
- package/dist/esm/plugins/table/ui/FloatingContextualMenu/ContextualMenu.js +4 -1
- package/dist/esm/plugins/table/ui/common-styles.js +1 -1
- package/dist/esm/plugins/table/ui/consts.js +5 -5
- package/dist/esm/plugins/table/ui/ui-styles.js +5 -5
- package/dist/esm/version.json +1 -1
- package/dist/types/plugins/table/event-handlers.d.ts +2 -2
- package/dist/types/plugins/table/pm-plugins/default-table-selection.d.ts +0 -1
- package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +8 -0
- package/dist/types/plugins/table/toolbar.d.ts +3 -2
- package/dist/types/plugins/table/ui/FloatingContextualButton/styles.d.ts +3 -1
- package/dist/types/plugins/table/ui/FloatingContextualMenu/styles.d.ts +2 -2
- package/dist/types/plugins/table/ui/common-styles.d.ts +3 -3
- package/dist/types/plugins/table/ui/consts.d.ts +2 -2
- package/dist/types/plugins/table/ui/ui-styles.d.ts +14 -14
- package/package.json +4 -4
- package/src/__tests__/integration/__snapshots__/floating-toolbar.ts.snap +321 -0
- package/src/__tests__/integration/delete-last-column-in-full-width.ts +6 -5
- package/src/__tests__/integration/floating-toolbar.ts +169 -0
- package/src/__tests__/unit/get-toolbar-config.ts +1 -0
- package/src/__tests__/unit/nodeviews/TableComponent.tsx +146 -4
- package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +82 -31
- package/src/__tests__/unit/toolbar.ts +165 -4
- package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +2 -2
- package/src/plugins/table/commands/hover.ts +1 -0
- package/src/plugins/table/event-handlers.ts +6 -17
- package/src/plugins/table/index.tsx +1 -0
- package/src/plugins/table/nodeviews/TableComponent.tsx +10 -2
- package/src/plugins/table/nodeviews/tableCell.tsx +1 -1
- package/src/plugins/table/pm-plugins/default-table-selection.ts +0 -1
- package/src/plugins/table/pm-plugins/main.ts +26 -28
- package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +44 -9
- package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +1 -1
- package/src/plugins/table/toolbar.tsx +60 -13
- package/src/plugins/table/ui/FloatingContextualButton/index.tsx +12 -2
- package/src/plugins/table/ui/FloatingContextualButton/styles.ts +51 -7
- package/src/plugins/table/ui/FloatingContextualMenu/ContextualMenu.tsx +3 -0
- package/src/plugins/table/ui/common-styles.ts +24 -9
- package/src/plugins/table/ui/consts.ts +7 -5
- package/src/plugins/table/ui/ui-styles.ts +20 -5
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { replaceRaf } from 'raf-stub';
|
|
3
|
+
import { TextSelection } from 'prosemirror-state';
|
|
4
|
+
|
|
5
|
+
import { Command } from '@atlaskit/editor-common/types';
|
|
3
6
|
import { render } from '@testing-library/react';
|
|
4
7
|
import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
|
|
8
|
+
import { selectTableClosestToPos } from '@atlaskit/editor-tables/src/utils/select-nodes';
|
|
5
9
|
import tablePlugin from '../../../plugins/table-plugin';
|
|
6
10
|
import {
|
|
7
11
|
doc,
|
|
@@ -12,8 +16,13 @@ import {
|
|
|
12
16
|
tdEmpty,
|
|
13
17
|
tdCursor,
|
|
14
18
|
DocBuilder,
|
|
19
|
+
thEmpty,
|
|
15
20
|
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
16
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
findTable,
|
|
23
|
+
findTableClosestToPos,
|
|
24
|
+
selectTable,
|
|
25
|
+
} from '@atlaskit/editor-tables/utils';
|
|
17
26
|
import {
|
|
18
27
|
TableCssClassName as ClassName,
|
|
19
28
|
TablePluginState,
|
|
@@ -22,7 +31,11 @@ import TableComponent from '../../../plugins/table/nodeviews/TableComponent';
|
|
|
22
31
|
|
|
23
32
|
import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
|
|
24
33
|
import type { EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
|
|
25
|
-
import
|
|
34
|
+
import * as commands from '../../../plugins/table/commands';
|
|
35
|
+
import {
|
|
36
|
+
toggleNumberColumn,
|
|
37
|
+
hoverTable,
|
|
38
|
+
} from '../../../plugins/table/commands';
|
|
26
39
|
|
|
27
40
|
jest.mock('../../../plugins/table/utils/nodes', () =>
|
|
28
41
|
Object.assign({}, jest.requireActual('../../../plugins/table/utils/nodes'), {
|
|
@@ -30,6 +43,12 @@ jest.mock('../../../plugins/table/utils/nodes', () =>
|
|
|
30
43
|
}),
|
|
31
44
|
);
|
|
32
45
|
|
|
46
|
+
jest.mock('../../../plugins/table/commands', () =>
|
|
47
|
+
Object.assign({}, jest.requireActual('../../../plugins/table/commands'), {
|
|
48
|
+
clearHoverSelection: jest.fn(),
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
|
|
33
52
|
replaceRaf();
|
|
34
53
|
const requestAnimationFrame = window.requestAnimationFrame as any;
|
|
35
54
|
|
|
@@ -57,8 +76,8 @@ describe('table -> nodeviews -> TableComponent.tsx', () => {
|
|
|
57
76
|
jest.clearAllMocks();
|
|
58
77
|
});
|
|
59
78
|
|
|
60
|
-
describe('when
|
|
61
|
-
it('should add table selected css class', () => {
|
|
79
|
+
describe('when a table is selected', () => {
|
|
80
|
+
it('should add table selected css class to the selected table', () => {
|
|
62
81
|
const { editorView } = editor(
|
|
63
82
|
doc(p('text'), table()(tr(tdEmpty, tdEmpty, tdCursor))),
|
|
64
83
|
{
|
|
@@ -78,6 +97,129 @@ describe('table -> nodeviews -> TableComponent.tsx', () => {
|
|
|
78
97
|
tableContainer!.classList.contains(ClassName.TABLE_SELECTED),
|
|
79
98
|
).toBeTruthy();
|
|
80
99
|
});
|
|
100
|
+
|
|
101
|
+
it('should not clear the editor state hover selection when changing selection to another table', () => {
|
|
102
|
+
const clearHoverSelectionSpy = jest
|
|
103
|
+
.spyOn(commands, 'clearHoverSelection')
|
|
104
|
+
.mockImplementation(() => (() => {}) as any as Command);
|
|
105
|
+
|
|
106
|
+
const { editorView } = editor(
|
|
107
|
+
doc(
|
|
108
|
+
p('text'),
|
|
109
|
+
table()(tr(thEmpty, thEmpty, thEmpty)),
|
|
110
|
+
table()(tr(thEmpty, thEmpty, thEmpty)),
|
|
111
|
+
),
|
|
112
|
+
);
|
|
113
|
+
const { state, dispatch } = editorView;
|
|
114
|
+
|
|
115
|
+
const isInDanger = true;
|
|
116
|
+
hoverTable(isInDanger)(state, dispatch);
|
|
117
|
+
|
|
118
|
+
const selectSecondTableTr = selectTableClosestToPos(
|
|
119
|
+
state.tr,
|
|
120
|
+
state.doc.resolve(26),
|
|
121
|
+
);
|
|
122
|
+
dispatch(selectSecondTableTr);
|
|
123
|
+
const secondTable = findTableClosestToPos(state.doc.resolve(26));
|
|
124
|
+
|
|
125
|
+
const selectFirstTableTr = selectTableClosestToPos(
|
|
126
|
+
state.tr,
|
|
127
|
+
state.doc.resolve(8),
|
|
128
|
+
);
|
|
129
|
+
dispatch(selectFirstTableTr);
|
|
130
|
+
const firstTable = findTableClosestToPos(state.doc.resolve(8));
|
|
131
|
+
|
|
132
|
+
const getTableNode = (index: number) => () =>
|
|
133
|
+
index === 1 ? firstTable!.node : secondTable!.node;
|
|
134
|
+
|
|
135
|
+
render(
|
|
136
|
+
<div>
|
|
137
|
+
<TableComponent
|
|
138
|
+
view={editorView}
|
|
139
|
+
eventDispatcher={
|
|
140
|
+
{ on: () => {}, off: () => {} } as any as EventDispatcher
|
|
141
|
+
}
|
|
142
|
+
// @ts-ignore
|
|
143
|
+
containerWidth={{}}
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
getNode={getTableNode(1)}
|
|
146
|
+
getEditorFeatureFlags={getEditorFeatureFlags}
|
|
147
|
+
allowControls
|
|
148
|
+
contentDOM={(wrapper: HTMLElement | null) => {
|
|
149
|
+
const node = editorView.dom.getElementsByTagName('table')[0];
|
|
150
|
+
if (!wrapper?.firstChild) {
|
|
151
|
+
wrapper?.appendChild(node);
|
|
152
|
+
}
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
<TableComponent
|
|
156
|
+
view={editorView}
|
|
157
|
+
eventDispatcher={
|
|
158
|
+
{ on: () => {}, off: () => {} } as any as EventDispatcher
|
|
159
|
+
}
|
|
160
|
+
// @ts-ignore
|
|
161
|
+
containerWidth={{}}
|
|
162
|
+
// @ts-ignore
|
|
163
|
+
getNode={getTableNode(2)}
|
|
164
|
+
getEditorFeatureFlags={getEditorFeatureFlags}
|
|
165
|
+
allowControls
|
|
166
|
+
contentDOM={(wrapper: HTMLElement | null) => {
|
|
167
|
+
const node = editorView.dom.getElementsByTagName('table')[0];
|
|
168
|
+
if (!wrapper?.firstChild) {
|
|
169
|
+
wrapper?.appendChild(node);
|
|
170
|
+
}
|
|
171
|
+
}}
|
|
172
|
+
/>
|
|
173
|
+
,
|
|
174
|
+
</div>,
|
|
175
|
+
);
|
|
176
|
+
expect(clearHoverSelectionSpy).not.toBeCalled();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('when there are no tables in selection', () => {
|
|
181
|
+
it('clears the editor state hover selection if the editor state is in danger flag is set', () => {
|
|
182
|
+
const clearHoverSelectionSpy = jest
|
|
183
|
+
.spyOn(commands, 'clearHoverSelection')
|
|
184
|
+
.mockImplementation(() => (() => {}) as any as Command);
|
|
185
|
+
|
|
186
|
+
const { editorView } = editor(
|
|
187
|
+
doc(p('text'), table()(tr(thEmpty, thEmpty, thEmpty))),
|
|
188
|
+
);
|
|
189
|
+
const { state, dispatch } = editorView;
|
|
190
|
+
|
|
191
|
+
const isInDanger = true;
|
|
192
|
+
hoverTable(isInDanger)(state, dispatch);
|
|
193
|
+
dispatch(selectTable(state.tr));
|
|
194
|
+
|
|
195
|
+
const tableF = findTable(state.selection);
|
|
196
|
+
const getNode = () => tableF!.node;
|
|
197
|
+
|
|
198
|
+
const newTr = state.tr.setSelection(TextSelection.create(state.doc, 0));
|
|
199
|
+
dispatch(newTr);
|
|
200
|
+
|
|
201
|
+
render(
|
|
202
|
+
<TableComponent
|
|
203
|
+
view={editorView}
|
|
204
|
+
eventDispatcher={
|
|
205
|
+
{ on: () => {}, off: () => {} } as any as EventDispatcher
|
|
206
|
+
}
|
|
207
|
+
// @ts-ignore
|
|
208
|
+
containerWidth={{}}
|
|
209
|
+
// @ts-ignore
|
|
210
|
+
getNode={getNode}
|
|
211
|
+
getEditorFeatureFlags={getEditorFeatureFlags}
|
|
212
|
+
allowControls
|
|
213
|
+
contentDOM={(wrapper: HTMLElement | null) => {
|
|
214
|
+
const node = editorView.dom.getElementsByTagName('table')[0];
|
|
215
|
+
if (!wrapper?.firstChild) {
|
|
216
|
+
wrapper?.appendChild(node);
|
|
217
|
+
}
|
|
218
|
+
}}
|
|
219
|
+
/>,
|
|
220
|
+
);
|
|
221
|
+
expect(clearHoverSelectionSpy).toBeCalledTimes(1);
|
|
222
|
+
});
|
|
81
223
|
});
|
|
82
224
|
|
|
83
225
|
describe('when the numbered column attribute is changed', () => {
|
|
@@ -21,10 +21,12 @@ import {
|
|
|
21
21
|
|
|
22
22
|
import tablePlugin from '../../../../plugins/table';
|
|
23
23
|
import { pluginKey } from '../../../../plugins/table/pm-plugins/plugin-key';
|
|
24
|
-
import { TextSelection, NodeSelection } from 'prosemirror-state';
|
|
24
|
+
import { TextSelection, NodeSelection, EditorState } from 'prosemirror-state';
|
|
25
|
+
import { EditorView } from 'prosemirror-view';
|
|
25
26
|
import panelPlugin from '@atlaskit/editor-core/src/plugins/panel';
|
|
26
27
|
import widthPlugin from '@atlaskit/editor-core/src/plugins/width';
|
|
27
28
|
import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
|
|
29
|
+
import { akEditorFullPageMaxWidth } from '@atlaskit/editor-shared-styles/consts';
|
|
28
30
|
|
|
29
31
|
describe('table-resizing/event-handlers', () => {
|
|
30
32
|
const editorAnalyticsAPIFake: EditorAnalyticsAPI = {
|
|
@@ -57,18 +59,7 @@ describe('table-resizing/event-handlers', () => {
|
|
|
57
59
|
doc(table()(tr(td()(p('1')), td()(p('2')), td()(p('3{<>}'))))),
|
|
58
60
|
);
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const mousedownEvent = new MouseEvent('mousedown', {
|
|
63
|
-
clientX: 150,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
view.dom.dispatchEvent(mousedownEvent);
|
|
67
|
-
|
|
68
|
-
const mouseupEvent = new MouseEvent('mouseup', {
|
|
69
|
-
clientX: 250,
|
|
70
|
-
});
|
|
71
|
-
window.dispatchEvent(mouseupEvent);
|
|
62
|
+
resizeColumn(view, 12, 150, 250);
|
|
72
63
|
|
|
73
64
|
expect(editorAnalyticsAPIFake.attachAnalyticsEvent).toHaveBeenCalledWith(
|
|
74
65
|
expect.objectContaining({
|
|
@@ -85,6 +76,50 @@ describe('table-resizing/event-handlers', () => {
|
|
|
85
76
|
);
|
|
86
77
|
});
|
|
87
78
|
|
|
79
|
+
it('should shrink last column until table is no longer overflowing', async () => {
|
|
80
|
+
const { editorView: view } = editor(
|
|
81
|
+
doc(table()(tr(td()(p('1')), td()(p('2')), td()(p('3{<>}'))))),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Increase column to overflow
|
|
85
|
+
resizeColumn(view, 7, 50, 500);
|
|
86
|
+
|
|
87
|
+
expect(getTotalTableWidth(view.state as EditorState)).toBeGreaterThan(
|
|
88
|
+
akEditorFullPageMaxWidth,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
resizeColumn(view, 12, 3000, 700);
|
|
92
|
+
|
|
93
|
+
// No matter how large we try to resize the result should equal the width (within 1 pt)
|
|
94
|
+
expect(getTotalTableWidth(view.state as EditorState)).toBeLessThanOrEqual(
|
|
95
|
+
akEditorFullPageMaxWidth,
|
|
96
|
+
);
|
|
97
|
+
expect(
|
|
98
|
+
getTotalTableWidth(view.state as EditorState),
|
|
99
|
+
).toBeGreaterThanOrEqual(akEditorFullPageMaxWidth - 1);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should not resize the last column to grow', async () => {
|
|
103
|
+
const { editorView: view } = editor(
|
|
104
|
+
doc(table()(tr(td()(p('1')), td()(p('2')), td()(p('3{<>}'))))),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Increase column to overflow
|
|
108
|
+
resizeColumn(view, 7, 50, 500);
|
|
109
|
+
|
|
110
|
+
const overflowingTableWidth = getTotalTableWidth(
|
|
111
|
+
view.state as EditorState,
|
|
112
|
+
);
|
|
113
|
+
expect(overflowingTableWidth).toBeGreaterThan(akEditorFullPageMaxWidth);
|
|
114
|
+
|
|
115
|
+
resizeColumn(view, 12, 400, 3000);
|
|
116
|
+
|
|
117
|
+
// Width should be unchanged
|
|
118
|
+
expect(getTotalTableWidth(view.state as EditorState)).toBe(
|
|
119
|
+
overflowingTableWidth,
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
88
123
|
it('should restore text selection after replacing the table', async () => {
|
|
89
124
|
const { editorView: view } = editor(
|
|
90
125
|
doc(table()(tr(td()(p('1')), td()(p('2')), td()(p('3{<>}'))))),
|
|
@@ -94,15 +129,7 @@ describe('table-resizing/event-handlers', () => {
|
|
|
94
129
|
expect(currentSelection instanceof TextSelection).toBeTruthy();
|
|
95
130
|
expect(currentSelection.$cursor.pos).toBe(15);
|
|
96
131
|
|
|
97
|
-
|
|
98
|
-
const mousedownEvent = new MouseEvent('mousedown', {
|
|
99
|
-
clientX: 150,
|
|
100
|
-
});
|
|
101
|
-
view.dom.dispatchEvent(mousedownEvent);
|
|
102
|
-
const mouseupEvent = new MouseEvent('mouseup', {
|
|
103
|
-
clientX: 250,
|
|
104
|
-
});
|
|
105
|
-
window.dispatchEvent(mouseupEvent);
|
|
132
|
+
resizeColumn(view, 12, 150, 250);
|
|
106
133
|
|
|
107
134
|
expect(currentSelection instanceof TextSelection).toBeTruthy();
|
|
108
135
|
expect(currentSelection.$cursor.pos).toBe(15);
|
|
@@ -118,17 +145,41 @@ describe('table-resizing/event-handlers', () => {
|
|
|
118
145
|
view.dispatch(_tr);
|
|
119
146
|
expect(view.state.tr.selection.node.type.name).toBe('panel');
|
|
120
147
|
|
|
121
|
-
|
|
122
|
-
const mousedownEvent = new MouseEvent('mousedown', {
|
|
123
|
-
clientX: 150,
|
|
124
|
-
});
|
|
125
|
-
view.dom.dispatchEvent(mousedownEvent);
|
|
126
|
-
const mouseupEvent = new MouseEvent('mouseup', {
|
|
127
|
-
clientX: 250,
|
|
128
|
-
});
|
|
129
|
-
window.dispatchEvent(mouseupEvent);
|
|
148
|
+
resizeColumn(view, 13, 150, 250);
|
|
130
149
|
|
|
131
150
|
expect(view.state.tr.selection.node.type.name).toBe('panel');
|
|
132
151
|
});
|
|
133
152
|
});
|
|
134
153
|
});
|
|
154
|
+
|
|
155
|
+
function getTotalTableWidth(state: EditorState) {
|
|
156
|
+
let totalWidth = 0;
|
|
157
|
+
state.doc.descendants((node) => {
|
|
158
|
+
if (node.type.name === 'tableCell') {
|
|
159
|
+
totalWidth += node.attrs.colwidth[0];
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
});
|
|
164
|
+
return totalWidth;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function resizeColumn(
|
|
168
|
+
view: EditorView,
|
|
169
|
+
pos: number,
|
|
170
|
+
start: number,
|
|
171
|
+
end: number,
|
|
172
|
+
) {
|
|
173
|
+
setResizeHandlePos(pos)(view.state, view.dispatch);
|
|
174
|
+
|
|
175
|
+
const firstmousedownEvent = new MouseEvent('mousedown', {
|
|
176
|
+
clientX: start,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
view.dom.dispatchEvent(firstmousedownEvent);
|
|
180
|
+
|
|
181
|
+
const firstmouseupEvent = new MouseEvent('mouseup', {
|
|
182
|
+
clientX: end,
|
|
183
|
+
});
|
|
184
|
+
window.dispatchEvent(firstmouseupEvent);
|
|
185
|
+
}
|
|
@@ -25,9 +25,17 @@ import { canMergeCells } from '../../plugins/table/transforms';
|
|
|
25
25
|
import { Rect } from '@atlaskit/editor-tables/table-map';
|
|
26
26
|
import tablePlugin from '../../plugins/table';
|
|
27
27
|
import { pluginKey } from '../../plugins/table/pm-plugins/plugin-key';
|
|
28
|
+
import { getMergedCellsPositions } from '../../plugins/table/utils';
|
|
29
|
+
import { getNewResizeStateFromSelectedColumns } from '../../plugins/table/pm-plugins/table-resizing/utils/resize-state';
|
|
28
30
|
|
|
29
31
|
jest.mock('@atlaskit/editor-tables/utils');
|
|
30
32
|
jest.mock('../../plugins/table/transforms');
|
|
33
|
+
jest.mock('../../plugins/table/utils');
|
|
34
|
+
jest.mock('../../plugins/table/pm-plugins/table-resizing/utils/resize-state');
|
|
35
|
+
|
|
36
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
37
|
+
() => () => [],
|
|
38
|
+
);
|
|
31
39
|
|
|
32
40
|
const formatMessage: (t: unknown) => string = (id) => 'Lorem ipsum';
|
|
33
41
|
const ctx = { formatMessage };
|
|
@@ -138,13 +146,21 @@ describe('getToolbarMenuConfig', () => {
|
|
|
138
146
|
|
|
139
147
|
describe('getToolbarCellOptionsConfig', () => {
|
|
140
148
|
const createEditor = createProsemirrorEditorFactory();
|
|
141
|
-
const {
|
|
142
|
-
editorView: { state },
|
|
143
|
-
} = createEditor({
|
|
149
|
+
const { editorView } = createEditor({
|
|
144
150
|
doc: doc(table()(row(td()(p('1{cursor}'))))),
|
|
145
|
-
preset: new Preset<LightEditorPlugin>().add(
|
|
151
|
+
preset: new Preset<LightEditorPlugin>().add([
|
|
152
|
+
tablePlugin,
|
|
153
|
+
{
|
|
154
|
+
tableOptions: {
|
|
155
|
+
allowDistributeColumns: true,
|
|
156
|
+
allowColumnResizing: true,
|
|
157
|
+
allowColumnSorting: true,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
]),
|
|
146
161
|
pluginKey,
|
|
147
162
|
});
|
|
163
|
+
const { state } = editorView;
|
|
148
164
|
const getEditorContainerWidth = () => ({ width: 500 });
|
|
149
165
|
|
|
150
166
|
const formatMessage: (t: { id: string }) => string = (message) =>
|
|
@@ -152,6 +168,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
152
168
|
const rect = new Rect(1, 1, 1, 1);
|
|
153
169
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
154
170
|
state,
|
|
171
|
+
editorView,
|
|
155
172
|
rect,
|
|
156
173
|
{
|
|
157
174
|
formatMessage,
|
|
@@ -193,6 +210,21 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
193
210
|
disabled: true,
|
|
194
211
|
});
|
|
195
212
|
expect(items[6]).toMatchObject({
|
|
213
|
+
title: 'fabric.editor.distributeColumns',
|
|
214
|
+
selected: false,
|
|
215
|
+
disabled: true,
|
|
216
|
+
});
|
|
217
|
+
expect(items[7]).toMatchObject({
|
|
218
|
+
title: 'fabric.editor.sortColumnASC',
|
|
219
|
+
selected: false,
|
|
220
|
+
disabled: false,
|
|
221
|
+
});
|
|
222
|
+
expect(items[8]).toMatchObject({
|
|
223
|
+
title: 'fabric.editor.sortColumnDESC',
|
|
224
|
+
selected: false,
|
|
225
|
+
disabled: false,
|
|
226
|
+
});
|
|
227
|
+
expect(items[9]).toMatchObject({
|
|
196
228
|
title: 'fabric.editor.clearCells',
|
|
197
229
|
selected: false,
|
|
198
230
|
disabled: false,
|
|
@@ -206,6 +238,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
206
238
|
//
|
|
207
239
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
208
240
|
state,
|
|
241
|
+
editorView,
|
|
209
242
|
rect,
|
|
210
243
|
{
|
|
211
244
|
formatMessage,
|
|
@@ -230,6 +263,7 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
230
263
|
//
|
|
231
264
|
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
232
265
|
state,
|
|
266
|
+
editorView,
|
|
233
267
|
rect,
|
|
234
268
|
{
|
|
235
269
|
formatMessage,
|
|
@@ -246,4 +280,131 @@ describe('getToolbarCellOptionsConfig', () => {
|
|
|
246
280
|
disabled: false,
|
|
247
281
|
});
|
|
248
282
|
});
|
|
283
|
+
|
|
284
|
+
it('should disable sorting when merged cells are detected', () => {
|
|
285
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
286
|
+
() => [1, 2, 3],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
290
|
+
state,
|
|
291
|
+
editorView,
|
|
292
|
+
rect,
|
|
293
|
+
{
|
|
294
|
+
formatMessage,
|
|
295
|
+
},
|
|
296
|
+
getEditorContainerWidth,
|
|
297
|
+
undefined,
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
301
|
+
const sortItems = items.filter((item) =>
|
|
302
|
+
item.id?.startsWith('editor.table.sortColumn'),
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
const isDisabled = sortItems.every((item) => item.disabled);
|
|
306
|
+
const hasTooltip = sortItems.every((item) => item.tooltip);
|
|
307
|
+
|
|
308
|
+
expect(isDisabled).toBeTruthy();
|
|
309
|
+
expect(hasTooltip).toBeTruthy();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should allow sorting when there are no merged cells detected', () => {
|
|
313
|
+
(getMergedCellsPositions as Function as jest.Mock<{}>).mockImplementation(
|
|
314
|
+
() => [],
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
318
|
+
state,
|
|
319
|
+
editorView,
|
|
320
|
+
rect,
|
|
321
|
+
{
|
|
322
|
+
formatMessage,
|
|
323
|
+
},
|
|
324
|
+
getEditorContainerWidth,
|
|
325
|
+
undefined,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
329
|
+
const sortItems = items.filter((item) =>
|
|
330
|
+
item.id?.startsWith('editor.table.sortColumn'),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const isDisabled = sortItems.every((item) => item.disabled);
|
|
334
|
+
const hasTooltip = sortItems.every((item) => item.tooltip);
|
|
335
|
+
|
|
336
|
+
expect(isDisabled).toBeFalsy();
|
|
337
|
+
expect(hasTooltip).toBeFalsy();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should disable distribute columns when no resize detected', () => {
|
|
341
|
+
(
|
|
342
|
+
getNewResizeStateFromSelectedColumns as Function as jest.Mock<{}>
|
|
343
|
+
).mockImplementation(() => ({ changed: false }));
|
|
344
|
+
|
|
345
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
346
|
+
state,
|
|
347
|
+
editorView,
|
|
348
|
+
rect,
|
|
349
|
+
{
|
|
350
|
+
formatMessage,
|
|
351
|
+
},
|
|
352
|
+
getEditorContainerWidth,
|
|
353
|
+
undefined,
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
357
|
+
const distributeColumns = items.filter((item) =>
|
|
358
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
362
|
+
expect(isDisabled).toBeTruthy();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('should allow distribute columns when resize detected', () => {
|
|
366
|
+
(
|
|
367
|
+
getNewResizeStateFromSelectedColumns as Function as jest.Mock<{}>
|
|
368
|
+
).mockImplementation(() => ({ changed: true }));
|
|
369
|
+
|
|
370
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
371
|
+
state,
|
|
372
|
+
editorView,
|
|
373
|
+
rect,
|
|
374
|
+
{
|
|
375
|
+
formatMessage,
|
|
376
|
+
},
|
|
377
|
+
getEditorContainerWidth,
|
|
378
|
+
undefined,
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
382
|
+
const distributeColumns = items.filter((item) =>
|
|
383
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
387
|
+
expect(isDisabled).toBeFalsy();
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('should disable distribute columns when editorView is undefined', () => {
|
|
391
|
+
const cellOptionsMenu = getToolbarCellOptionsConfig(
|
|
392
|
+
state,
|
|
393
|
+
undefined,
|
|
394
|
+
rect,
|
|
395
|
+
{
|
|
396
|
+
formatMessage,
|
|
397
|
+
},
|
|
398
|
+
getEditorContainerWidth,
|
|
399
|
+
undefined,
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
const items = cellOptionsMenu.options as Array<DropdownOptionT<Command>>;
|
|
403
|
+
const distributeColumns = items.filter((item) =>
|
|
404
|
+
item.id?.startsWith('editor.table.distributeColumns'),
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
const isDisabled = distributeColumns.every((item) => item.disabled);
|
|
408
|
+
expect(isDisabled).toBeTruthy();
|
|
409
|
+
});
|
|
249
410
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
version https://git-lfs.github.com/spec/v1
|
|
2
|
-
oid sha256:
|
|
3
|
-
size
|
|
2
|
+
oid sha256:5cd747accdc40bfc52f004ff689a3df00173ee2f27d15c68f3a76172c11050fd
|
|
3
|
+
size 13990
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
isRowControlsButton,
|
|
64
64
|
isTableControlsButton,
|
|
65
65
|
isTableContainerOrWrapper,
|
|
66
|
+
hasResizeHandler,
|
|
66
67
|
} from './utils';
|
|
67
68
|
import { getAllowAddColumnCustomStep } from './utils/get-allow-add-column-custom-step';
|
|
68
69
|
import type { GetEditorFeatureFlags } from '@atlaskit/editor-common/types';
|
|
@@ -298,7 +299,6 @@ export const handleMouseMove =
|
|
|
298
299
|
(
|
|
299
300
|
view: EditorView,
|
|
300
301
|
event: Event,
|
|
301
|
-
tableCellOptimization?: boolean,
|
|
302
302
|
elementContentRects?: ElementContentRects,
|
|
303
303
|
) => {
|
|
304
304
|
if (!(event.target instanceof HTMLElement)) {
|
|
@@ -314,7 +314,7 @@ export const handleMouseMove =
|
|
|
314
314
|
const positionColumn =
|
|
315
315
|
getMousePositionHorizontalRelativeByElement(
|
|
316
316
|
event as MouseEvent,
|
|
317
|
-
|
|
317
|
+
false,
|
|
318
318
|
elementContentRects,
|
|
319
319
|
) === 'right'
|
|
320
320
|
? endIndex
|
|
@@ -342,15 +342,11 @@ export const handleMouseMove =
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
const { mouseMoveOptimization } = getEditorFeatureFlags();
|
|
345
|
-
// we only want to allow mouseMoveOptimisation when tableCellOptimization is enabled
|
|
346
|
-
// because it relies on tableCell node view that is added via tableCellOptimization
|
|
347
|
-
const useMouseMoveOptimisation =
|
|
348
|
-
tableCellOptimization && mouseMoveOptimization;
|
|
349
345
|
|
|
350
346
|
if (!isResizeHandleDecoration(element) && isCell(element)) {
|
|
351
347
|
const positionColumn = getMousePositionHorizontalRelativeByElement(
|
|
352
348
|
event as MouseEvent,
|
|
353
|
-
|
|
349
|
+
mouseMoveOptimization,
|
|
354
350
|
elementContentRects,
|
|
355
351
|
RESIZE_HANDLE_AREA_DECORATION_GAP,
|
|
356
352
|
);
|
|
@@ -376,7 +372,8 @@ export const handleMouseMove =
|
|
|
376
372
|
|
|
377
373
|
if (
|
|
378
374
|
columnEndIndexTarget !== resizeHandleColumnIndex ||
|
|
379
|
-
rowIndexTarget !== resizeHandleRowIndex
|
|
375
|
+
rowIndexTarget !== resizeHandleRowIndex ||
|
|
376
|
+
!hasResizeHandler({ target: element, columnEndIndexTarget })
|
|
380
377
|
) {
|
|
381
378
|
return addResizeHandleDecorations(
|
|
382
379
|
rowIndexTarget,
|
|
@@ -487,7 +484,6 @@ export const whenTableInFocus =
|
|
|
487
484
|
eventHandler: (
|
|
488
485
|
view: EditorView,
|
|
489
486
|
mouseEvent: Event,
|
|
490
|
-
tableCellOptimization?: boolean,
|
|
491
487
|
elementContentRects?: ElementContentRects,
|
|
492
488
|
) => boolean,
|
|
493
489
|
elementContentRects?: ElementContentRects,
|
|
@@ -498,17 +494,10 @@ export const whenTableInFocus =
|
|
|
498
494
|
const isDragging =
|
|
499
495
|
tableResizePluginState && !!tableResizePluginState.dragging;
|
|
500
496
|
const hasTableNode = tablePluginState && tablePluginState.tableNode;
|
|
501
|
-
const tableCellOptimization =
|
|
502
|
-
tablePluginState?.pluginConfig?.tableCellOptimization;
|
|
503
497
|
|
|
504
498
|
if (!hasTableNode || isDragging) {
|
|
505
499
|
return false;
|
|
506
500
|
}
|
|
507
501
|
|
|
508
|
-
return eventHandler(
|
|
509
|
-
view,
|
|
510
|
-
mouseEvent,
|
|
511
|
-
tableCellOptimization,
|
|
512
|
-
elementContentRects,
|
|
513
|
-
);
|
|
502
|
+
return eventHandler(view, mouseEvent, elementContentRects);
|
|
514
503
|
};
|
|
@@ -458,6 +458,7 @@ const tablesPlugin = (options?: TablePluginOptions): EditorPlugin => {
|
|
|
458
458
|
defaultGetEditorContainerWidth,
|
|
459
459
|
options?.editorAnalyticsAPI,
|
|
460
460
|
options?.getEditorFeatureFlags || defaultGetEditorFeatureFlags,
|
|
461
|
+
() => editorViewRef.current,
|
|
461
462
|
)(pluginConfig(options?.tableOptions)),
|
|
462
463
|
},
|
|
463
464
|
};
|
|
@@ -4,6 +4,7 @@ import { Node as PmNode } from 'prosemirror-model';
|
|
|
4
4
|
import { isTableSelected } from '@atlaskit/editor-tables/utils';
|
|
5
5
|
import { EditorView } from 'prosemirror-view';
|
|
6
6
|
import rafSchedule from 'raf-schd';
|
|
7
|
+
import { findTable } from '@atlaskit/editor-tables/utils';
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
calcTableWidth,
|
|
@@ -19,7 +20,7 @@ import { getParentNodeWidth } from '@atlaskit/editor-common/node-width';
|
|
|
19
20
|
import type { EditorContainerWidth } from '@atlaskit/editor-common/types';
|
|
20
21
|
import { parsePx } from '@atlaskit/editor-common/utils';
|
|
21
22
|
|
|
22
|
-
import { autoSizeTable } from '../commands';
|
|
23
|
+
import { autoSizeTable, clearHoverSelection } from '../commands';
|
|
23
24
|
import { getPluginState } from '../pm-plugins/plugin-factory';
|
|
24
25
|
import {
|
|
25
26
|
findStickyHeaderForTable,
|
|
@@ -196,7 +197,14 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
componentDidUpdate(prevProps: ComponentProps) {
|
|
199
|
-
const { getNode, isMediaFullscreen, allowColumnResizing } =
|
|
200
|
+
const { view, getNode, isMediaFullscreen, allowColumnResizing } =
|
|
201
|
+
this.props;
|
|
202
|
+
const { isInDanger } = getPluginState(view.state);
|
|
203
|
+
const table = findTable(view.state.selection);
|
|
204
|
+
|
|
205
|
+
if (isInDanger && !table) {
|
|
206
|
+
clearHoverSelection()(view.state, view.dispatch);
|
|
207
|
+
}
|
|
200
208
|
|
|
201
209
|
const { tableOverflowShadowsOptimization } =
|
|
202
210
|
this.props.getEditorFeatureFlags();
|