@atlaskit/editor-tables 2.2.3 → 2.2.5
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 +14 -0
- package/dist/cjs/cell-bookmark.js +0 -10
- package/dist/cjs/cell-selection.js +37 -102
- package/dist/cjs/index.js +0 -4
- package/dist/cjs/pm-plugins/input.js +24 -75
- package/dist/cjs/pm-plugins/plugin-key.js +0 -2
- package/dist/cjs/pm-plugins/table-editing.js +17 -18
- package/dist/cjs/pm-plugins.js +0 -2
- package/dist/cjs/table-map.js +63 -134
- package/dist/cjs/utils/add-column-at.js +0 -9
- package/dist/cjs/utils/add-column.js +8 -24
- package/dist/cjs/utils/add-row-at.js +8 -37
- package/dist/cjs/utils/add-row.js +2 -23
- package/dist/cjs/utils/analytics-helpers.js +4 -15
- package/dist/cjs/utils/cells.js +0 -12
- package/dist/cjs/utils/clone-tr.js +0 -2
- package/dist/cjs/utils/colspan.js +2 -18
- package/dist/cjs/utils/copy-paste.js +94 -120
- package/dist/cjs/utils/create-table.js +14 -28
- package/dist/cjs/utils/draw-cell-selection.js +0 -4
- package/dist/cjs/utils/empty-cells.js +0 -6
- package/dist/cjs/utils/find.js +6 -18
- package/dist/cjs/utils/fix-tables.js +13 -56
- package/dist/cjs/utils/for-each-cell.js +3 -17
- package/dist/cjs/utils/get-cell-selection-ranges.js +2 -9
- package/dist/cjs/utils/get-cells-in-column.js +0 -7
- package/dist/cjs/utils/get-cells-in-row.js +0 -7
- package/dist/cjs/utils/get-cells-in-table.js +0 -8
- package/dist/cjs/utils/get-selection-range-in-column.js +6 -27
- package/dist/cjs/utils/get-selection-range-in-row.js +6 -27
- package/dist/cjs/utils/get-selection-rect.js +0 -7
- package/dist/cjs/utils/go-to-next-cell.js +3 -22
- package/dist/cjs/utils/handle-paste.js +4 -33
- package/dist/cjs/utils/is-selected.js +6 -23
- package/dist/cjs/utils/is-selection-type.js +0 -2
- package/dist/cjs/utils/move-column.js +0 -12
- package/dist/cjs/utils/move-row.js +0 -11
- package/dist/cjs/utils/normalize-selection.js +3 -27
- package/dist/cjs/utils/remove-column.js +10 -46
- package/dist/cjs/utils/remove-row.js +8 -49
- package/dist/cjs/utils/remove-table.js +0 -6
- package/dist/cjs/utils/reorder-utils.js +13 -37
- package/dist/cjs/utils/replace-table.js +0 -8
- package/dist/cjs/utils/select-nodes.js +11 -31
- package/dist/cjs/utils/selection-cell.js +0 -5
- package/dist/cjs/utils/selection-rect.js +0 -10
- package/dist/cjs/utils/set-cell-attrs.js +0 -4
- package/dist/cjs/utils/split-cell-with-type.js +2 -35
- package/dist/cjs/utils/split-cell.js +0 -4
- package/dist/cjs/utils/table-node-types.js +4 -8
- package/dist/cjs/utils/tables.js +0 -4
- package/dist/cjs/utils/test-utils.js +9 -26
- package/dist/cjs/utils/toggle-header.js +4 -16
- package/dist/cjs/utils/uuid.js +0 -3
- package/dist/cjs/utils.js +0 -42
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/cell-bookmark.js +0 -5
- package/dist/es2019/cell-selection.js +37 -81
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/pm-plugins/input.js +27 -63
- package/dist/es2019/pm-plugins/table-editing.js +3 -12
- package/dist/es2019/table-map.js +54 -124
- package/dist/es2019/utils/add-column-at.js +2 -4
- package/dist/es2019/utils/add-column.js +6 -16
- package/dist/es2019/utils/add-row-at.js +8 -22
- package/dist/es2019/utils/add-row.js +2 -17
- package/dist/es2019/utils/analytics-helpers.js +0 -5
- package/dist/es2019/utils/cells.js +4 -9
- package/dist/es2019/utils/colspan.js +6 -11
- package/dist/es2019/utils/copy-paste.js +85 -99
- package/dist/es2019/utils/create-table.js +3 -12
- package/dist/es2019/utils/draw-cell-selection.js +0 -1
- package/dist/es2019/utils/empty-cells.js +2 -3
- package/dist/es2019/utils/find.js +8 -8
- package/dist/es2019/utils/fix-tables.js +17 -47
- package/dist/es2019/utils/for-each-cell.js +6 -11
- package/dist/es2019/utils/get-cell-selection-ranges.js +2 -4
- package/dist/es2019/utils/get-cells-in-column.js +2 -3
- package/dist/es2019/utils/get-cells-in-row.js +2 -3
- package/dist/es2019/utils/get-cells-in-table.js +2 -4
- package/dist/es2019/utils/get-selection-range-in-column.js +8 -22
- package/dist/es2019/utils/get-selection-range-in-row.js +8 -22
- package/dist/es2019/utils/get-selection-rect.js +2 -2
- package/dist/es2019/utils/go-to-next-cell.js +3 -19
- package/dist/es2019/utils/handle-paste.js +3 -14
- package/dist/es2019/utils/is-selected.js +8 -10
- package/dist/es2019/utils/is-selection-type.js +0 -1
- package/dist/es2019/utils/move-column.js +3 -8
- package/dist/es2019/utils/move-row.js +3 -7
- package/dist/es2019/utils/normalize-selection.js +0 -16
- package/dist/es2019/utils/remove-column.js +10 -27
- package/dist/es2019/utils/remove-row.js +12 -32
- package/dist/es2019/utils/remove-table.js +2 -4
- package/dist/es2019/utils/reorder-utils.js +11 -26
- package/dist/es2019/utils/replace-table.js +0 -2
- package/dist/es2019/utils/select-nodes.js +9 -20
- package/dist/es2019/utils/selection-cell.js +0 -2
- package/dist/es2019/utils/selection-rect.js +0 -4
- package/dist/es2019/utils/set-cell-attrs.js +2 -2
- package/dist/es2019/utils/split-cell-with-type.js +8 -28
- package/dist/es2019/utils/split-cell.js +3 -2
- package/dist/es2019/utils/table-node-types.js +4 -7
- package/dist/es2019/utils/tables.js +0 -2
- package/dist/es2019/utils/test-utils.js +12 -16
- package/dist/es2019/utils/toggle-header.js +4 -13
- package/dist/es2019/utils/uuid.js +0 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/cell-bookmark.js +0 -5
- package/dist/esm/cell-selection.js +37 -79
- package/dist/esm/index.js +1 -0
- package/dist/esm/pm-plugins/input.js +24 -63
- package/dist/esm/pm-plugins/table-editing.js +8 -13
- package/dist/esm/table-map.js +65 -130
- package/dist/esm/utils/add-column-at.js +2 -4
- package/dist/esm/utils/add-column.js +8 -20
- package/dist/esm/utils/add-row-at.js +8 -23
- package/dist/esm/utils/add-row.js +2 -21
- package/dist/esm/utils/analytics-helpers.js +4 -10
- package/dist/esm/utils/cells.js +0 -5
- package/dist/esm/utils/colspan.js +2 -14
- package/dist/esm/utils/copy-paste.js +88 -109
- package/dist/esm/utils/create-table.js +14 -25
- package/dist/esm/utils/draw-cell-selection.js +0 -1
- package/dist/esm/utils/empty-cells.js +2 -3
- package/dist/esm/utils/find.js +8 -8
- package/dist/esm/utils/fix-tables.js +13 -49
- package/dist/esm/utils/for-each-cell.js +6 -11
- package/dist/esm/utils/get-cell-selection-ranges.js +2 -4
- package/dist/esm/utils/get-cells-in-column.js +2 -3
- package/dist/esm/utils/get-cells-in-row.js +2 -3
- package/dist/esm/utils/get-cells-in-table.js +2 -4
- package/dist/esm/utils/get-selection-range-in-column.js +8 -24
- package/dist/esm/utils/get-selection-range-in-row.js +8 -24
- package/dist/esm/utils/get-selection-rect.js +2 -2
- package/dist/esm/utils/go-to-next-cell.js +3 -19
- package/dist/esm/utils/handle-paste.js +4 -22
- package/dist/esm/utils/is-selected.js +8 -10
- package/dist/esm/utils/is-selection-type.js +0 -1
- package/dist/esm/utils/move-column.js +3 -8
- package/dist/esm/utils/move-row.js +3 -7
- package/dist/esm/utils/normalize-selection.js +3 -22
- package/dist/esm/utils/remove-column.js +10 -31
- package/dist/esm/utils/remove-row.js +8 -35
- package/dist/esm/utils/remove-table.js +2 -4
- package/dist/esm/utils/reorder-utils.js +11 -26
- package/dist/esm/utils/replace-table.js +0 -2
- package/dist/esm/utils/select-nodes.js +11 -22
- package/dist/esm/utils/selection-cell.js +0 -2
- package/dist/esm/utils/selection-rect.js +0 -4
- package/dist/esm/utils/set-cell-attrs.js +2 -2
- package/dist/esm/utils/split-cell-with-type.js +2 -28
- package/dist/esm/utils/split-cell.js +3 -2
- package/dist/esm/utils/table-node-types.js +4 -7
- package/dist/esm/utils/tables.js +0 -2
- package/dist/esm/utils/test-utils.js +12 -16
- package/dist/esm/utils/toggle-header.js +4 -13
- package/dist/esm/version.json +1 -1
- package/dist/types/utils/toggle-header.d.ts +3 -0
- package/package.json +7 -5
- package/report.api.md +11 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// Was copied from https://github.com/ProseMirror/prosemirror-tables/blob/master/src/cellselection.js
|
|
2
|
+
|
|
2
3
|
// This file defines a ProseMirror selection subclass that models
|
|
3
4
|
// table cell selections. The table plugin needs to be active to wire
|
|
4
5
|
// in the user interaction part of table selections (so that you
|
|
5
6
|
// actually get such selections when you select across cells).
|
|
7
|
+
|
|
6
8
|
import { Fragment, Slice } from 'prosemirror-model';
|
|
7
9
|
import { Selection, TextSelection } from 'prosemirror-state';
|
|
8
10
|
import { CellBookmark } from './cell-bookmark';
|
|
@@ -10,56 +12,52 @@ import { TableMap } from './table-map';
|
|
|
10
12
|
import { pointsAtCell } from './utils/cells';
|
|
11
13
|
import { removeColSpan } from './utils/colspan';
|
|
12
14
|
import { getCellSelectionRanges } from './utils/get-cell-selection-ranges';
|
|
13
|
-
import { inSameTable } from './utils/tables';
|
|
15
|
+
import { inSameTable } from './utils/tables';
|
|
16
|
+
|
|
17
|
+
// ::- A [`Selection`](http://prosemirror.net/docs/ref/#state.Selection)
|
|
14
18
|
// subclass that represents a cell selection spanning part of a table.
|
|
15
19
|
// With the plugin enabled, these will be created when the user
|
|
16
20
|
// selects across cells, and will be drawn by giving selected cells a
|
|
17
21
|
// `selectedCell` CSS class.
|
|
18
|
-
|
|
19
22
|
export class CellSelection extends Selection {
|
|
20
23
|
// :: (ResolvedPos, ?ResolvedPos)
|
|
21
24
|
// A table selection is identified by its anchor and head cells. The
|
|
22
25
|
// positions given to this constructor should point _before_ two
|
|
23
26
|
// cells in the same table. They may be the same, to select a single
|
|
24
27
|
// cell.
|
|
28
|
+
|
|
25
29
|
constructor($anchorCell, $headCell = $anchorCell) {
|
|
26
30
|
const ranges = getCellSelectionRanges($anchorCell, $headCell);
|
|
27
|
-
super(ranges[0].$from, ranges[0].$to, ranges);
|
|
31
|
+
super(ranges[0].$from, ranges[0].$to, ranges);
|
|
32
|
+
// :: ResolvedPos
|
|
28
33
|
// A resolved position pointing _in front of_ the anchor cell (the one
|
|
29
34
|
// that doesn't move when extending the selection).
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
this.$anchorCell = $anchorCell;
|
|
36
|
+
// :: ResolvedPos
|
|
32
37
|
// A resolved position pointing in front of the head cell (the one
|
|
33
38
|
// moves when extending the selection).
|
|
34
|
-
|
|
35
39
|
this.$headCell = $headCell;
|
|
36
40
|
this.visible = false;
|
|
37
41
|
}
|
|
38
|
-
|
|
39
42
|
map(doc, mapping) {
|
|
40
43
|
const $anchorCell = doc.resolve(mapping.map(this.$anchorCell.pos));
|
|
41
44
|
const $headCell = doc.resolve(mapping.map(this.$headCell.pos));
|
|
42
|
-
|
|
43
45
|
if (pointsAtCell($anchorCell) && pointsAtCell($headCell) && inSameTable($anchorCell, $headCell)) {
|
|
44
46
|
const tableChanged = this.$anchorCell.node(-1) !== $anchorCell.node(-1);
|
|
45
|
-
|
|
46
47
|
if (tableChanged && this.isRowSelection()) {
|
|
47
48
|
return CellSelection.rowSelection($anchorCell, $headCell);
|
|
48
49
|
}
|
|
49
|
-
|
|
50
50
|
if (tableChanged && this.isColSelection()) {
|
|
51
51
|
return CellSelection.colSelection($anchorCell, $headCell);
|
|
52
52
|
}
|
|
53
|
-
|
|
54
53
|
return new CellSelection($anchorCell, $headCell);
|
|
55
54
|
}
|
|
56
|
-
|
|
57
55
|
return TextSelection.between($anchorCell, $headCell);
|
|
58
|
-
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// :: () → Slice
|
|
59
59
|
// Returns a rectangular slice of table rows containing the selected
|
|
60
60
|
// cells.
|
|
61
|
-
|
|
62
|
-
|
|
63
61
|
content() {
|
|
64
62
|
const table = this.$anchorCell.node(-1);
|
|
65
63
|
const map = TableMap.get(table);
|
|
@@ -67,86 +65,68 @@ export class CellSelection extends Selection {
|
|
|
67
65
|
const rect = map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start);
|
|
68
66
|
const seen = {};
|
|
69
67
|
const rows = [];
|
|
70
|
-
|
|
71
68
|
for (let row = rect.top; row < rect.bottom; row++) {
|
|
72
69
|
const rowContent = [];
|
|
73
|
-
|
|
74
70
|
for (let index = row * map.width + rect.left, col = rect.left; col < rect.right; col++, index++) {
|
|
75
71
|
const pos = map.map[index];
|
|
76
|
-
|
|
77
72
|
if (!seen[pos]) {
|
|
78
73
|
seen[pos] = true;
|
|
79
74
|
const cellRect = map.findCell(pos);
|
|
80
75
|
let cell = table.nodeAt(pos);
|
|
81
|
-
|
|
82
76
|
if (cell === null || cell === undefined) {
|
|
83
77
|
throw new Error(`No cell at position ${pos}`);
|
|
84
78
|
}
|
|
85
|
-
|
|
86
79
|
const extraLeft = rect.left - cellRect.left;
|
|
87
80
|
const extraRight = cellRect.right - rect.right;
|
|
88
|
-
|
|
89
81
|
if (extraLeft > 0 || extraRight > 0) {
|
|
90
82
|
let {
|
|
91
83
|
attrs
|
|
92
84
|
} = cell;
|
|
93
|
-
|
|
94
85
|
if (!attrs) {
|
|
95
86
|
throw new Error(`No cell at position ${pos}`);
|
|
96
87
|
}
|
|
97
|
-
|
|
98
88
|
if (extraLeft > 0) {
|
|
99
89
|
attrs = removeColSpan(attrs, 0, extraLeft);
|
|
100
90
|
}
|
|
101
|
-
|
|
102
91
|
if (extraRight > 0) {
|
|
103
92
|
attrs = removeColSpan(attrs, attrs.colspan - extraRight, extraRight);
|
|
104
93
|
}
|
|
105
|
-
|
|
106
94
|
if (cellRect.left < rect.left) {
|
|
107
95
|
cell = cell.type.createAndFill(attrs);
|
|
108
96
|
} else {
|
|
109
97
|
cell = cell.type.create(attrs, cell.content);
|
|
110
98
|
}
|
|
111
99
|
}
|
|
112
|
-
|
|
113
100
|
if (cell === null || cell === undefined) {
|
|
114
101
|
throw new Error(`No cell at position after create/createAndFill`);
|
|
115
102
|
}
|
|
116
|
-
|
|
117
103
|
if (cellRect.top < rect.top || cellRect.bottom > rect.bottom) {
|
|
118
|
-
const attrs = {
|
|
104
|
+
const attrs = {
|
|
105
|
+
...cell.attrs,
|
|
119
106
|
rowspan: Math.min(cellRect.bottom, rect.bottom) - Math.max(cellRect.top, rect.top)
|
|
120
107
|
};
|
|
121
|
-
|
|
122
108
|
if (cellRect.top < rect.top) {
|
|
123
109
|
cell = cell.type.createAndFill(attrs);
|
|
124
110
|
} else {
|
|
125
111
|
cell = cell.type.create(attrs, cell.content);
|
|
126
112
|
}
|
|
127
113
|
}
|
|
128
|
-
|
|
129
114
|
if (cell === null || cell === undefined) {
|
|
130
115
|
throw new Error(`No cell at position before rowContent.push`);
|
|
131
116
|
}
|
|
132
|
-
|
|
133
117
|
rowContent.push(cell);
|
|
134
118
|
}
|
|
135
119
|
}
|
|
136
|
-
|
|
137
120
|
rows.push(table.child(row).copy(Fragment.from(rowContent)));
|
|
138
121
|
}
|
|
139
|
-
|
|
140
122
|
const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
|
|
141
123
|
return new Slice(Fragment.from(fragment), 1, 1);
|
|
142
124
|
}
|
|
143
|
-
|
|
144
125
|
replace(tr, content = Slice.empty) {
|
|
145
126
|
const mapFrom = tr.steps.length;
|
|
146
127
|
const {
|
|
147
128
|
ranges
|
|
148
129
|
} = this;
|
|
149
|
-
|
|
150
130
|
for (let i = 0; i < ranges.length; i++) {
|
|
151
131
|
const {
|
|
152
132
|
$from,
|
|
@@ -155,58 +135,48 @@ export class CellSelection extends Selection {
|
|
|
155
135
|
const mapping = tr.mapping.slice(mapFrom);
|
|
156
136
|
tr.replace(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content);
|
|
157
137
|
}
|
|
158
|
-
|
|
159
138
|
const sel = Selection.findFrom(tr.doc.resolve(tr.mapping.slice(mapFrom).map(this.to)), -1);
|
|
160
|
-
|
|
161
139
|
if (sel) {
|
|
162
140
|
tr.setSelection(sel);
|
|
163
141
|
}
|
|
164
142
|
}
|
|
165
|
-
|
|
166
143
|
replaceWith(tr, node) {
|
|
167
144
|
this.replace(tr, new Slice(Fragment.from(node), 0, 0));
|
|
168
145
|
}
|
|
169
|
-
|
|
170
146
|
forEachCell(f) {
|
|
171
147
|
const table = this.$anchorCell.node(-1);
|
|
172
148
|
const map = TableMap.get(table);
|
|
173
149
|
const start = this.$anchorCell.start(-1);
|
|
174
150
|
const cells = map.cellsInRect(map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start));
|
|
175
|
-
|
|
176
151
|
for (let i = 0; i < cells.length; i++) {
|
|
177
152
|
const cell = table.nodeAt(cells[i]);
|
|
178
|
-
|
|
179
153
|
if (cell === null || cell === undefined) {
|
|
180
154
|
throw new Error(`undefined cell at pos ${cells[i]}`);
|
|
181
155
|
}
|
|
182
|
-
|
|
183
156
|
f(cell, start + cells[i]);
|
|
184
157
|
}
|
|
185
|
-
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// :: () → bool
|
|
186
161
|
// True if this selection goes all the way from the top to the
|
|
187
162
|
// bottom of the table.
|
|
188
|
-
|
|
189
|
-
|
|
190
163
|
isColSelection() {
|
|
191
164
|
if (!this.$anchorCell || !this.$headCell) {
|
|
192
165
|
throw new Error('invalid $anchorCell or $headCell');
|
|
193
166
|
}
|
|
194
|
-
|
|
195
167
|
const anchorTop = this.$anchorCell.index(-1);
|
|
196
168
|
const headTop = this.$headCell.index(-1);
|
|
197
|
-
|
|
198
169
|
if (Math.min(anchorTop, headTop) > 0) {
|
|
199
170
|
return false;
|
|
200
171
|
}
|
|
201
|
-
|
|
202
172
|
const anchorBot = anchorTop + this.$anchorCell.nodeAfter.attrs.rowspan;
|
|
203
173
|
const headBot = headTop + this.$headCell.nodeAfter.attrs.rowspan;
|
|
204
174
|
return Math.max(anchorBot, headBot) === this.$headCell.node(-1).childCount;
|
|
205
|
-
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// :: (ResolvedPos, ?ResolvedPos) → CellSelection
|
|
206
178
|
// Returns the smallest column selection that covers the given anchor
|
|
207
179
|
// and head cell.
|
|
208
|
-
|
|
209
|
-
|
|
210
180
|
static colSelection($anchorCell, $headCell = $anchorCell) {
|
|
211
181
|
let $calculatedAnchorCell = $anchorCell;
|
|
212
182
|
let $calculatedHeadCell = $headCell;
|
|
@@ -215,12 +185,10 @@ export class CellSelection extends Selection {
|
|
|
215
185
|
const anchorRect = map.findCell($calculatedAnchorCell.pos - start);
|
|
216
186
|
const headRect = map.findCell($calculatedHeadCell.pos - start);
|
|
217
187
|
const doc = $calculatedAnchorCell.node(0);
|
|
218
|
-
|
|
219
188
|
if (anchorRect.top <= headRect.top) {
|
|
220
189
|
if (anchorRect.top > 0) {
|
|
221
190
|
$calculatedAnchorCell = doc.resolve(start + map.map[anchorRect.left]);
|
|
222
191
|
}
|
|
223
|
-
|
|
224
192
|
if (headRect.bottom < map.height) {
|
|
225
193
|
$calculatedHeadCell = doc.resolve(start + map.map[map.width * (map.height - 1) + headRect.right - 1]);
|
|
226
194
|
}
|
|
@@ -228,59 +196,55 @@ export class CellSelection extends Selection {
|
|
|
228
196
|
if (headRect.top > 0) {
|
|
229
197
|
$calculatedHeadCell = doc.resolve(start + map.map[headRect.left]);
|
|
230
198
|
}
|
|
231
|
-
|
|
232
199
|
if (anchorRect.bottom < map.height) {
|
|
233
200
|
$calculatedAnchorCell = doc.resolve(start + map.map[map.width * (map.height - 1) + anchorRect.right - 1]);
|
|
234
201
|
}
|
|
235
202
|
}
|
|
236
|
-
|
|
237
203
|
return new CellSelection($calculatedAnchorCell, $calculatedHeadCell);
|
|
238
|
-
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// :: () → bool
|
|
239
207
|
// True if this selection goes all the way from the left to the
|
|
240
208
|
// right of the table.
|
|
241
|
-
|
|
242
|
-
|
|
243
209
|
isRowSelection() {
|
|
244
210
|
if (!this.$anchorCell || !this.$headCell) {
|
|
245
211
|
return false;
|
|
246
212
|
}
|
|
247
|
-
|
|
248
213
|
const start = this.$anchorCell.start(-1);
|
|
249
214
|
const map = TableMap.get(this.$anchorCell.node(-1));
|
|
250
215
|
const rowAtAnchorCell = map.rowCount(this.$anchorCell.pos - start);
|
|
251
216
|
const rowAtHeadCell = map.rowCount(this.$headCell.pos - start);
|
|
252
|
-
const isSelectionSameRow = rowAtAnchorCell === rowAtHeadCell;
|
|
217
|
+
const isSelectionSameRow = rowAtAnchorCell === rowAtHeadCell;
|
|
218
|
+
|
|
219
|
+
// if anchor and head in the same line, counting how many cells
|
|
253
220
|
// should be in the row except merged cell
|
|
221
|
+
let maxColumnInSelectedRow = map.getMaxColInRow(this.$anchorCell);
|
|
254
222
|
|
|
255
|
-
|
|
223
|
+
// if selected cells less than table max column amount, and
|
|
256
224
|
// the anchor/head not in a merged cell
|
|
257
225
|
// it should be select maxColumnInSelectedRow to be TRUE
|
|
258
|
-
|
|
259
226
|
if (isSelectionSameRow && this.ranges.length <= map.width && !map.isPosMerged(this.$anchorCell.pos - start) && !map.isPosMerged(this.$headCell.pos - start)) {
|
|
260
227
|
return this.ranges.length === maxColumnInSelectedRow;
|
|
261
|
-
}
|
|
262
|
-
// last column to select the whole row.
|
|
263
|
-
|
|
228
|
+
}
|
|
264
229
|
|
|
230
|
+
// If anchor and head in different row, it should be always in first and
|
|
231
|
+
// last column to select the whole row.
|
|
265
232
|
const anchorLeft = map.colCount(this.$anchorCell.pos - start);
|
|
266
233
|
const headLeft = map.colCount(this.$headCell.pos - start);
|
|
267
|
-
|
|
268
234
|
if (Math.min(anchorLeft, headLeft) > 0) {
|
|
269
235
|
return false;
|
|
270
236
|
}
|
|
271
|
-
|
|
272
237
|
const anchorRight = anchorLeft + this.$anchorCell.nodeAfter.attrs.colspan;
|
|
273
238
|
const headRight = headLeft + this.$headCell.nodeAfter.attrs.colspan;
|
|
274
239
|
return Math.max(anchorRight, headRight) === map.width;
|
|
275
240
|
}
|
|
276
|
-
|
|
277
241
|
eq(other) {
|
|
278
242
|
return other instanceof CellSelection && other.$anchorCell.pos === this.$anchorCell.pos && other.$headCell.pos === this.$headCell.pos;
|
|
279
|
-
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// :: (ResolvedPos, ?ResolvedPos) → CellSelection
|
|
280
246
|
// Returns the smallest row selection that covers the given anchor
|
|
281
247
|
// and head cell.
|
|
282
|
-
|
|
283
|
-
|
|
284
248
|
static rowSelection($anchorCell, $headCell = $anchorCell) {
|
|
285
249
|
let $calculatedAnchorCell = $anchorCell;
|
|
286
250
|
let $calculatedHeadCell = $headCell;
|
|
@@ -289,12 +253,10 @@ export class CellSelection extends Selection {
|
|
|
289
253
|
const anchorRect = map.findCell($calculatedAnchorCell.pos - start);
|
|
290
254
|
const headRect = map.findCell($calculatedHeadCell.pos - start);
|
|
291
255
|
const doc = $calculatedAnchorCell.node(0);
|
|
292
|
-
|
|
293
256
|
if (anchorRect.left <= headRect.left) {
|
|
294
257
|
if (anchorRect.left > 0) {
|
|
295
258
|
$calculatedAnchorCell = doc.resolve(start + map.map[anchorRect.top * map.width]);
|
|
296
259
|
}
|
|
297
|
-
|
|
298
260
|
if (headRect.right < map.width) {
|
|
299
261
|
$calculatedHeadCell = doc.resolve(start + map.map[map.width * (headRect.top + 1) - 1]);
|
|
300
262
|
}
|
|
@@ -302,15 +264,12 @@ export class CellSelection extends Selection {
|
|
|
302
264
|
if (headRect.left > 0) {
|
|
303
265
|
$calculatedHeadCell = doc.resolve(start + map.map[headRect.top * map.width]);
|
|
304
266
|
}
|
|
305
|
-
|
|
306
267
|
if (anchorRect.right < map.width) {
|
|
307
268
|
$calculatedAnchorCell = doc.resolve(start + map.map[map.width * (anchorRect.top + 1) - 1]);
|
|
308
269
|
}
|
|
309
270
|
}
|
|
310
|
-
|
|
311
271
|
return new CellSelection($calculatedAnchorCell, $calculatedHeadCell);
|
|
312
272
|
}
|
|
313
|
-
|
|
314
273
|
toJSON() {
|
|
315
274
|
return {
|
|
316
275
|
type: 'cell',
|
|
@@ -318,19 +277,16 @@ export class CellSelection extends Selection {
|
|
|
318
277
|
head: this.$headCell.pos
|
|
319
278
|
};
|
|
320
279
|
}
|
|
321
|
-
|
|
322
280
|
static fromJSON(doc, json) {
|
|
323
281
|
return new CellSelection(doc.resolve(json.anchor), doc.resolve(json.head));
|
|
324
|
-
}
|
|
325
|
-
|
|
282
|
+
}
|
|
326
283
|
|
|
284
|
+
// :: (Node, number, ?number) → CellSelection
|
|
327
285
|
static create(doc, anchorCell, headCell = anchorCell) {
|
|
328
286
|
return new CellSelection(doc.resolve(anchorCell), doc.resolve(headCell));
|
|
329
287
|
}
|
|
330
|
-
|
|
331
288
|
getBookmark() {
|
|
332
289
|
return new CellBookmark(this.$anchorCell.pos, this.$headCell.pos);
|
|
333
290
|
}
|
|
334
|
-
|
|
335
291
|
}
|
|
336
292
|
Selection.jsonID('cell', CellSelection);
|
package/dist/es2019/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// This file defines a number of helpers for wiring up user input to
|
|
2
2
|
// table-related functionality.
|
|
3
|
+
|
|
3
4
|
import { keydownHandler } from 'prosemirror-keymap';
|
|
4
5
|
import { Slice } from 'prosemirror-model';
|
|
5
6
|
import { Selection, TextSelection } from 'prosemirror-state';
|
|
@@ -22,46 +23,35 @@ export const handleKeyDown = keydownHandler({
|
|
|
22
23
|
Delete: deleteCellSelection,
|
|
23
24
|
'Mod-Delete': deleteCellSelection
|
|
24
25
|
});
|
|
25
|
-
|
|
26
26
|
function maybeSetSelection(state, dispatch, selection) {
|
|
27
27
|
if (selection.eq(state.selection)) {
|
|
28
28
|
return false;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
30
|
if (dispatch) {
|
|
32
31
|
dispatch(state.tr.setSelection(selection).scrollIntoView());
|
|
33
32
|
}
|
|
34
|
-
|
|
35
33
|
return true;
|
|
36
34
|
}
|
|
37
|
-
|
|
38
35
|
function arrow(axis, dir) {
|
|
39
36
|
return (state, dispatch, view) => {
|
|
40
37
|
if (dispatch) {
|
|
41
38
|
const sel = state.selection;
|
|
42
|
-
|
|
43
39
|
if (sel instanceof CellSelection) {
|
|
44
40
|
return maybeSetSelection(state, dispatch, Selection.near(sel.$headCell, dir));
|
|
45
41
|
}
|
|
46
|
-
|
|
47
42
|
if (axis !== 'horiz' && !sel.empty) {
|
|
48
43
|
return false;
|
|
49
44
|
}
|
|
50
|
-
|
|
51
45
|
const end = view ? atEndOfCell(view, axis, dir) : null;
|
|
52
|
-
|
|
53
46
|
if (end === null) {
|
|
54
47
|
return false;
|
|
55
48
|
}
|
|
56
|
-
|
|
57
49
|
if (axis === 'horiz') {
|
|
58
50
|
return maybeSetSelection(state, dispatch, Selection.near(state.doc.resolve(sel.head + dir), dir));
|
|
59
51
|
}
|
|
60
|
-
|
|
61
52
|
const $cell = state.doc.resolve(end);
|
|
62
53
|
const $next = nextCell($cell, axis, dir);
|
|
63
54
|
let newSel;
|
|
64
|
-
|
|
65
55
|
if ($next) {
|
|
66
56
|
newSel = Selection.near($next, 1);
|
|
67
57
|
} else if (dir < 0) {
|
|
@@ -69,49 +59,50 @@ function arrow(axis, dir) {
|
|
|
69
59
|
} else {
|
|
70
60
|
newSel = Selection.near(state.doc.resolve($cell.after(-1)), 1);
|
|
71
61
|
}
|
|
72
|
-
|
|
73
62
|
return maybeSetSelection(state, dispatch, newSel);
|
|
74
63
|
}
|
|
75
|
-
|
|
76
64
|
return true;
|
|
77
65
|
};
|
|
78
66
|
}
|
|
79
|
-
|
|
80
67
|
function shiftArrow(axis, dir) {
|
|
81
68
|
return (state, dispatch, view) => {
|
|
82
69
|
let sel = state.selection;
|
|
83
|
-
|
|
84
70
|
if (!(sel instanceof CellSelection)) {
|
|
71
|
+
var _maybeTableCell$paren;
|
|
85
72
|
const end = view ? atEndOfCell(view, axis, dir) : null;
|
|
86
|
-
|
|
87
73
|
if (end === null) {
|
|
88
74
|
return false;
|
|
89
75
|
}
|
|
90
|
-
|
|
76
|
+
const {
|
|
77
|
+
selection: {
|
|
78
|
+
$head,
|
|
79
|
+
$anchor
|
|
80
|
+
}
|
|
81
|
+
} = state;
|
|
82
|
+
const maybeTableCell = $head.blockRange($anchor);
|
|
83
|
+
|
|
84
|
+
// Make sure the selection is coming from the same cell
|
|
85
|
+
const sameCell = ['tableCell', 'tableHeader'].includes((maybeTableCell === null || maybeTableCell === void 0 ? void 0 : (_maybeTableCell$paren = maybeTableCell.parent) === null || _maybeTableCell$paren === void 0 ? void 0 : _maybeTableCell$paren.type.name) || '');
|
|
86
|
+
if (!sameCell) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
91
89
|
sel = new CellSelection(state.doc.resolve(end));
|
|
92
90
|
}
|
|
93
|
-
|
|
94
91
|
const $head = nextCell(sel.$headCell, axis, dir);
|
|
95
|
-
|
|
96
92
|
if (!$head) {
|
|
97
93
|
return false;
|
|
98
94
|
}
|
|
99
|
-
|
|
100
95
|
if (dispatch) {
|
|
101
96
|
return maybeSetSelection(state, dispatch, new CellSelection(sel.$anchorCell, $head));
|
|
102
97
|
}
|
|
103
|
-
|
|
104
98
|
return true;
|
|
105
99
|
};
|
|
106
100
|
}
|
|
107
|
-
|
|
108
101
|
function deleteCellSelection(state, dispatch) {
|
|
109
102
|
const sel = state.selection;
|
|
110
|
-
|
|
111
103
|
if (!(sel instanceof CellSelection)) {
|
|
112
104
|
return false;
|
|
113
105
|
}
|
|
114
|
-
|
|
115
106
|
if (dispatch) {
|
|
116
107
|
const {
|
|
117
108
|
tr
|
|
@@ -122,39 +113,32 @@ function deleteCellSelection(state, dispatch) {
|
|
|
122
113
|
tr.replace(tr.mapping.map(pos + 1), tr.mapping.map(pos + cell.nodeSize - 1), new Slice(baseContent, 0, 0));
|
|
123
114
|
}
|
|
124
115
|
});
|
|
125
|
-
|
|
126
116
|
if (tr.docChanged) {
|
|
127
117
|
dispatch(tr);
|
|
128
118
|
}
|
|
129
119
|
}
|
|
130
|
-
|
|
131
120
|
return true;
|
|
132
121
|
}
|
|
133
|
-
|
|
134
122
|
export function handleTripleClick(view, pos) {
|
|
135
123
|
const {
|
|
136
124
|
doc
|
|
137
125
|
} = view.state;
|
|
138
126
|
const $cell = cellAround(doc.resolve(pos));
|
|
139
|
-
|
|
140
127
|
if (!$cell) {
|
|
141
128
|
return false;
|
|
142
129
|
}
|
|
143
|
-
|
|
144
130
|
view.dispatch(view.state.tr.setSelection(new CellSelection($cell)));
|
|
145
131
|
return true;
|
|
146
132
|
}
|
|
147
133
|
export function handleMouseDown(view, event) {
|
|
148
|
-
const startEvent = event;
|
|
149
|
-
|
|
134
|
+
const startEvent = event;
|
|
135
|
+
// Prevent right clicks from making a cell selection https://product-fabric.atlassian.net/browse/ED-12527
|
|
150
136
|
if (startEvent.ctrlKey || startEvent.metaKey || startEvent.button === 2 // right mouse click
|
|
151
137
|
) {
|
|
152
138
|
return false;
|
|
153
139
|
}
|
|
154
|
-
|
|
155
140
|
const startDOMCell = domInCell(view, startEvent.target);
|
|
156
141
|
const $anchor = cellAround(view.state.selection.$anchor);
|
|
157
|
-
|
|
158
142
|
if (startEvent.shiftKey && view.state.selection instanceof CellSelection) {
|
|
159
143
|
// Adding to an existing cell selection
|
|
160
144
|
setCellSelection(view.state.selection.$anchorCell, startEvent);
|
|
@@ -167,14 +151,13 @@ export function handleMouseDown(view, event) {
|
|
|
167
151
|
} else if (!startDOMCell) {
|
|
168
152
|
// Not in a cell, let the default behavior happen.
|
|
169
153
|
return false;
|
|
170
|
-
}
|
|
171
|
-
// the position under the mouse.
|
|
172
|
-
|
|
154
|
+
}
|
|
173
155
|
|
|
156
|
+
// Create and dispatch a cell selection between the given anchor and
|
|
157
|
+
// the position under the mouse.
|
|
174
158
|
function setCellSelection($selectionAnchor, event) {
|
|
175
159
|
let $head = cellUnderMouse(view, event);
|
|
176
160
|
const starting = tableEditingKey.getState(view.state) == null;
|
|
177
|
-
|
|
178
161
|
if (!$head || !inSameTable($selectionAnchor, $head)) {
|
|
179
162
|
if (starting) {
|
|
180
163
|
$head = $selectionAnchor;
|
|
@@ -182,109 +165,90 @@ export function handleMouseDown(view, event) {
|
|
|
182
165
|
return false;
|
|
183
166
|
}
|
|
184
167
|
}
|
|
185
|
-
|
|
186
168
|
const selection = new CellSelection($selectionAnchor, $head);
|
|
187
|
-
|
|
188
169
|
if (starting || !view.state.selection.eq(selection)) {
|
|
189
170
|
const tr = view.state.tr.setSelection(selection);
|
|
190
|
-
|
|
191
171
|
if (starting) {
|
|
192
172
|
tr.setMeta(tableEditingKey, $selectionAnchor.pos);
|
|
193
173
|
}
|
|
194
|
-
|
|
195
174
|
view.dispatch(tr);
|
|
196
175
|
}
|
|
197
|
-
}
|
|
198
|
-
|
|
176
|
+
}
|
|
199
177
|
|
|
178
|
+
// Stop listening to mouse motion events.
|
|
200
179
|
function stop() {
|
|
201
180
|
view.root.removeEventListener('mouseup', stop);
|
|
202
181
|
view.root.removeEventListener('dragstart', stop);
|
|
203
182
|
view.root.removeEventListener('mousemove', move);
|
|
204
|
-
|
|
205
183
|
if (tableEditingKey.getState(view.state) != null) {
|
|
206
184
|
view.dispatch(view.state.tr.setMeta(tableEditingKey, -1));
|
|
207
185
|
}
|
|
208
186
|
}
|
|
209
|
-
|
|
210
187
|
function move(event) {
|
|
211
188
|
const anchor = tableEditingKey.getState(view.state);
|
|
212
189
|
let $moveAnchor;
|
|
213
|
-
|
|
214
190
|
if (anchor != null) {
|
|
215
191
|
// Continuing an existing cross-cell selection
|
|
216
192
|
$moveAnchor = view.state.doc.resolve(anchor);
|
|
217
193
|
} else if (domInCell(view, event.target) !== startDOMCell) {
|
|
218
194
|
// Moving out of the initial cell -- start a new cell selection
|
|
219
195
|
$moveAnchor = cellUnderMouse(view, startEvent);
|
|
220
|
-
|
|
221
196
|
if (!$moveAnchor) {
|
|
222
197
|
stop();
|
|
223
198
|
return;
|
|
224
199
|
}
|
|
225
200
|
}
|
|
226
|
-
|
|
227
201
|
if ($moveAnchor) {
|
|
228
202
|
setCellSelection($moveAnchor, event);
|
|
229
203
|
}
|
|
230
204
|
}
|
|
231
|
-
|
|
232
205
|
view.root.addEventListener('mouseup', stop);
|
|
233
206
|
view.root.addEventListener('dragstart', stop);
|
|
234
207
|
view.root.addEventListener('mousemove', move);
|
|
235
208
|
return false;
|
|
236
|
-
}
|
|
237
|
-
// motion would move out of the cell)
|
|
209
|
+
}
|
|
238
210
|
|
|
211
|
+
// Check whether the cursor is at the end of a cell (so that further
|
|
212
|
+
// motion would move out of the cell)
|
|
239
213
|
function atEndOfCell(view, axis, dir) {
|
|
240
214
|
if (!(view.state.selection instanceof TextSelection)) {
|
|
241
215
|
return null;
|
|
242
216
|
}
|
|
243
|
-
|
|
244
217
|
const {
|
|
245
218
|
$head
|
|
246
219
|
} = view.state.selection;
|
|
247
|
-
|
|
248
220
|
for (let d = $head.depth - 1; d >= 0; d--) {
|
|
249
221
|
const parent = $head.node(d);
|
|
250
222
|
const index = dir < 0 ? $head.index(d) : $head.indexAfter(d);
|
|
251
|
-
|
|
252
223
|
if (index !== (dir < 0 ? 0 : parent.childCount)) {
|
|
253
224
|
return null;
|
|
254
225
|
}
|
|
255
|
-
|
|
256
226
|
if (parent.type.spec.tableRole === 'cell' || parent.type.spec.tableRole === 'header_cell') {
|
|
257
227
|
const cellPos = $head.before(d);
|
|
258
|
-
const dirStr =
|
|
228
|
+
const dirStr =
|
|
229
|
+
// eslint-disable-next-line no-nested-ternary
|
|
259
230
|
axis === 'vert' ? dir > 0 ? 'down' : 'up' : dir > 0 ? 'right' : 'left';
|
|
260
231
|
return view.endOfTextblock(dirStr) ? cellPos : null;
|
|
261
232
|
}
|
|
262
233
|
}
|
|
263
|
-
|
|
264
234
|
return null;
|
|
265
235
|
}
|
|
266
|
-
|
|
267
236
|
function domInCell(view, inputDom) {
|
|
268
237
|
let dom = inputDom;
|
|
269
|
-
|
|
270
238
|
for (; dom && dom !== view.dom; dom = dom.parentNode) {
|
|
271
239
|
if (dom.nodeName === 'TD' || dom.nodeName === 'TH') {
|
|
272
240
|
return dom;
|
|
273
241
|
}
|
|
274
242
|
}
|
|
275
|
-
|
|
276
243
|
return null;
|
|
277
244
|
}
|
|
278
|
-
|
|
279
245
|
function cellUnderMouse(view, event) {
|
|
280
246
|
const mousePos = view.posAtCoords({
|
|
281
247
|
left: event.clientX,
|
|
282
248
|
top: event.clientY
|
|
283
249
|
});
|
|
284
|
-
|
|
285
250
|
if (!mousePos) {
|
|
286
251
|
return null;
|
|
287
252
|
}
|
|
288
|
-
|
|
289
253
|
return cellAround(view.state.doc.resolve(mousePos.pos));
|
|
290
254
|
}
|