@atlaskit/editor-tables 2.5.8 → 2.6.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 +6 -0
- package/cell-bookmark/package.json +1 -1
- package/cell-selection/package.json +1 -1
- package/dist/cjs/utils/clone-column.js +143 -0
- package/dist/cjs/utils/clone-row.js +126 -0
- package/dist/cjs/utils.js +14 -0
- package/dist/es2019/utils/clone-column.js +133 -0
- package/dist/es2019/utils/clone-row.js +104 -0
- package/dist/es2019/utils.js +2 -0
- package/dist/esm/utils/clone-column.js +136 -0
- package/dist/esm/utils/clone-row.js +119 -0
- package/dist/esm/utils.js +2 -0
- package/dist/types/types.d.ts +5 -0
- package/dist/types/utils/clone-column.d.ts +3 -0
- package/dist/types/utils/clone-row.d.ts +3 -0
- package/dist/types/utils.d.ts +2 -0
- package/dist/types-ts4.5/types.d.ts +5 -0
- package/dist/types-ts4.5/utils/clone-column.d.ts +3 -0
- package/dist/types-ts4.5/utils/clone-row.d.ts +3 -0
- package/dist/types-ts4.5/utils.d.ts +2 -0
- package/package.json +2 -2
- package/pm-plugins/package.json +1 -1
- package/table-map/package.json +1 -1
- package/types/package.json +1 -1
- package/utils/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @atlaskit/editor-tables
|
|
2
2
|
|
|
3
|
+
## 2.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#83612](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/83612) [`25b32cbfbb7e`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/25b32cbfbb7e) - [ux] Added new clone row/column behaviour to tables drag N drop. When the user holds the alt modifier during the operation the row/column will be duplicated rather then moved.
|
|
8
|
+
|
|
3
9
|
## 2.5.8
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.cloneColumn = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _cellSelection = require("../cell-selection");
|
|
10
|
+
var _tableMap = require("../table-map");
|
|
11
|
+
var _analyseTable = require("./analyse-table");
|
|
12
|
+
var _cloneTr = require("./clone-tr");
|
|
13
|
+
var _find = require("./find");
|
|
14
|
+
var _getSelectionRangeInColumn = require("./get-selection-range-in-column");
|
|
15
|
+
var _reorderUtils = require("./reorder-utils");
|
|
16
|
+
var _tableNodeTypes = require("./table-node-types");
|
|
17
|
+
function normalizeDirection(targetDirection, options) {
|
|
18
|
+
var _options$direction;
|
|
19
|
+
var override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
20
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
21
|
+
}
|
|
22
|
+
var cloneColumn = exports.cloneColumn = function cloneColumn(state, originColumnIndex, targetColumnIndex, targetDirection) {
|
|
23
|
+
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
|
|
24
|
+
tryToFit: false,
|
|
25
|
+
direction: 0,
|
|
26
|
+
selectAfterClone: false
|
|
27
|
+
};
|
|
28
|
+
return function (tr) {
|
|
29
|
+
var _originalColumnRanges, _targetColumnRanges$i;
|
|
30
|
+
var table = (0, _find.findTable)(tr.selection);
|
|
31
|
+
if (!table) {
|
|
32
|
+
return tr;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// normalize the origin index to an array since this supports moving both a single & multiple cols in a single action.
|
|
36
|
+
if (!Array.isArray(originColumnIndex)) {
|
|
37
|
+
originColumnIndex = [originColumnIndex];
|
|
38
|
+
}
|
|
39
|
+
var tableMap = _tableMap.TableMap.get(table.node);
|
|
40
|
+
var originalColumnRanges = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(Math.min.apply(Math, (0, _toConsumableArray2.default)(originColumnIndex)), Math.max.apply(Math, (0, _toConsumableArray2.default)(originColumnIndex)))(tr);
|
|
41
|
+
var targetColumnRanges = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(targetColumnIndex)(tr);
|
|
42
|
+
var indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
|
|
43
|
+
var indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
|
|
44
|
+
var min = indexesOriginColumn[0];
|
|
45
|
+
var max = indexesOriginColumn[indexesOriginColumn.length - 1];
|
|
46
|
+
if (!options.tryToFit && indexesTargetColumn.length > 1) {
|
|
47
|
+
(0, _reorderUtils.isValidReorder)(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
|
|
48
|
+
}
|
|
49
|
+
var types = (0, _tableNodeTypes.tableNodeTypes)(state.schema);
|
|
50
|
+
var direction = normalizeDirection(targetDirection, options);
|
|
51
|
+
var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, (0, _toConsumableArray2.default)(indexesTargetColumn));
|
|
52
|
+
var _determineTableHeader = (0, _analyseTable.determineTableHeaderStateFromTableNode)(table.node, tableMap, types),
|
|
53
|
+
rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
|
|
54
|
+
columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
|
|
55
|
+
var createContentNode = createContentNodeFactory(table);
|
|
56
|
+
var newTr = (0, _cloneTr.cloneTr)(tr);
|
|
57
|
+
var origins = [];
|
|
58
|
+
for (var y = 0; y < tableMap.height; y++) {
|
|
59
|
+
origins.push([]);
|
|
60
|
+
for (var x = min; x <= max; x++) {
|
|
61
|
+
if (tableMap.isCellMergedTopLeft(y, x)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
var nodePos = tableMap.map[y * tableMap.width + x];
|
|
65
|
+
origins[y].push(createContentNode(nodePos));
|
|
66
|
+
}
|
|
67
|
+
if (columnHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
68
|
+
// This block is handling the situation where a col is moved in/out of the header position. If the header col option
|
|
69
|
+
// is enabled then;
|
|
70
|
+
// When a col is moved out, the col will be converted to a normal col and the col to the right will become the header.
|
|
71
|
+
// When a col is moved in, the old col header needs to be made normal, and the incoming col needs to be made a header.
|
|
72
|
+
// This section only manages what happens to the other col, not the one being moved.
|
|
73
|
+
var nearHeaderCol = min === 0 ? max + 1 : actualTargetIndex;
|
|
74
|
+
var _nodePos = tableMap.map[y * tableMap.width + nearHeaderCol];
|
|
75
|
+
var _createContentNode = createContentNode(_nodePos),
|
|
76
|
+
pos = _createContentNode.pos,
|
|
77
|
+
node = _createContentNode.node;
|
|
78
|
+
newTr.setNodeMarkup(pos, actualTargetIndex !== 0 || rowHeaderEnabled && y === 0 ? types.header_cell : types.cell, node.attrs);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
origins.forEach(function (row, y) {
|
|
82
|
+
if (!row.length) {
|
|
83
|
+
// If the origin has no cells to be moved then we can skip moving for this row. This can occur when a cell above rowspans
|
|
84
|
+
// into the current row.
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// The actual target index needs to be translated per row, this is because row/col spans can affect the amount of
|
|
89
|
+
// cells each row contains.
|
|
90
|
+
var rowTargetPosition = translateTargetPosition(y, actualTargetIndex, tableMap);
|
|
91
|
+
var node = table.node.nodeAt(rowTargetPosition);
|
|
92
|
+
var pos = table.start + rowTargetPosition;
|
|
93
|
+
var insertPos = direction === 'end' ? newTr.mapping.map(pos + node.nodeSize, 1) : newTr.mapping.map(pos, -1);
|
|
94
|
+
return newTr.insert(insertPos, row.map(function (_ref, x) {
|
|
95
|
+
var node = _ref.node;
|
|
96
|
+
return normalizeCellNode(node, rowHeaderEnabled && y === 0, columnHeaderEnabled && actualTargetIndex === 0 && x === 0 && direction === 'start', types);
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
99
|
+
if (options.selectAfterClone) {
|
|
100
|
+
var offset = direction === 'end' ? 1 : 0;
|
|
101
|
+
var selectionRange = (0, _getSelectionRangeInColumn.getSelectionRangeInColumn)(actualTargetIndex + offset, actualTargetIndex + offset + indexesOriginColumn.length - 1)(newTr);
|
|
102
|
+
if (selectionRange) {
|
|
103
|
+
newTr.setSelection(new _cellSelection.CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return newTr;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
function normalizeCellNode(cellNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
110
|
+
var newTargetType = rowHeaderEnabled || columnHeaderEnabled ? types.header_cell : types.cell;
|
|
111
|
+
return cellNode.type !== newTargetType ? newTargetType.create(cellNode.attrs, cellNode.content, cellNode.marks) : cellNode;
|
|
112
|
+
}
|
|
113
|
+
function createContentNodeFactory(table) {
|
|
114
|
+
return function (nodePos) {
|
|
115
|
+
var node = table.node.nodeAt(nodePos);
|
|
116
|
+
var pos = nodePos + table.start;
|
|
117
|
+
return {
|
|
118
|
+
pos: pos,
|
|
119
|
+
start: pos + 1,
|
|
120
|
+
node: node,
|
|
121
|
+
depth: table.depth + 2
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function translateTargetPosition(row, startIndex, tableMap) {
|
|
126
|
+
if (tableMap.isCellMergedTopLeft(row, startIndex)) {
|
|
127
|
+
// find the closet unmerged position to the left of the target. We scan left first because merged cells will actually
|
|
128
|
+
// reduce the amount of cells in a row.
|
|
129
|
+
for (var x = startIndex - 1; x >= 0; x--) {
|
|
130
|
+
if (!tableMap.isCellMergedTopLeft(row, x)) {
|
|
131
|
+
return tableMap.map[row * tableMap.width + x];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If no index found then we need to look to the right, this can occur when the first cell in the row is merged.
|
|
136
|
+
for (var _x = startIndex + 1; _x < tableMap.width; _x++) {
|
|
137
|
+
if (!tableMap.isCellMergedTopLeft(row, _x)) {
|
|
138
|
+
return tableMap.map[row * tableMap.width + _x];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return tableMap.map[row * tableMap.width + startIndex];
|
|
143
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.cloneRow = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
|
+
var _cellSelection = require("../cell-selection");
|
|
11
|
+
var _tableMap = require("../table-map");
|
|
12
|
+
var _analyseTable = require("./analyse-table");
|
|
13
|
+
var _cloneTr = require("./clone-tr");
|
|
14
|
+
var _find = require("./find");
|
|
15
|
+
var _getSelectionRangeInRow = require("./get-selection-range-in-row");
|
|
16
|
+
var _reorderUtils = require("./reorder-utils");
|
|
17
|
+
var _tableNodeTypes = require("./table-node-types");
|
|
18
|
+
function normalizeDirection(targetDirection, options) {
|
|
19
|
+
var _options$direction;
|
|
20
|
+
var override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
21
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
22
|
+
}
|
|
23
|
+
var cloneRow = exports.cloneRow = function cloneRow(state, originRowIndex, targetRowIndex, targetDirection) {
|
|
24
|
+
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
|
|
25
|
+
tryToFit: false,
|
|
26
|
+
direction: 0,
|
|
27
|
+
selectAfterClone: false
|
|
28
|
+
};
|
|
29
|
+
return function (tr) {
|
|
30
|
+
var table = (0, _find.findTable)(tr.selection);
|
|
31
|
+
if (!table) {
|
|
32
|
+
return tr;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
|
|
36
|
+
if (!Array.isArray(originRowIndex)) {
|
|
37
|
+
originRowIndex = [originRowIndex];
|
|
38
|
+
}
|
|
39
|
+
var tableMap = _tableMap.TableMap.get(table.node);
|
|
40
|
+
var _originRowIndex$reduc = originRowIndex.reduce(function (_ref, cur) {
|
|
41
|
+
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
|
|
42
|
+
min = _ref2[0],
|
|
43
|
+
max = _ref2[1];
|
|
44
|
+
return [Math.min(min, cur), Math.max(max, cur)];
|
|
45
|
+
}, [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]),
|
|
46
|
+
_originRowIndex$reduc2 = (0, _slicedToArray2.default)(_originRowIndex$reduc, 2),
|
|
47
|
+
originMin = _originRowIndex$reduc2[0],
|
|
48
|
+
originMax = _originRowIndex$reduc2[1];
|
|
49
|
+
var originalRowRanges = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(originMin, originMax)(tr);
|
|
50
|
+
var targetRowRanges = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(targetRowIndex)(tr);
|
|
51
|
+
var indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
|
|
52
|
+
var indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
|
|
53
|
+
if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER) {
|
|
54
|
+
return tr;
|
|
55
|
+
}
|
|
56
|
+
if (!options.tryToFit && indexesTargetRow.length > 1) {
|
|
57
|
+
(0, _reorderUtils.isValidReorder)(originMin, targetRowIndex, indexesTargetRow, 'row');
|
|
58
|
+
}
|
|
59
|
+
var types = (0, _tableNodeTypes.tableNodeTypes)(state.schema);
|
|
60
|
+
var direction = normalizeDirection(targetDirection, options);
|
|
61
|
+
var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, (0, _toConsumableArray2.default)(indexesTargetRow));
|
|
62
|
+
var originPositions = indexesOriginRow.map(function (index) {
|
|
63
|
+
return tableMap.positionAt(index, 0, table.node) + table.pos;
|
|
64
|
+
});
|
|
65
|
+
var originNodes = originPositions.reduce(function (acc, pos) {
|
|
66
|
+
var node = tr.doc.nodeAt(tr.mapping.map(pos));
|
|
67
|
+
if (node) {
|
|
68
|
+
return [].concat((0, _toConsumableArray2.default)(acc), [{
|
|
69
|
+
pos: pos,
|
|
70
|
+
node: node
|
|
71
|
+
}]);
|
|
72
|
+
}
|
|
73
|
+
return acc;
|
|
74
|
+
}, []);
|
|
75
|
+
var targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
|
|
76
|
+
var targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
|
|
77
|
+
if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
|
|
78
|
+
var newTr = (0, _cloneTr.cloneTr)(tr);
|
|
79
|
+
var _determineTableHeader = (0, _analyseTable.determineTableHeaderStateFromTableNode)(table.node, tableMap, types),
|
|
80
|
+
rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
|
|
81
|
+
columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
|
|
82
|
+
if (rowHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
83
|
+
// This block is handling the situation where a row is moved in/out of the header position. If the header row option
|
|
84
|
+
// is enabled then;
|
|
85
|
+
// When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
|
|
86
|
+
// When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
|
|
87
|
+
// This section only manages what happens to the other row, no the one being moved.
|
|
88
|
+
var nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
|
|
89
|
+
var nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
|
|
90
|
+
if (nearHeaderNode) {
|
|
91
|
+
nearHeaderNode.forEach(function (node, offset, index) {
|
|
92
|
+
var start = newTr.mapping.map(nearHeaderPos + 1 + offset);
|
|
93
|
+
newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
var insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
|
|
98
|
+
newTr.insert(insertPos, originNodes.map(function (_ref3, index) {
|
|
99
|
+
var node = _ref3.node;
|
|
100
|
+
return normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0 && direction === 'start', columnHeaderEnabled, types);
|
|
101
|
+
}));
|
|
102
|
+
if (options.selectAfterClone) {
|
|
103
|
+
var offset = direction === 'end' ? 1 : 0;
|
|
104
|
+
var selectionRange = (0, _getSelectionRangeInRow.getSelectionRangeInRow)(actualTargetIndex + offset, actualTargetIndex + offset + originNodes.length - 1)(newTr);
|
|
105
|
+
if (selectionRange) {
|
|
106
|
+
newTr.setSelection(new _cellSelection.CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return newTr;
|
|
110
|
+
}
|
|
111
|
+
return tr;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* This ensures the row node cell type correctly reflect what they should be.
|
|
117
|
+
* @returns A copy of the rowNode
|
|
118
|
+
*/
|
|
119
|
+
function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
120
|
+
var content = [];
|
|
121
|
+
rowNode.forEach(function (node, offset, index) {
|
|
122
|
+
var newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
|
|
123
|
+
content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
|
|
124
|
+
});
|
|
125
|
+
return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
|
|
126
|
+
}
|
package/dist/cjs/utils.js
CHANGED
|
@@ -51,6 +51,18 @@ Object.defineProperty(exports, "cellWrapping", {
|
|
|
51
51
|
return _splitCellWithType.cellWrapping;
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
+
Object.defineProperty(exports, "cloneColumn", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function get() {
|
|
57
|
+
return _cloneColumn.cloneColumn;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "cloneRow", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function get() {
|
|
63
|
+
return _cloneRow.cloneRow;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
54
66
|
Object.defineProperty(exports, "cloneTr", {
|
|
55
67
|
enumerable: true,
|
|
56
68
|
get: function get() {
|
|
@@ -430,6 +442,8 @@ var _isSelected = require("./utils/is-selected");
|
|
|
430
442
|
var _isSelectionType = require("./utils/is-selection-type");
|
|
431
443
|
var _moveColumn = require("./utils/move-column");
|
|
432
444
|
var _moveRow = require("./utils/move-row");
|
|
445
|
+
var _cloneColumn = require("./utils/clone-column");
|
|
446
|
+
var _cloneRow = require("./utils/clone-row");
|
|
433
447
|
var _normalizeSelection = require("./utils/normalize-selection");
|
|
434
448
|
var _removeColumn = require("./utils/remove-column");
|
|
435
449
|
var _removeRow = require("./utils/remove-row");
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { CellSelection } from '../cell-selection';
|
|
2
|
+
import { TableMap } from '../table-map';
|
|
3
|
+
import { determineTableHeaderStateFromTableNode } from './analyse-table';
|
|
4
|
+
import { cloneTr } from './clone-tr';
|
|
5
|
+
import { findTable } from './find';
|
|
6
|
+
import { getSelectionRangeInColumn } from './get-selection-range-in-column';
|
|
7
|
+
import { isValidReorder } from './reorder-utils';
|
|
8
|
+
import { tableNodeTypes } from './table-node-types';
|
|
9
|
+
function normalizeDirection(targetDirection, options) {
|
|
10
|
+
var _options$direction;
|
|
11
|
+
const override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
12
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
13
|
+
}
|
|
14
|
+
export const cloneColumn = (state, originColumnIndex, targetColumnIndex, targetDirection, options = {
|
|
15
|
+
tryToFit: false,
|
|
16
|
+
direction: 0,
|
|
17
|
+
selectAfterClone: false
|
|
18
|
+
}) => tr => {
|
|
19
|
+
var _originalColumnRanges, _targetColumnRanges$i;
|
|
20
|
+
const table = findTable(tr.selection);
|
|
21
|
+
if (!table) {
|
|
22
|
+
return tr;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// normalize the origin index to an array since this supports moving both a single & multiple cols in a single action.
|
|
26
|
+
if (!Array.isArray(originColumnIndex)) {
|
|
27
|
+
originColumnIndex = [originColumnIndex];
|
|
28
|
+
}
|
|
29
|
+
const tableMap = TableMap.get(table.node);
|
|
30
|
+
const originalColumnRanges = getSelectionRangeInColumn(Math.min(...originColumnIndex), Math.max(...originColumnIndex))(tr);
|
|
31
|
+
const targetColumnRanges = getSelectionRangeInColumn(targetColumnIndex)(tr);
|
|
32
|
+
const indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
|
|
33
|
+
const indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
|
|
34
|
+
const min = indexesOriginColumn[0];
|
|
35
|
+
const max = indexesOriginColumn[indexesOriginColumn.length - 1];
|
|
36
|
+
if (!options.tryToFit && indexesTargetColumn.length > 1) {
|
|
37
|
+
isValidReorder(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
|
|
38
|
+
}
|
|
39
|
+
const types = tableNodeTypes(state.schema);
|
|
40
|
+
const direction = normalizeDirection(targetDirection, options);
|
|
41
|
+
const actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'](...indexesTargetColumn);
|
|
42
|
+
const {
|
|
43
|
+
rowHeaderEnabled,
|
|
44
|
+
columnHeaderEnabled
|
|
45
|
+
} = determineTableHeaderStateFromTableNode(table.node, tableMap, types);
|
|
46
|
+
const createContentNode = createContentNodeFactory(table);
|
|
47
|
+
const newTr = cloneTr(tr);
|
|
48
|
+
const origins = [];
|
|
49
|
+
for (let y = 0; y < tableMap.height; y++) {
|
|
50
|
+
origins.push([]);
|
|
51
|
+
for (let x = min; x <= max; x++) {
|
|
52
|
+
if (tableMap.isCellMergedTopLeft(y, x)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const nodePos = tableMap.map[y * tableMap.width + x];
|
|
56
|
+
origins[y].push(createContentNode(nodePos));
|
|
57
|
+
}
|
|
58
|
+
if (columnHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
59
|
+
// This block is handling the situation where a col is moved in/out of the header position. If the header col option
|
|
60
|
+
// is enabled then;
|
|
61
|
+
// When a col is moved out, the col will be converted to a normal col and the col to the right will become the header.
|
|
62
|
+
// When a col is moved in, the old col header needs to be made normal, and the incoming col needs to be made a header.
|
|
63
|
+
// This section only manages what happens to the other col, not the one being moved.
|
|
64
|
+
const nearHeaderCol = min === 0 ? max + 1 : actualTargetIndex;
|
|
65
|
+
const nodePos = tableMap.map[y * tableMap.width + nearHeaderCol];
|
|
66
|
+
const {
|
|
67
|
+
pos,
|
|
68
|
+
node
|
|
69
|
+
} = createContentNode(nodePos);
|
|
70
|
+
newTr.setNodeMarkup(pos, actualTargetIndex !== 0 || rowHeaderEnabled && y === 0 ? types.header_cell : types.cell, node.attrs);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
origins.forEach((row, y) => {
|
|
74
|
+
if (!row.length) {
|
|
75
|
+
// If the origin has no cells to be moved then we can skip moving for this row. This can occur when a cell above rowspans
|
|
76
|
+
// into the current row.
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The actual target index needs to be translated per row, this is because row/col spans can affect the amount of
|
|
81
|
+
// cells each row contains.
|
|
82
|
+
const rowTargetPosition = translateTargetPosition(y, actualTargetIndex, tableMap);
|
|
83
|
+
const node = table.node.nodeAt(rowTargetPosition);
|
|
84
|
+
const pos = table.start + rowTargetPosition;
|
|
85
|
+
const insertPos = direction === 'end' ? newTr.mapping.map(pos + node.nodeSize, 1) : newTr.mapping.map(pos, -1);
|
|
86
|
+
return newTr.insert(insertPos, row.map(({
|
|
87
|
+
node
|
|
88
|
+
}, x) => normalizeCellNode(node, rowHeaderEnabled && y === 0, columnHeaderEnabled && actualTargetIndex === 0 && x === 0 && direction === 'start', types)));
|
|
89
|
+
});
|
|
90
|
+
if (options.selectAfterClone) {
|
|
91
|
+
const offset = direction === 'end' ? 1 : 0;
|
|
92
|
+
const selectionRange = getSelectionRangeInColumn(actualTargetIndex + offset, actualTargetIndex + offset + indexesOriginColumn.length - 1)(newTr);
|
|
93
|
+
if (selectionRange) {
|
|
94
|
+
newTr.setSelection(new CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return newTr;
|
|
98
|
+
};
|
|
99
|
+
function normalizeCellNode(cellNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
100
|
+
const newTargetType = rowHeaderEnabled || columnHeaderEnabled ? types.header_cell : types.cell;
|
|
101
|
+
return cellNode.type !== newTargetType ? newTargetType.create(cellNode.attrs, cellNode.content, cellNode.marks) : cellNode;
|
|
102
|
+
}
|
|
103
|
+
function createContentNodeFactory(table) {
|
|
104
|
+
return nodePos => {
|
|
105
|
+
const node = table.node.nodeAt(nodePos);
|
|
106
|
+
const pos = nodePos + table.start;
|
|
107
|
+
return {
|
|
108
|
+
pos,
|
|
109
|
+
start: pos + 1,
|
|
110
|
+
node,
|
|
111
|
+
depth: table.depth + 2
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function translateTargetPosition(row, startIndex, tableMap) {
|
|
116
|
+
if (tableMap.isCellMergedTopLeft(row, startIndex)) {
|
|
117
|
+
// find the closet unmerged position to the left of the target. We scan left first because merged cells will actually
|
|
118
|
+
// reduce the amount of cells in a row.
|
|
119
|
+
for (let x = startIndex - 1; x >= 0; x--) {
|
|
120
|
+
if (!tableMap.isCellMergedTopLeft(row, x)) {
|
|
121
|
+
return tableMap.map[row * tableMap.width + x];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// If no index found then we need to look to the right, this can occur when the first cell in the row is merged.
|
|
126
|
+
for (let x = startIndex + 1; x < tableMap.width; x++) {
|
|
127
|
+
if (!tableMap.isCellMergedTopLeft(row, x)) {
|
|
128
|
+
return tableMap.map[row * tableMap.width + x];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return tableMap.map[row * tableMap.width + startIndex];
|
|
133
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { CellSelection } from '../cell-selection';
|
|
2
|
+
import { TableMap } from '../table-map';
|
|
3
|
+
import { determineTableHeaderStateFromTableNode } from './analyse-table';
|
|
4
|
+
import { cloneTr } from './clone-tr';
|
|
5
|
+
import { findTable } from './find';
|
|
6
|
+
import { getSelectionRangeInRow } from './get-selection-range-in-row';
|
|
7
|
+
import { isValidReorder } from './reorder-utils';
|
|
8
|
+
import { tableNodeTypes } from './table-node-types';
|
|
9
|
+
function normalizeDirection(targetDirection, options) {
|
|
10
|
+
var _options$direction;
|
|
11
|
+
const override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
12
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
13
|
+
}
|
|
14
|
+
export const cloneRow = (state, originRowIndex, targetRowIndex, targetDirection, options = {
|
|
15
|
+
tryToFit: false,
|
|
16
|
+
direction: 0,
|
|
17
|
+
selectAfterClone: false
|
|
18
|
+
}) => tr => {
|
|
19
|
+
const table = findTable(tr.selection);
|
|
20
|
+
if (!table) {
|
|
21
|
+
return tr;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
|
|
25
|
+
if (!Array.isArray(originRowIndex)) {
|
|
26
|
+
originRowIndex = [originRowIndex];
|
|
27
|
+
}
|
|
28
|
+
const tableMap = TableMap.get(table.node);
|
|
29
|
+
const [originMin, originMax] = originRowIndex.reduce(([min, max], cur) => [Math.min(min, cur), Math.max(max, cur)], [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]);
|
|
30
|
+
const originalRowRanges = getSelectionRangeInRow(originMin, originMax)(tr);
|
|
31
|
+
const targetRowRanges = getSelectionRangeInRow(targetRowIndex)(tr);
|
|
32
|
+
const indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
|
|
33
|
+
const indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
|
|
34
|
+
if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER) {
|
|
35
|
+
return tr;
|
|
36
|
+
}
|
|
37
|
+
if (!options.tryToFit && indexesTargetRow.length > 1) {
|
|
38
|
+
isValidReorder(originMin, targetRowIndex, indexesTargetRow, 'row');
|
|
39
|
+
}
|
|
40
|
+
const types = tableNodeTypes(state.schema);
|
|
41
|
+
const direction = normalizeDirection(targetDirection, options);
|
|
42
|
+
const actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'](...indexesTargetRow);
|
|
43
|
+
const originPositions = indexesOriginRow.map(index => tableMap.positionAt(index, 0, table.node) + table.pos);
|
|
44
|
+
const originNodes = originPositions.reduce((acc, pos) => {
|
|
45
|
+
const node = tr.doc.nodeAt(tr.mapping.map(pos));
|
|
46
|
+
if (node) {
|
|
47
|
+
return [...acc, {
|
|
48
|
+
pos,
|
|
49
|
+
node
|
|
50
|
+
}];
|
|
51
|
+
}
|
|
52
|
+
return acc;
|
|
53
|
+
}, []);
|
|
54
|
+
const targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
|
|
55
|
+
const targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
|
|
56
|
+
if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
|
|
57
|
+
const newTr = cloneTr(tr);
|
|
58
|
+
const {
|
|
59
|
+
rowHeaderEnabled,
|
|
60
|
+
columnHeaderEnabled
|
|
61
|
+
} = determineTableHeaderStateFromTableNode(table.node, tableMap, types);
|
|
62
|
+
if (rowHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
63
|
+
// This block is handling the situation where a row is moved in/out of the header position. If the header row option
|
|
64
|
+
// is enabled then;
|
|
65
|
+
// When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
|
|
66
|
+
// When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
|
|
67
|
+
// This section only manages what happens to the other row, no the one being moved.
|
|
68
|
+
const nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
|
|
69
|
+
const nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
|
|
70
|
+
if (nearHeaderNode) {
|
|
71
|
+
nearHeaderNode.forEach((node, offset, index) => {
|
|
72
|
+
const start = newTr.mapping.map(nearHeaderPos + 1 + offset);
|
|
73
|
+
newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
|
|
78
|
+
newTr.insert(insertPos, originNodes.map(({
|
|
79
|
+
node
|
|
80
|
+
}, index) => normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0 && direction === 'start', columnHeaderEnabled, types)));
|
|
81
|
+
if (options.selectAfterClone) {
|
|
82
|
+
const offset = direction === 'end' ? 1 : 0;
|
|
83
|
+
const selectionRange = getSelectionRangeInRow(actualTargetIndex + offset, actualTargetIndex + offset + originNodes.length - 1)(newTr);
|
|
84
|
+
if (selectionRange) {
|
|
85
|
+
newTr.setSelection(new CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return newTr;
|
|
89
|
+
}
|
|
90
|
+
return tr;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* This ensures the row node cell type correctly reflect what they should be.
|
|
95
|
+
* @returns A copy of the rowNode
|
|
96
|
+
*/
|
|
97
|
+
function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
98
|
+
let content = [];
|
|
99
|
+
rowNode.forEach((node, offset, index) => {
|
|
100
|
+
const newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
|
|
101
|
+
content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
|
|
102
|
+
});
|
|
103
|
+
return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
|
|
104
|
+
}
|
package/dist/es2019/utils.js
CHANGED
|
@@ -23,6 +23,8 @@ export { isRectSelected, isColumnSelected, isRowSelected, isTableSelected } from
|
|
|
23
23
|
export { isSelectionType } from './utils/is-selection-type';
|
|
24
24
|
export { moveColumn } from './utils/move-column';
|
|
25
25
|
export { moveRow } from './utils/move-row';
|
|
26
|
+
export { cloneColumn } from './utils/clone-column';
|
|
27
|
+
export { cloneRow } from './utils/clone-row';
|
|
26
28
|
export { normalizeSelection } from './utils/normalize-selection';
|
|
27
29
|
export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos } from './utils/remove-column';
|
|
28
30
|
export { removeRowAt, removeSelectedRows, removeRowClosestToPos } from './utils/remove-row';
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import { CellSelection } from '../cell-selection';
|
|
3
|
+
import { TableMap } from '../table-map';
|
|
4
|
+
import { determineTableHeaderStateFromTableNode } from './analyse-table';
|
|
5
|
+
import { cloneTr } from './clone-tr';
|
|
6
|
+
import { findTable } from './find';
|
|
7
|
+
import { getSelectionRangeInColumn } from './get-selection-range-in-column';
|
|
8
|
+
import { isValidReorder } from './reorder-utils';
|
|
9
|
+
import { tableNodeTypes } from './table-node-types';
|
|
10
|
+
function normalizeDirection(targetDirection, options) {
|
|
11
|
+
var _options$direction;
|
|
12
|
+
var override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
13
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
14
|
+
}
|
|
15
|
+
export var cloneColumn = function cloneColumn(state, originColumnIndex, targetColumnIndex, targetDirection) {
|
|
16
|
+
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
|
|
17
|
+
tryToFit: false,
|
|
18
|
+
direction: 0,
|
|
19
|
+
selectAfterClone: false
|
|
20
|
+
};
|
|
21
|
+
return function (tr) {
|
|
22
|
+
var _originalColumnRanges, _targetColumnRanges$i;
|
|
23
|
+
var table = findTable(tr.selection);
|
|
24
|
+
if (!table) {
|
|
25
|
+
return tr;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// normalize the origin index to an array since this supports moving both a single & multiple cols in a single action.
|
|
29
|
+
if (!Array.isArray(originColumnIndex)) {
|
|
30
|
+
originColumnIndex = [originColumnIndex];
|
|
31
|
+
}
|
|
32
|
+
var tableMap = TableMap.get(table.node);
|
|
33
|
+
var originalColumnRanges = getSelectionRangeInColumn(Math.min.apply(Math, _toConsumableArray(originColumnIndex)), Math.max.apply(Math, _toConsumableArray(originColumnIndex)))(tr);
|
|
34
|
+
var targetColumnRanges = getSelectionRangeInColumn(targetColumnIndex)(tr);
|
|
35
|
+
var indexesOriginColumn = (_originalColumnRanges = originalColumnRanges === null || originalColumnRanges === void 0 ? void 0 : originalColumnRanges.indexes) !== null && _originalColumnRanges !== void 0 ? _originalColumnRanges : [];
|
|
36
|
+
var indexesTargetColumn = (_targetColumnRanges$i = targetColumnRanges === null || targetColumnRanges === void 0 ? void 0 : targetColumnRanges.indexes) !== null && _targetColumnRanges$i !== void 0 ? _targetColumnRanges$i : [];
|
|
37
|
+
var min = indexesOriginColumn[0];
|
|
38
|
+
var max = indexesOriginColumn[indexesOriginColumn.length - 1];
|
|
39
|
+
if (!options.tryToFit && indexesTargetColumn.length > 1) {
|
|
40
|
+
isValidReorder(originColumnIndex[0], targetColumnIndex, indexesTargetColumn, 'column');
|
|
41
|
+
}
|
|
42
|
+
var types = tableNodeTypes(state.schema);
|
|
43
|
+
var direction = normalizeDirection(targetDirection, options);
|
|
44
|
+
var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, _toConsumableArray(indexesTargetColumn));
|
|
45
|
+
var _determineTableHeader = determineTableHeaderStateFromTableNode(table.node, tableMap, types),
|
|
46
|
+
rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
|
|
47
|
+
columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
|
|
48
|
+
var createContentNode = createContentNodeFactory(table);
|
|
49
|
+
var newTr = cloneTr(tr);
|
|
50
|
+
var origins = [];
|
|
51
|
+
for (var y = 0; y < tableMap.height; y++) {
|
|
52
|
+
origins.push([]);
|
|
53
|
+
for (var x = min; x <= max; x++) {
|
|
54
|
+
if (tableMap.isCellMergedTopLeft(y, x)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
var nodePos = tableMap.map[y * tableMap.width + x];
|
|
58
|
+
origins[y].push(createContentNode(nodePos));
|
|
59
|
+
}
|
|
60
|
+
if (columnHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
61
|
+
// This block is handling the situation where a col is moved in/out of the header position. If the header col option
|
|
62
|
+
// is enabled then;
|
|
63
|
+
// When a col is moved out, the col will be converted to a normal col and the col to the right will become the header.
|
|
64
|
+
// When a col is moved in, the old col header needs to be made normal, and the incoming col needs to be made a header.
|
|
65
|
+
// This section only manages what happens to the other col, not the one being moved.
|
|
66
|
+
var nearHeaderCol = min === 0 ? max + 1 : actualTargetIndex;
|
|
67
|
+
var _nodePos = tableMap.map[y * tableMap.width + nearHeaderCol];
|
|
68
|
+
var _createContentNode = createContentNode(_nodePos),
|
|
69
|
+
pos = _createContentNode.pos,
|
|
70
|
+
node = _createContentNode.node;
|
|
71
|
+
newTr.setNodeMarkup(pos, actualTargetIndex !== 0 || rowHeaderEnabled && y === 0 ? types.header_cell : types.cell, node.attrs);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
origins.forEach(function (row, y) {
|
|
75
|
+
if (!row.length) {
|
|
76
|
+
// If the origin has no cells to be moved then we can skip moving for this row. This can occur when a cell above rowspans
|
|
77
|
+
// into the current row.
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The actual target index needs to be translated per row, this is because row/col spans can affect the amount of
|
|
82
|
+
// cells each row contains.
|
|
83
|
+
var rowTargetPosition = translateTargetPosition(y, actualTargetIndex, tableMap);
|
|
84
|
+
var node = table.node.nodeAt(rowTargetPosition);
|
|
85
|
+
var pos = table.start + rowTargetPosition;
|
|
86
|
+
var insertPos = direction === 'end' ? newTr.mapping.map(pos + node.nodeSize, 1) : newTr.mapping.map(pos, -1);
|
|
87
|
+
return newTr.insert(insertPos, row.map(function (_ref, x) {
|
|
88
|
+
var node = _ref.node;
|
|
89
|
+
return normalizeCellNode(node, rowHeaderEnabled && y === 0, columnHeaderEnabled && actualTargetIndex === 0 && x === 0 && direction === 'start', types);
|
|
90
|
+
}));
|
|
91
|
+
});
|
|
92
|
+
if (options.selectAfterClone) {
|
|
93
|
+
var offset = direction === 'end' ? 1 : 0;
|
|
94
|
+
var selectionRange = getSelectionRangeInColumn(actualTargetIndex + offset, actualTargetIndex + offset + indexesOriginColumn.length - 1)(newTr);
|
|
95
|
+
if (selectionRange) {
|
|
96
|
+
newTr.setSelection(new CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return newTr;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
function normalizeCellNode(cellNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
103
|
+
var newTargetType = rowHeaderEnabled || columnHeaderEnabled ? types.header_cell : types.cell;
|
|
104
|
+
return cellNode.type !== newTargetType ? newTargetType.create(cellNode.attrs, cellNode.content, cellNode.marks) : cellNode;
|
|
105
|
+
}
|
|
106
|
+
function createContentNodeFactory(table) {
|
|
107
|
+
return function (nodePos) {
|
|
108
|
+
var node = table.node.nodeAt(nodePos);
|
|
109
|
+
var pos = nodePos + table.start;
|
|
110
|
+
return {
|
|
111
|
+
pos: pos,
|
|
112
|
+
start: pos + 1,
|
|
113
|
+
node: node,
|
|
114
|
+
depth: table.depth + 2
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function translateTargetPosition(row, startIndex, tableMap) {
|
|
119
|
+
if (tableMap.isCellMergedTopLeft(row, startIndex)) {
|
|
120
|
+
// find the closet unmerged position to the left of the target. We scan left first because merged cells will actually
|
|
121
|
+
// reduce the amount of cells in a row.
|
|
122
|
+
for (var x = startIndex - 1; x >= 0; x--) {
|
|
123
|
+
if (!tableMap.isCellMergedTopLeft(row, x)) {
|
|
124
|
+
return tableMap.map[row * tableMap.width + x];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If no index found then we need to look to the right, this can occur when the first cell in the row is merged.
|
|
129
|
+
for (var _x = startIndex + 1; _x < tableMap.width; _x++) {
|
|
130
|
+
if (!tableMap.isCellMergedTopLeft(row, _x)) {
|
|
131
|
+
return tableMap.map[row * tableMap.width + _x];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return tableMap.map[row * tableMap.width + startIndex];
|
|
136
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
+
import { CellSelection } from '../cell-selection';
|
|
4
|
+
import { TableMap } from '../table-map';
|
|
5
|
+
import { determineTableHeaderStateFromTableNode } from './analyse-table';
|
|
6
|
+
import { cloneTr } from './clone-tr';
|
|
7
|
+
import { findTable } from './find';
|
|
8
|
+
import { getSelectionRangeInRow } from './get-selection-range-in-row';
|
|
9
|
+
import { isValidReorder } from './reorder-utils';
|
|
10
|
+
import { tableNodeTypes } from './table-node-types';
|
|
11
|
+
function normalizeDirection(targetDirection, options) {
|
|
12
|
+
var _options$direction;
|
|
13
|
+
var override = ((_options$direction = options === null || options === void 0 ? void 0 : options.direction) !== null && _options$direction !== void 0 ? _options$direction : 0) < 0 ? 'start' : 'end';
|
|
14
|
+
return options !== null && options !== void 0 && options.tryToFit && !!(options !== null && options !== void 0 && options.direction) ? override : targetDirection;
|
|
15
|
+
}
|
|
16
|
+
export var cloneRow = function cloneRow(state, originRowIndex, targetRowIndex, targetDirection) {
|
|
17
|
+
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {
|
|
18
|
+
tryToFit: false,
|
|
19
|
+
direction: 0,
|
|
20
|
+
selectAfterClone: false
|
|
21
|
+
};
|
|
22
|
+
return function (tr) {
|
|
23
|
+
var table = findTable(tr.selection);
|
|
24
|
+
if (!table) {
|
|
25
|
+
return tr;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// normalize the origin index to an array since move row support moving both a single & multiple rows in a single action.
|
|
29
|
+
if (!Array.isArray(originRowIndex)) {
|
|
30
|
+
originRowIndex = [originRowIndex];
|
|
31
|
+
}
|
|
32
|
+
var tableMap = TableMap.get(table.node);
|
|
33
|
+
var _originRowIndex$reduc = originRowIndex.reduce(function (_ref, cur) {
|
|
34
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
35
|
+
min = _ref2[0],
|
|
36
|
+
max = _ref2[1];
|
|
37
|
+
return [Math.min(min, cur), Math.max(max, cur)];
|
|
38
|
+
}, [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]),
|
|
39
|
+
_originRowIndex$reduc2 = _slicedToArray(_originRowIndex$reduc, 2),
|
|
40
|
+
originMin = _originRowIndex$reduc2[0],
|
|
41
|
+
originMax = _originRowIndex$reduc2[1];
|
|
42
|
+
var originalRowRanges = getSelectionRangeInRow(originMin, originMax)(tr);
|
|
43
|
+
var targetRowRanges = getSelectionRangeInRow(targetRowIndex)(tr);
|
|
44
|
+
var indexesOriginRow = (originalRowRanges === null || originalRowRanges === void 0 ? void 0 : originalRowRanges.indexes) || [];
|
|
45
|
+
var indexesTargetRow = (targetRowRanges === null || targetRowRanges === void 0 ? void 0 : targetRowRanges.indexes) || [];
|
|
46
|
+
if (originMin < 0 || originMin === Number.MAX_SAFE_INTEGER || originMax >= tableMap.height || originMax === Number.MIN_SAFE_INTEGER) {
|
|
47
|
+
return tr;
|
|
48
|
+
}
|
|
49
|
+
if (!options.tryToFit && indexesTargetRow.length > 1) {
|
|
50
|
+
isValidReorder(originMin, targetRowIndex, indexesTargetRow, 'row');
|
|
51
|
+
}
|
|
52
|
+
var types = tableNodeTypes(state.schema);
|
|
53
|
+
var direction = normalizeDirection(targetDirection, options);
|
|
54
|
+
var actualTargetIndex = Math[direction === 'start' ? 'min' : 'max'].apply(Math, _toConsumableArray(indexesTargetRow));
|
|
55
|
+
var originPositions = indexesOriginRow.map(function (index) {
|
|
56
|
+
return tableMap.positionAt(index, 0, table.node) + table.pos;
|
|
57
|
+
});
|
|
58
|
+
var originNodes = originPositions.reduce(function (acc, pos) {
|
|
59
|
+
var node = tr.doc.nodeAt(tr.mapping.map(pos));
|
|
60
|
+
if (node) {
|
|
61
|
+
return [].concat(_toConsumableArray(acc), [{
|
|
62
|
+
pos: pos,
|
|
63
|
+
node: node
|
|
64
|
+
}]);
|
|
65
|
+
}
|
|
66
|
+
return acc;
|
|
67
|
+
}, []);
|
|
68
|
+
var targetPos = tableMap.positionAt(actualTargetIndex, 0, table.node) + table.pos;
|
|
69
|
+
var targetNode = tr.doc.nodeAt(tr.mapping.map(targetPos));
|
|
70
|
+
if (originNodes !== null && originNodes !== void 0 && originNodes.length && targetNode) {
|
|
71
|
+
var newTr = cloneTr(tr);
|
|
72
|
+
var _determineTableHeader = determineTableHeaderStateFromTableNode(table.node, tableMap, types),
|
|
73
|
+
rowHeaderEnabled = _determineTableHeader.rowHeaderEnabled,
|
|
74
|
+
columnHeaderEnabled = _determineTableHeader.columnHeaderEnabled;
|
|
75
|
+
if (rowHeaderEnabled && actualTargetIndex === 0 && direction === 'start') {
|
|
76
|
+
// This block is handling the situation where a row is moved in/out of the header position. If the header row option
|
|
77
|
+
// is enabled then;
|
|
78
|
+
// When a row is moved out, the row will be converted to a normal row and the row below it will become the header.
|
|
79
|
+
// When a row is moved in, the old row header needs to be made normal, and the incoming row needs to be made a header.
|
|
80
|
+
// This section only manages what happens to the other row, no the one being moved.
|
|
81
|
+
var nearHeaderPos = tableMap.positionAt(originMin === 0 ? originMax + 1 : actualTargetIndex, 0, table.node) + table.pos;
|
|
82
|
+
var nearHeaderNode = newTr.doc.nodeAt(newTr.mapping.map(nearHeaderPos));
|
|
83
|
+
if (nearHeaderNode) {
|
|
84
|
+
nearHeaderNode.forEach(function (node, offset, index) {
|
|
85
|
+
var start = newTr.mapping.map(nearHeaderPos + 1 + offset);
|
|
86
|
+
newTr.setNodeMarkup(start, actualTargetIndex !== 0 || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell, node.attrs);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
var insertPos = direction === 'end' ? newTr.mapping.map(targetPos + targetNode.nodeSize, 1) : newTr.mapping.map(targetPos, -1);
|
|
91
|
+
newTr.insert(insertPos, originNodes.map(function (_ref3, index) {
|
|
92
|
+
var node = _ref3.node;
|
|
93
|
+
return normalizeRowNode(node, rowHeaderEnabled && actualTargetIndex === 0 && index === 0 && direction === 'start', columnHeaderEnabled, types);
|
|
94
|
+
}));
|
|
95
|
+
if (options.selectAfterClone) {
|
|
96
|
+
var offset = direction === 'end' ? 1 : 0;
|
|
97
|
+
var selectionRange = getSelectionRangeInRow(actualTargetIndex + offset, actualTargetIndex + offset + originNodes.length - 1)(newTr);
|
|
98
|
+
if (selectionRange) {
|
|
99
|
+
newTr.setSelection(new CellSelection(selectionRange.$anchor, selectionRange.$head));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return newTr;
|
|
103
|
+
}
|
|
104
|
+
return tr;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* This ensures the row node cell type correctly reflect what they should be.
|
|
110
|
+
* @returns A copy of the rowNode
|
|
111
|
+
*/
|
|
112
|
+
function normalizeRowNode(rowNode, rowHeaderEnabled, columnHeaderEnabled, types) {
|
|
113
|
+
var content = [];
|
|
114
|
+
rowNode.forEach(function (node, offset, index) {
|
|
115
|
+
var newTargetType = rowHeaderEnabled || columnHeaderEnabled && index === 0 ? types.header_cell : types.cell;
|
|
116
|
+
content.push(node.type !== newTargetType ? newTargetType.create(node.attrs, node.content, node.marks) : node);
|
|
117
|
+
});
|
|
118
|
+
return rowNode.type.create(rowNode.attrs, content, rowNode.marks);
|
|
119
|
+
}
|
package/dist/esm/utils.js
CHANGED
|
@@ -23,6 +23,8 @@ export { isRectSelected, isColumnSelected, isRowSelected, isTableSelected } from
|
|
|
23
23
|
export { isSelectionType } from './utils/is-selection-type';
|
|
24
24
|
export { moveColumn } from './utils/move-column';
|
|
25
25
|
export { moveRow } from './utils/move-row';
|
|
26
|
+
export { cloneColumn } from './utils/clone-column';
|
|
27
|
+
export { cloneRow } from './utils/clone-row';
|
|
26
28
|
export { normalizeSelection } from './utils/normalize-selection';
|
|
27
29
|
export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos } from './utils/remove-column';
|
|
28
30
|
export { removeRowAt, removeSelectedRows, removeRowClosestToPos } from './utils/remove-row';
|
package/dist/types/types.d.ts
CHANGED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { CloneOptions } from '../types';
|
|
3
|
+
export declare const cloneColumn: (state: EditorState, originColumnIndex: number | number[], targetColumnIndex: number, targetDirection: 'start' | 'end', options?: CloneOptions) => (tr: Transaction) => Transaction;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { CloneOptions } from '../types';
|
|
3
|
+
export declare const cloneRow: (state: EditorState, originRowIndex: number | number[], targetRowIndex: number, targetDirection: 'start' | 'end', options?: CloneOptions) => (tr: Transaction) => Transaction;
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export { isRectSelected, isColumnSelected, isRowSelected, isTableSelected, } fro
|
|
|
23
23
|
export { isSelectionType } from './utils/is-selection-type';
|
|
24
24
|
export { moveColumn } from './utils/move-column';
|
|
25
25
|
export { moveRow } from './utils/move-row';
|
|
26
|
+
export { cloneColumn } from './utils/clone-column';
|
|
27
|
+
export { cloneRow } from './utils/clone-row';
|
|
26
28
|
export { normalizeSelection } from './utils/normalize-selection';
|
|
27
29
|
export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos, } from './utils/remove-column';
|
|
28
30
|
export { removeRowAt, removeSelectedRows, removeRowClosestToPos, } from './utils/remove-row';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { CloneOptions } from '../types';
|
|
3
|
+
export declare const cloneColumn: (state: EditorState, originColumnIndex: number | number[], targetColumnIndex: number, targetDirection: 'start' | 'end', options?: CloneOptions) => (tr: Transaction) => Transaction;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import type { CloneOptions } from '../types';
|
|
3
|
+
export declare const cloneRow: (state: EditorState, originRowIndex: number | number[], targetRowIndex: number, targetDirection: 'start' | 'end', options?: CloneOptions) => (tr: Transaction) => Transaction;
|
|
@@ -23,6 +23,8 @@ export { isRectSelected, isColumnSelected, isRowSelected, isTableSelected, } fro
|
|
|
23
23
|
export { isSelectionType } from './utils/is-selection-type';
|
|
24
24
|
export { moveColumn } from './utils/move-column';
|
|
25
25
|
export { moveRow } from './utils/move-row';
|
|
26
|
+
export { cloneColumn } from './utils/clone-column';
|
|
27
|
+
export { cloneRow } from './utils/clone-row';
|
|
26
28
|
export { normalizeSelection } from './utils/normalize-selection';
|
|
27
29
|
export { removeColumnAt, removeSelectedColumns, removeColumnClosestToPos, } from './utils/remove-column';
|
|
28
30
|
export { removeRowAt, removeSelectedRows, removeRowClosestToPos, } from './utils/remove-row';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-tables",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "A package that contains common classes and utility functions for editor tables",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -71,4 +71,4 @@
|
|
|
71
71
|
"./types": "./src/types.ts",
|
|
72
72
|
"./utils": "./src/utils.ts"
|
|
73
73
|
}
|
|
74
|
-
}
|
|
74
|
+
}
|
package/pm-plugins/package.json
CHANGED
package/table-map/package.json
CHANGED
package/types/package.json
CHANGED