@atlaskit/editor-plugin-table 7.10.1 → 7.11.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 +16 -0
- package/dist/cjs/commands/insert.js +4 -7
- package/dist/cjs/commands/misc.js +10 -3
- package/dist/cjs/nodeviews/TableComponent.js +23 -2
- package/dist/cjs/plugin.js +7 -1
- package/dist/cjs/pm-plugins/analytics/plugin.js +17 -22
- package/dist/cjs/pm-plugins/view-mode-sort/consts.js +9 -0
- package/dist/cjs/pm-plugins/view-mode-sort/index.js +304 -0
- package/dist/cjs/pm-plugins/view-mode-sort/plugin-key.js +8 -0
- package/dist/cjs/pm-plugins/view-mode-sort/types.js +5 -0
- package/dist/cjs/pm-plugins/view-mode-sort/utils.js +106 -0
- package/dist/cjs/ui/common-styles.js +22 -15
- package/dist/es2019/commands/insert.js +4 -7
- package/dist/es2019/commands/misc.js +10 -3
- package/dist/es2019/nodeviews/TableComponent.js +24 -2
- package/dist/es2019/plugin.js +7 -1
- package/dist/es2019/pm-plugins/analytics/plugin.js +21 -26
- package/dist/es2019/pm-plugins/view-mode-sort/consts.js +3 -0
- package/dist/es2019/pm-plugins/view-mode-sort/index.js +243 -0
- package/dist/es2019/pm-plugins/view-mode-sort/plugin-key.js +2 -0
- package/dist/es2019/pm-plugins/view-mode-sort/types.js +1 -0
- package/dist/es2019/pm-plugins/view-mode-sort/utils.js +98 -0
- package/dist/es2019/ui/common-styles.js +35 -0
- package/dist/esm/commands/insert.js +4 -7
- package/dist/esm/commands/misc.js +10 -3
- package/dist/esm/nodeviews/TableComponent.js +23 -2
- package/dist/esm/plugin.js +7 -1
- package/dist/esm/pm-plugins/analytics/plugin.js +17 -22
- package/dist/esm/pm-plugins/view-mode-sort/consts.js +3 -0
- package/dist/esm/pm-plugins/view-mode-sort/index.js +299 -0
- package/dist/esm/pm-plugins/view-mode-sort/plugin-key.js +2 -0
- package/dist/esm/pm-plugins/view-mode-sort/types.js +1 -0
- package/dist/esm/pm-plugins/view-mode-sort/utils.js +99 -0
- package/dist/esm/ui/common-styles.js +15 -8
- package/dist/types/pm-plugins/view-mode-sort/consts.d.ts +3 -0
- package/dist/types/pm-plugins/view-mode-sort/index.d.ts +10 -0
- package/dist/types/pm-plugins/view-mode-sort/plugin-key.d.ts +3 -0
- package/dist/types/pm-plugins/view-mode-sort/types.d.ts +17 -0
- package/dist/types/pm-plugins/view-mode-sort/utils.d.ts +15 -0
- package/dist/types/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -2
- package/dist/types/ui/TableFloatingControls/CornerControls/DragCornerControls.d.ts +4 -4
- package/dist/types/ui/TableFloatingControls/index.d.ts +2 -2
- package/dist/types-ts4.5/pm-plugins/view-mode-sort/consts.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/view-mode-sort/index.d.ts +10 -0
- package/dist/types-ts4.5/pm-plugins/view-mode-sort/plugin-key.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/view-mode-sort/types.d.ts +21 -0
- package/dist/types-ts4.5/pm-plugins/view-mode-sort/utils.d.ts +15 -0
- package/dist/types-ts4.5/ui/TableFloatingColumnControls/ColumnControls/index.d.ts +2 -2
- package/dist/types-ts4.5/ui/TableFloatingControls/CornerControls/DragCornerControls.d.ts +4 -4
- package/dist/types-ts4.5/ui/TableFloatingControls/index.d.ts +2 -2
- package/package.json +8 -8
- package/src/commands/insert.ts +7 -13
- package/src/commands/misc.ts +14 -8
- package/src/nodeviews/TableComponent.tsx +22 -0
- package/src/plugin.tsx +12 -3
- package/src/pm-plugins/analytics/plugin.ts +24 -33
- package/src/pm-plugins/view-mode-sort/consts.ts +3 -0
- package/src/pm-plugins/view-mode-sort/index.ts +257 -0
- package/src/pm-plugins/view-mode-sort/plugin-key.ts +6 -0
- package/src/pm-plugins/view-mode-sort/types.ts +23 -0
- package/src/pm-plugins/view-mode-sort/utils.ts +120 -0
- package/src/ui/common-styles.ts +36 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This plugin allows sorting of table nodes in the Editor without modifying the underlying ProseMirror document.
|
|
3
|
+
* Instead of making changes to the ProseMirror document, the plugin sorts the table rows in the DOM. This allows the sorting to be
|
|
4
|
+
* visible to the user without affecting the document's content.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createElement } from 'react';
|
|
8
|
+
import ReactDOM from 'react-dom';
|
|
9
|
+
import { RawIntlProvider } from 'react-intl-next';
|
|
10
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
11
|
+
import { SortingIcon } from '@atlaskit/editor-common/table';
|
|
12
|
+
import { SortOrder } from '@atlaskit/editor-common/types';
|
|
13
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
14
|
+
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
15
|
+
import { getPluginState } from '../plugin-factory';
|
|
16
|
+
import { IS_DISABLED_CLASS_NAME, SORT_INDEX_DATA_ATTRIBUTE, SORTING_ICON_CLASS_NAME } from './consts';
|
|
17
|
+
import { tableViewModeSortPluginKey as key } from './plugin-key';
|
|
18
|
+
import { getTableElements, toggleSort } from './utils';
|
|
19
|
+
export const createPlugin = editorViewModeAPI => {
|
|
20
|
+
return new SafePlugin({
|
|
21
|
+
state: {
|
|
22
|
+
init: () => ({
|
|
23
|
+
decorations: DecorationSet.empty,
|
|
24
|
+
sort: {},
|
|
25
|
+
allTables: []
|
|
26
|
+
}),
|
|
27
|
+
apply(tr, pluginState, oldState) {
|
|
28
|
+
// TODO - move this mode check to plugin creation if possible. Right now it's here because the initial state
|
|
29
|
+
// does not appear correct when the plugin is created.
|
|
30
|
+
const {
|
|
31
|
+
mode
|
|
32
|
+
} = (editorViewModeAPI === null || editorViewModeAPI === void 0 ? void 0 : editorViewModeAPI.sharedState.currentState()) || {};
|
|
33
|
+
if (mode !== 'view') {
|
|
34
|
+
return pluginState;
|
|
35
|
+
}
|
|
36
|
+
let {
|
|
37
|
+
decorations,
|
|
38
|
+
sort,
|
|
39
|
+
allTables
|
|
40
|
+
} = pluginState;
|
|
41
|
+
const sortMeta = tr.getMeta('tableSortMeta');
|
|
42
|
+
let hoverTableMeta = tr.getMeta('mouseEnterTable');
|
|
43
|
+
let removeTableMeta = tr.getMeta('removeTable');
|
|
44
|
+
let tableId = '';
|
|
45
|
+
|
|
46
|
+
// Remove the table from the state
|
|
47
|
+
if (removeTableMeta) {
|
|
48
|
+
allTables = allTables.filter(([id]) => id !== removeTableMeta);
|
|
49
|
+
} else {
|
|
50
|
+
tableId = hoverTableMeta === null || hoverTableMeta === void 0 ? void 0 : hoverTableMeta[0];
|
|
51
|
+
}
|
|
52
|
+
sort = {
|
|
53
|
+
...sort,
|
|
54
|
+
...sortMeta
|
|
55
|
+
};
|
|
56
|
+
const isTableInState = allTables.some(([id]) => id === tableId);
|
|
57
|
+
|
|
58
|
+
// Update the table in the state
|
|
59
|
+
if (hoverTableMeta) {
|
|
60
|
+
allTables = allTables.filter(([id]) => id !== hoverTableMeta[0]);
|
|
61
|
+
allTables.push(hoverTableMeta);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create decorations for the sorting icons
|
|
66
|
+
*/
|
|
67
|
+
const decs = [];
|
|
68
|
+
|
|
69
|
+
// TODO - add support for keyboard only users
|
|
70
|
+
if (hoverTableMeta && !isTableInState || sortMeta) {
|
|
71
|
+
allTables.forEach(table => {
|
|
72
|
+
const [tableId, _node, pos] = table;
|
|
73
|
+
const tableNode = tr.doc.nodeAt(tr.mapping.map(pos));
|
|
74
|
+
if (!tableNode || tableNode.type.name !== 'table') {
|
|
75
|
+
return pluginState;
|
|
76
|
+
}
|
|
77
|
+
const map = TableMap.get(tableNode);
|
|
78
|
+
const hasMergedCells = new Set(map.map).size !== map.map.length;
|
|
79
|
+
map.mapByRow[0].forEach((cell, index) => {
|
|
80
|
+
// return pluginState;
|
|
81
|
+
decs.push(Decoration.widget(cell + pos + 2, () => {
|
|
82
|
+
var _sort$tableId;
|
|
83
|
+
const element = document.createElement('div');
|
|
84
|
+
element.setAttribute(SORT_INDEX_DATA_ATTRIBUTE, `${index}`);
|
|
85
|
+
element.classList.add(SORTING_ICON_CLASS_NAME);
|
|
86
|
+
if (hasMergedCells) {
|
|
87
|
+
element.classList.add(IS_DISABLED_CLASS_NAME);
|
|
88
|
+
}
|
|
89
|
+
let sortOrdered;
|
|
90
|
+
if (index === ((_sort$tableId = sort[tableId]) === null || _sort$tableId === void 0 ? void 0 : _sort$tableId.index)) {
|
|
91
|
+
var _sort$tableId2;
|
|
92
|
+
sortOrdered = (_sort$tableId2 = sort[tableId]) === null || _sort$tableId2 === void 0 ? void 0 : _sort$tableId2.direction;
|
|
93
|
+
} else {
|
|
94
|
+
sortOrdered = SortOrder.NO_ORDER;
|
|
95
|
+
}
|
|
96
|
+
const {
|
|
97
|
+
getIntl
|
|
98
|
+
} = getPluginState(oldState);
|
|
99
|
+
ReactDOM.render( /*#__PURE__*/createElement(RawIntlProvider, {
|
|
100
|
+
value: getIntl()
|
|
101
|
+
}, /*#__PURE__*/createElement(SortingIcon, {
|
|
102
|
+
isSortingAllowed: !hasMergedCells,
|
|
103
|
+
sortOrdered,
|
|
104
|
+
onClick: () => {},
|
|
105
|
+
onKeyDown: () => {}
|
|
106
|
+
})), element);
|
|
107
|
+
return element;
|
|
108
|
+
}));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
decorations = DecorationSet.create(tr.doc, decs);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Map the decorations to the new document if there are changes
|
|
116
|
+
*/
|
|
117
|
+
if (tr.docChanged) {
|
|
118
|
+
decorations = decorations.map(tr.mapping, tr.doc);
|
|
119
|
+
allTables = allTables.map(table => {
|
|
120
|
+
return [table[0], table[1], tr.mapping.map(table[2])];
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
decorations,
|
|
125
|
+
sort,
|
|
126
|
+
allTables
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
key,
|
|
131
|
+
appendTransaction: (trs, oldState, newState) => {
|
|
132
|
+
var _key$getState;
|
|
133
|
+
// return newState.tr;
|
|
134
|
+
const {
|
|
135
|
+
mode
|
|
136
|
+
} = (editorViewModeAPI === null || editorViewModeAPI === void 0 ? void 0 : editorViewModeAPI.sharedState.currentState()) || {};
|
|
137
|
+
if (mode !== 'view') {
|
|
138
|
+
return newState.tr;
|
|
139
|
+
}
|
|
140
|
+
let allTables = ((_key$getState = key.getState(newState)) === null || _key$getState === void 0 ? void 0 : _key$getState.allTables) || [];
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* If incoming changes have affected a table node, remove the sorting. This prevents the
|
|
144
|
+
* table from breaking if changes like merged cells are incoming.
|
|
145
|
+
*/
|
|
146
|
+
for (const tr of trs) {
|
|
147
|
+
const hoverTableMeta = tr.getMeta('mouseEnterTable');
|
|
148
|
+
if (hoverTableMeta) {
|
|
149
|
+
allTables = allTables.filter(([id]) => id !== hoverTableMeta[0]);
|
|
150
|
+
allTables.push(hoverTableMeta);
|
|
151
|
+
}
|
|
152
|
+
const isRemote = tr.getMeta('isRemote');
|
|
153
|
+
const isDocChanged = tr.docChanged;
|
|
154
|
+
const isChangesIncoming = isRemote && isDocChanged;
|
|
155
|
+
const oldPluginState = key.getState(oldState);
|
|
156
|
+
const newPluginState = key.getState(newState);
|
|
157
|
+
for (const table of allTables) {
|
|
158
|
+
var _oldPluginState$sort, _newPluginState$sort;
|
|
159
|
+
const [tableId, node, pos] = table;
|
|
160
|
+
const {
|
|
161
|
+
order: oldOrder,
|
|
162
|
+
direction: oldDirection,
|
|
163
|
+
index: oldIndex
|
|
164
|
+
} = (oldPluginState === null || oldPluginState === void 0 ? void 0 : (_oldPluginState$sort = oldPluginState.sort) === null || _oldPluginState$sort === void 0 ? void 0 : _oldPluginState$sort[tableId]) || {};
|
|
165
|
+
if (isChangesIncoming) {
|
|
166
|
+
var _maybeTableNode$attrs;
|
|
167
|
+
const maybeTableNode = tr.doc.nodeAt(pos);
|
|
168
|
+
const isTableNodeChanged = (maybeTableNode === null || maybeTableNode === void 0 ? void 0 : (_maybeTableNode$attrs = maybeTableNode.attrs) === null || _maybeTableNode$attrs === void 0 ? void 0 : _maybeTableNode$attrs.localId) !== tableId || !node.eq(maybeTableNode);
|
|
169
|
+
if (isTableNodeChanged) {
|
|
170
|
+
const newtr = newState.tr;
|
|
171
|
+
newtr.setMeta('tableSortMeta', {
|
|
172
|
+
[tableId]: {}
|
|
173
|
+
});
|
|
174
|
+
newtr.setMeta('removeTable', tableId);
|
|
175
|
+
|
|
176
|
+
// Unsort the table here
|
|
177
|
+
if (oldOrder !== undefined) {
|
|
178
|
+
const {
|
|
179
|
+
rows,
|
|
180
|
+
tbody
|
|
181
|
+
} = getTableElements(tableId);
|
|
182
|
+
if (!rows || !tbody) {
|
|
183
|
+
return newtr;
|
|
184
|
+
}
|
|
185
|
+
const sortedOrder = [...oldOrder].sort((a, b) => a.value - b.value);
|
|
186
|
+
sortedOrder.forEach((index, i) => {
|
|
187
|
+
tbody.appendChild(rows[index.index + 1]);
|
|
188
|
+
});
|
|
189
|
+
return newtr;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Sort the table if the sort order has changed
|
|
196
|
+
*/
|
|
197
|
+
const {
|
|
198
|
+
order: newOrder,
|
|
199
|
+
direction: newDirection,
|
|
200
|
+
index: newIndex
|
|
201
|
+
} = (newPluginState === null || newPluginState === void 0 ? void 0 : (_newPluginState$sort = newPluginState.sort) === null || _newPluginState$sort === void 0 ? void 0 : _newPluginState$sort[tableId]) || {};
|
|
202
|
+
const orderChanged = oldDirection !== newDirection || oldIndex !== newIndex;
|
|
203
|
+
if (orderChanged) {
|
|
204
|
+
if (!isRemote && newDirection !== SortOrder.NO_ORDER) {
|
|
205
|
+
const {
|
|
206
|
+
rows,
|
|
207
|
+
tbody
|
|
208
|
+
} = getTableElements(tableId);
|
|
209
|
+
if (rows && newOrder) {
|
|
210
|
+
newOrder.forEach((index, i) => {
|
|
211
|
+
tbody === null || tbody === void 0 ? void 0 : tbody.appendChild(rows[index.value + 1]);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return newState.tr;
|
|
219
|
+
},
|
|
220
|
+
props: {
|
|
221
|
+
handleDOMEvents: {
|
|
222
|
+
keydown: (view, event) => {
|
|
223
|
+
// TODO - fix the focus issue here, where toggling sort with a keypress loses focus
|
|
224
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
225
|
+
var _key$getState2;
|
|
226
|
+
const pluginState = ((_key$getState2 = key.getState(view.state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.sort) || {};
|
|
227
|
+
toggleSort(view, event, pluginState);
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
click: (view, event) => {
|
|
231
|
+
var _key$getState3;
|
|
232
|
+
const pluginState = ((_key$getState3 = key.getState(view.state)) === null || _key$getState3 === void 0 ? void 0 : _key$getState3.sort) || {};
|
|
233
|
+
toggleSort(view, event, pluginState);
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
decorations(state) {
|
|
237
|
+
var _key$getState4;
|
|
238
|
+
const decs = ((_key$getState4 = key.getState(state)) === null || _key$getState4 === void 0 ? void 0 : _key$getState4.decorations) || DecorationSet.empty;
|
|
239
|
+
return decs;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { SortOrder } from '@atlaskit/editor-common/types';
|
|
2
|
+
import { IS_DISABLED_CLASS_NAME, SORT_INDEX_DATA_ATTRIBUTE, SORTING_ICON_CLASS_NAME } from './consts';
|
|
3
|
+
export const unsort = (oldOrder, tableElement) => {
|
|
4
|
+
const rows = tableElement.querySelectorAll('tr');
|
|
5
|
+
const tbody = tableElement.querySelector('tbody');
|
|
6
|
+
const sortedOrder = [...oldOrder].sort((a, b) => a.value - b.value);
|
|
7
|
+
sortedOrder.forEach(item => {
|
|
8
|
+
tbody === null || tbody === void 0 ? void 0 : tbody.appendChild(rows[item.index + 1]);
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// TODO - reuse sort logic from the Renderer and support switching between ASC, DESC and NO_ORDER
|
|
13
|
+
export const getSortOrderFromTable = (tableElement, sortIndex, direction) => {
|
|
14
|
+
const sortOrder = direction === SortOrder.DESC ? -1 : 1;
|
|
15
|
+
const strings = [];
|
|
16
|
+
tableElement.querySelectorAll('tr:not([data-header-row="true"])').forEach(tr => {
|
|
17
|
+
var _tr$querySelectorAll$;
|
|
18
|
+
strings.push(((_tr$querySelectorAll$ = tr.querySelectorAll('td')[sortIndex]) === null || _tr$querySelectorAll$ === void 0 ? void 0 : _tr$querySelectorAll$.textContent) || '');
|
|
19
|
+
});
|
|
20
|
+
const order = Array.from(strings.keys()).sort((a, b) => {
|
|
21
|
+
const string = strings[a] || '';
|
|
22
|
+
return string.localeCompare(strings[b] || '') * sortOrder;
|
|
23
|
+
}).map((value, index) => ({
|
|
24
|
+
value,
|
|
25
|
+
index
|
|
26
|
+
}));
|
|
27
|
+
// TODO - improve this. right now this is a workaround to ensure the first tr is always first in the order
|
|
28
|
+
return [{
|
|
29
|
+
value: -1,
|
|
30
|
+
index: -1
|
|
31
|
+
}, ...order];
|
|
32
|
+
};
|
|
33
|
+
export const toggleSort = (view, event, pluginState) => {
|
|
34
|
+
var _target$closest;
|
|
35
|
+
const target = event.target;
|
|
36
|
+
const widget = target.closest(`.${SORTING_ICON_CLASS_NAME}`);
|
|
37
|
+
if (widget !== null && widget !== void 0 && widget.classList.contains(IS_DISABLED_CLASS_NAME) || !widget) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let datasetortIndex = target === null || target === void 0 ? void 0 : (_target$closest = target.closest('.ProseMirror-widget')) === null || _target$closest === void 0 ? void 0 : _target$closest.getAttribute(SORT_INDEX_DATA_ATTRIBUTE);
|
|
41
|
+
const tr = view.state.tr;
|
|
42
|
+
const tableElement = target.closest('table');
|
|
43
|
+
if (!tableElement || !datasetortIndex) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const tableId = tableElement.getAttribute('data-table-local-id') || '';
|
|
47
|
+
let {
|
|
48
|
+
index,
|
|
49
|
+
direction,
|
|
50
|
+
order: oldOrder
|
|
51
|
+
} = (pluginState === null || pluginState === void 0 ? void 0 : pluginState[tableId]) || {};
|
|
52
|
+
|
|
53
|
+
// Unsort if there was already a sort
|
|
54
|
+
if (direction !== SortOrder.NO_ORDER && oldOrder !== undefined) {
|
|
55
|
+
unsort(oldOrder, tableElement);
|
|
56
|
+
}
|
|
57
|
+
const sortIndex = parseInt(datasetortIndex);
|
|
58
|
+
if (sortIndex === index) {
|
|
59
|
+
switch (direction) {
|
|
60
|
+
case SortOrder.NO_ORDER:
|
|
61
|
+
direction = SortOrder.ASC;
|
|
62
|
+
break;
|
|
63
|
+
case SortOrder.ASC:
|
|
64
|
+
direction = SortOrder.DESC;
|
|
65
|
+
break;
|
|
66
|
+
case SortOrder.DESC:
|
|
67
|
+
direction = SortOrder.NO_ORDER;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
direction = SortOrder.ASC; // default direction when a new index is clicked
|
|
72
|
+
}
|
|
73
|
+
const order = getSortOrderFromTable(tableElement, sortIndex, direction);
|
|
74
|
+
if (direction === SortOrder.NO_ORDER) {
|
|
75
|
+
tr.setMeta('tableSortMeta', {
|
|
76
|
+
[tableId]: {}
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
tr.setMeta('tableSortMeta', {
|
|
80
|
+
[tableId]: {
|
|
81
|
+
index: sortIndex,
|
|
82
|
+
direction,
|
|
83
|
+
order,
|
|
84
|
+
tableElement
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
view.dispatch(tr);
|
|
89
|
+
};
|
|
90
|
+
export const getTableElements = tableId => {
|
|
91
|
+
const tableElement = document.querySelector(`table[data-table-local-id="${tableId}"]`);
|
|
92
|
+
const tbody = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelector('tbody');
|
|
93
|
+
const rows = tableElement === null || tableElement === void 0 ? void 0 : tableElement.querySelectorAll('tr');
|
|
94
|
+
return {
|
|
95
|
+
tbody,
|
|
96
|
+
rows
|
|
97
|
+
};
|
|
98
|
+
};
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import { css } from '@emotion/react';
|
|
4
4
|
import { tableMarginTop, tableSharedStyle } from '@atlaskit/editor-common/styles';
|
|
5
|
+
import { SORTABLE_COLUMN_ICON_CLASSNAME } from '@atlaskit/editor-common/table';
|
|
5
6
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
6
7
|
import { akEditorSelectedNodeClassName, akEditorSmallZIndex, akEditorStickyHeaderZIndex, akEditorTableCellOnStickyHeaderZIndex, akEditorTableNumberColumnWidth, akEditorTableToolbarSize, akEditorUnitZIndex, getSelectionStyles, MAX_BROWSER_SCROLLBAR_HEIGHT, relativeFontSizeToBase16, SelectionStyle } from '@atlaskit/editor-shared-styles';
|
|
7
8
|
import { scrollbarStyles } from '@atlaskit/editor-shared-styles/scrollbar';
|
|
8
9
|
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
10
|
import { N0, N40A, R500 } from '@atlaskit/theme/colors';
|
|
10
11
|
import { fontSize } from '@atlaskit/theme/constants';
|
|
12
|
+
import { SORTING_ICON_CLASS_NAME } from '../pm-plugins/view-mode-sort/consts';
|
|
11
13
|
import { TableCssClassName as ClassName } from '../types';
|
|
12
14
|
import { columnControlsDecorationHeight, resizeHandlerAreaWidth, resizeHandlerZIndex, resizeLineWidth, rowControlsZIndex, stickyHeaderBorderBottomWidth, stickyRowOffsetTop, tableBorderColor, tableBorderDeleteColor, tableBorderRadiusSize, tableBorderSelectedColor, tableCellBackgroundColor, tableCellDeleteColor, tableCellSelectedColor, tableControlsSpacing, tableHeaderCellBackgroundColor, tableInsertColumnButtonSize, tableOverflowShadowWidth, tablePadding, tableScrollbarOffset, tableTextColor, tableToolbarDeleteColor, tableToolbarSelectedColor, tableToolbarSize } from './consts';
|
|
13
15
|
import { columnControlsDecoration, columnControlsLineMarker, DeleteButton, dragCornerControlButton, dragInsertButtonWrapper, floatingColumnControls, HeaderButton, HeaderButtonDanger, HeaderButtonHover, hoveredCell, hoveredDeleteButton, hoveredWarningCell, insertColumnButtonWrapper, insertLine, InsertMarker, insertRowButtonWrapper, OverflowShadow, resizeHandle, rowControlsWrapperDotStyle } from './ui-styles';
|
|
@@ -123,6 +125,38 @@ const breakoutWidthStyling = () => {
|
|
|
123
125
|
}
|
|
124
126
|
`;
|
|
125
127
|
};
|
|
128
|
+
const viewModeSortStyles = () => {
|
|
129
|
+
if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
|
|
130
|
+
return css`
|
|
131
|
+
th {
|
|
132
|
+
.${SORTING_ICON_CLASS_NAME} {
|
|
133
|
+
+ p {
|
|
134
|
+
margin-top: 0 !important;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&:has(.is-active) {
|
|
139
|
+
.${SORTABLE_COLUMN_ICON_CLASSNAME} {
|
|
140
|
+
opacity: 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.${SORTABLE_COLUMN_ICON_CLASSNAME} {
|
|
145
|
+
opacity: 0;
|
|
146
|
+
&:focus {
|
|
147
|
+
opacity: 1;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
&:hover {
|
|
152
|
+
.${SORTABLE_COLUMN_ICON_CLASSNAME} {
|
|
153
|
+
opacity: 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
126
160
|
const tableBorderStyles = () => {
|
|
127
161
|
if (getBooleanFF('platform.editor.table.column-controls-styles-updated')) {
|
|
128
162
|
return `border-color: ${tableBorderDeleteColor}`;
|
|
@@ -190,6 +224,7 @@ export const baseTableStyles = props => {
|
|
|
190
224
|
${((_props$featureFlags = props.featureFlags) === null || _props$featureFlags === void 0 ? void 0 : _props$featureFlags.tableDragAndDrop) && insertLine()};
|
|
191
225
|
${resizeHandle((_props$featureFlags2 = props.featureFlags) === null || _props$featureFlags2 === void 0 ? void 0 : _props$featureFlags2.tableDragAndDrop)};
|
|
192
226
|
${rangeSelectionStyles};
|
|
227
|
+
${viewModeSortStyles()};
|
|
193
228
|
|
|
194
229
|
.${ClassName.LAST_ITEM_IN_CELL} {
|
|
195
230
|
margin-bottom: 0;
|
|
@@ -5,7 +5,6 @@ import { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
|
5
5
|
import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
6
6
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
7
7
|
import { addColumnAt as addColumnAtPMUtils, addRowAt, findTable, selectedRect } from '@atlaskit/editor-tables/utils';
|
|
8
|
-
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
8
|
import { updateRowOrColumnMovedTransform } from '../pm-plugins/analytics/commands';
|
|
10
9
|
import { META_KEYS } from '../pm-plugins/table-analytics';
|
|
11
10
|
import { rescaleColumns } from '../transforms/column-width';
|
|
@@ -37,7 +36,7 @@ export function addColumnAt() {
|
|
|
37
36
|
// [ED-8288] Update colwidths manually to avoid multiple dispatch in TableComponent
|
|
38
37
|
updatedTr = rescaleColumns(isTableScalingEnabled)(table, view)(updatedTr);
|
|
39
38
|
}
|
|
40
|
-
if (
|
|
39
|
+
if (view) {
|
|
41
40
|
updatedTr = updateRowOrColumnMovedTransform({
|
|
42
41
|
type: 'column'
|
|
43
42
|
}, 'addRowOrColumn')(view.state, updatedTr);
|
|
@@ -125,11 +124,9 @@ export var insertRow = function insertRow(row, moveCursorToTheNewRow) {
|
|
|
125
124
|
} else {
|
|
126
125
|
tr.setSelection(selection.map(tr.doc, tr.mapping));
|
|
127
126
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}, 'addRowOrColumn')(state, tr);
|
|
132
|
-
}
|
|
127
|
+
updateRowOrColumnMovedTransform({
|
|
128
|
+
type: 'row'
|
|
129
|
+
}, 'addRowOrColumn')(state, tr);
|
|
133
130
|
dispatch(tr);
|
|
134
131
|
}
|
|
135
132
|
return true;
|
|
@@ -188,9 +188,16 @@ export var getTableElementMoveTypeBySlice = function getTableElementMoveTypeBySl
|
|
|
188
188
|
if (slice.content.childCount === 1 && slice.content.firstChild.type === tableRow) {
|
|
189
189
|
return 'row';
|
|
190
190
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return
|
|
191
|
+
|
|
192
|
+
// `TableMap.get` can throw if the content is invalid - in which case we should just
|
|
193
|
+
// return undefined
|
|
194
|
+
try {
|
|
195
|
+
var map = TableMap.get(currentTable.node);
|
|
196
|
+
var slicedMap = TableMap.get(slice.content.firstChild);
|
|
197
|
+
return map.width === slicedMap.width ? 'row' : map.height === slicedMap.height ? 'column' : undefined;
|
|
198
|
+
} catch (e) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
194
201
|
};
|
|
195
202
|
export var isInsideFirstCellOfRowOrColumn = function isInsideFirstCellOfRowOrColumn(selection, type) {
|
|
196
203
|
var table = findTable(selection);
|
|
@@ -66,6 +66,14 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
66
66
|
scroll: 0,
|
|
67
67
|
parentWidth: undefined
|
|
68
68
|
}, _defineProperty(_defineProperty2, ShadowEvent.SHOW_BEFORE_SHADOW, false), _defineProperty(_defineProperty2, ShadowEvent.SHOW_AFTER_SHADOW, false), _defineProperty(_defineProperty2, "tableWrapperWidth", undefined), _defineProperty(_defineProperty2, "tableWrapperHeight", undefined), _defineProperty2));
|
|
69
|
+
_defineProperty(_assertThisInitialized(_this), "handleMouseEnter", function () {
|
|
70
|
+
var node = _this.props.getNode();
|
|
71
|
+
var pos = _this.props.getPos();
|
|
72
|
+
var tr = _this.props.view.state.tr;
|
|
73
|
+
var tableId = node.attrs.localId;
|
|
74
|
+
tr.setMeta('mouseEnterTable', [tableId, node, pos]);
|
|
75
|
+
_this.props.view.dispatch(tr);
|
|
76
|
+
});
|
|
69
77
|
_defineProperty(_assertThisInitialized(_this), "updateShadowState", function (shadowKey, value) {
|
|
70
78
|
if (_this.state[shadowKey] === value) {
|
|
71
79
|
return;
|
|
@@ -331,6 +339,15 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
331
339
|
getNode = _this$props7.getNode,
|
|
332
340
|
getEditorFeatureFlags = _this$props7.getEditorFeatureFlags,
|
|
333
341
|
isTableScalingEnabled = _this$props7.isTableScalingEnabled;
|
|
342
|
+
if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
|
|
343
|
+
var _this$props$pluginInj;
|
|
344
|
+
var _ref = ((_this$props$pluginInj = this.props.pluginInjectionApi) === null || _this$props$pluginInj === void 0 || (_this$props$pluginInj = _this$props$pluginInj.editorViewMode) === null || _this$props$pluginInj === void 0 ? void 0 : _this$props$pluginInj.sharedState.currentState()) || {},
|
|
345
|
+
mode = _ref.mode;
|
|
346
|
+
if (mode === 'view') {
|
|
347
|
+
var _this$table;
|
|
348
|
+
this === null || this === void 0 || (_this$table = this.table) === null || _this$table === void 0 || _this$table.addEventListener('mouseenter', this.handleMouseEnter);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
334
351
|
if (isTableScalingEnabled) {
|
|
335
352
|
this.handleColgroupUpdates(true);
|
|
336
353
|
}
|
|
@@ -406,6 +423,10 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
406
423
|
if (!(options !== null && options !== void 0 && options.isTableResizingEnabled) && allowColumnResizing) {
|
|
407
424
|
window.removeEventListener('resize', this.handleWindowResizeDebounced);
|
|
408
425
|
}
|
|
426
|
+
if (getBooleanFF('platform.editor.table.live-pages-sorting_4malx')) {
|
|
427
|
+
var _this$table2;
|
|
428
|
+
this === null || this === void 0 || (_this$table2 = this.table) === null || _this$table2 === void 0 || _this$table2.removeEventListener('mouseenter', this.handleMouseEnter);
|
|
429
|
+
}
|
|
409
430
|
if (this.overflowShadowsObserver) {
|
|
410
431
|
this.overflowShadowsObserver.dispose();
|
|
411
432
|
}
|
|
@@ -520,8 +541,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
520
541
|
var isNoOfColumnsChanged = tablesHaveDifferentNoOfColumns(currentTable, previousTable);
|
|
521
542
|
var isNoOfRowsChanged = tablesHaveDifferentNoOfRows(currentTable, previousTable);
|
|
522
543
|
if (isNoOfColumnsChanged || isNoOfRowsChanged) {
|
|
523
|
-
var _this$props$
|
|
524
|
-
(_this$props$
|
|
544
|
+
var _this$props$pluginInj2;
|
|
545
|
+
(_this$props$pluginInj2 = this.props.pluginInjectionApi) === null || _this$props$pluginInj2 === void 0 || (_this$props$pluginInj2 = _this$props$pluginInj2.accessibilityUtils) === null || _this$props$pluginInj2 === void 0 || _this$props$pluginInj2.actions.ariaNotify(getAssistiveMessage(previousTable, currentTable, this.props.intl), {
|
|
525
546
|
priority: 'important'
|
|
526
547
|
});
|
|
527
548
|
}
|
package/dist/esm/plugin.js
CHANGED
|
@@ -27,6 +27,7 @@ import { createPlugin as createTableLocalIdPlugin } from './pm-plugins/table-loc
|
|
|
27
27
|
import { createPlugin as createFlexiResizingPlugin, getPluginState as getFlexiResizingPlugin, pluginKey as tableResizingPluginKey } from './pm-plugins/table-resizing';
|
|
28
28
|
import { tableSelectionKeymapPlugin } from './pm-plugins/table-selection-keymap';
|
|
29
29
|
import { createPlugin as createTableWidthPlugin, pluginKey as tableWidthPluginKey } from './pm-plugins/table-width';
|
|
30
|
+
import { createPlugin as createViewModeSortPlugin } from './pm-plugins/view-mode-sort';
|
|
30
31
|
import { getToolbarConfig } from './toolbar';
|
|
31
32
|
import FloatingContextualButton from './ui/FloatingContextualButton';
|
|
32
33
|
import FloatingContextualMenu from './ui/FloatingContextualMenu';
|
|
@@ -219,6 +220,11 @@ var tablesPlugin = function tablesPlugin(_ref) {
|
|
|
219
220
|
var dispatch = _ref11.dispatch;
|
|
220
221
|
return options !== null && options !== void 0 && options.dragAndDropEnabled ? createDragAndDropPlugin(dispatch, editorAnalyticsAPI) : undefined;
|
|
221
222
|
}
|
|
223
|
+
}, {
|
|
224
|
+
name: 'tableViewModeSort',
|
|
225
|
+
plugin: function plugin() {
|
|
226
|
+
return getBooleanFF('platform.editor.table.live-pages-sorting_4malx') && api !== null && api !== void 0 && api.editorViewMode ? createViewModeSortPlugin(api.editorViewMode) : undefined;
|
|
227
|
+
}
|
|
222
228
|
}, {
|
|
223
229
|
name: 'tableLocalId',
|
|
224
230
|
plugin: function plugin(_ref12) {
|
|
@@ -248,7 +254,7 @@ var tablesPlugin = function tablesPlugin(_ref) {
|
|
|
248
254
|
plugin: function plugin(_ref15) {
|
|
249
255
|
var dispatch = _ref15.dispatch,
|
|
250
256
|
dispatchAnalyticsEvent = _ref15.dispatchAnalyticsEvent;
|
|
251
|
-
return
|
|
257
|
+
return createTableAnalyticsPlugin(dispatch, dispatchAnalyticsEvent);
|
|
252
258
|
}
|
|
253
259
|
}, {
|
|
254
260
|
name: 'tableGetEditorViewReferencePlugin',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
-
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
4
3
|
import { countCellsInSlice, getTableElementMoveTypeBySlice, getTableSelectionType, isInsideFirstCellOfRowOrColumn } from '../../commands/misc';
|
|
5
4
|
import { resetRowOrColumnMovedTransform, updateRowOrColumnMoved } from './commands';
|
|
6
5
|
import { createPluginState } from './plugin-factory';
|
|
@@ -34,33 +33,29 @@ export var createPlugin = function createPlugin(dispatch, dispatchAnalyticsEvent
|
|
|
34
33
|
handlePaste: function handlePaste(_ref, event, slice) {
|
|
35
34
|
var state = _ref.state,
|
|
36
35
|
dispatch = _ref.dispatch;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
var type = getTableElementMoveTypeBySlice(slice, state);
|
|
36
|
+
var schema = state.schema;
|
|
37
|
+
var type = getTableElementMoveTypeBySlice(slice, state);
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
var count = countCellsInSlice(slice, schema, type);
|
|
46
|
-
updateRowOrColumnMoved({
|
|
47
|
-
numberOfCells: count,
|
|
48
|
-
type: type
|
|
49
|
-
}, 'pasted')(state, dispatch);
|
|
39
|
+
// if the selection wasn't in the first cell of a row or column, don't count it
|
|
40
|
+
if (!type || !isInsideFirstCellOfRowOrColumn(state.selection, type)) {
|
|
41
|
+
return;
|
|
50
42
|
}
|
|
43
|
+
var count = countCellsInSlice(slice, schema, type);
|
|
44
|
+
updateRowOrColumnMoved({
|
|
45
|
+
numberOfCells: count,
|
|
46
|
+
type: type
|
|
47
|
+
}, 'pasted')(state, dispatch);
|
|
51
48
|
},
|
|
52
49
|
transformCopied: function transformCopied(slice, _ref2) {
|
|
53
50
|
var state = _ref2.state,
|
|
54
51
|
dispatch = _ref2.dispatch;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}, 'copyOrCut')(state, dispatch);
|
|
63
|
-
}
|
|
52
|
+
var schema = state.schema;
|
|
53
|
+
var type = getTableSelectionType(state.selection);
|
|
54
|
+
var count = countCellsInSlice(slice, schema, type);
|
|
55
|
+
updateRowOrColumnMoved({
|
|
56
|
+
numberOfCells: count,
|
|
57
|
+
type: type
|
|
58
|
+
}, 'copyOrCut')(state, dispatch);
|
|
64
59
|
return slice;
|
|
65
60
|
}
|
|
66
61
|
}
|