@atlaskit/editor-plugin-table 7.4.2 → 7.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/ui/DragHandle/index.js +34 -2
- package/dist/cjs/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
- package/dist/cjs/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
- package/dist/cjs/utils/index.js +18 -0
- package/dist/cjs/utils/merged-cells.js +95 -1
- package/dist/cjs/utils/nodes.js +4 -3
- package/dist/es2019/ui/DragHandle/index.js +36 -2
- package/dist/es2019/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
- package/dist/es2019/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
- package/dist/es2019/utils/index.js +1 -1
- package/dist/es2019/utils/merged-cells.js +91 -0
- package/dist/es2019/utils/nodes.js +4 -3
- package/dist/esm/ui/DragHandle/index.js +35 -3
- package/dist/esm/ui/TableFloatingColumnControls/ColumnControls/index.js +1 -0
- package/dist/esm/ui/TableFloatingControls/RowControls/DragControls.js +1 -0
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/merged-cells.js +94 -0
- package/dist/esm/utils/nodes.js +4 -3
- package/dist/types/ui/DragHandle/index.d.ts +2 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/merged-cells.d.ts +28 -0
- package/dist/types-ts4.5/ui/DragHandle/index.d.ts +2 -1
- package/dist/types-ts4.5/utils/index.d.ts +1 -1
- package/dist/types-ts4.5/utils/merged-cells.d.ts +28 -0
- package/package.json +1 -1
- package/src/ui/DragHandle/index.tsx +64 -9
- package/src/ui/TableFloatingColumnControls/ColumnControls/index.tsx +1 -0
- package/src/ui/TableFloatingControls/RowControls/DragControls.tsx +1 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/merged-cells.ts +104 -0
- package/src/utils/nodes.ts +10 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-table
|
|
2
2
|
|
|
3
|
+
## 7.4.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#75436](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/75436) [`bfcf32bb4fa3`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/bfcf32bb4fa3) - [ux] ED-21941 Disable resize/layout options for table, media and extension when added to MBE. Table rendering fixed for Confluence editor
|
|
8
|
+
|
|
9
|
+
## 7.4.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#72037](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/72037) [`e59f0b7a9115`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e59f0b7a9115) - [ux] add flexiable to make merged cells detection allow to detect edge merged cells
|
|
14
|
+
|
|
3
15
|
## 7.4.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -14,6 +14,8 @@ var _reactDom = _interopRequireDefault(require("react-dom"));
|
|
|
14
14
|
var _reactIntlNext = require("react-intl-next");
|
|
15
15
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
16
16
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
17
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
18
|
+
var _editorTables = require("@atlaskit/editor-tables");
|
|
17
19
|
var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
|
|
18
20
|
var _setCustomNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview");
|
|
19
21
|
var _pluginFactory = require("../../pm-plugins/drag-and-drop/plugin-factory");
|
|
@@ -40,6 +42,7 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
|
|
|
40
42
|
onMouseOver = _ref.onMouseOver,
|
|
41
43
|
onMouseOut = _ref.onMouseOut,
|
|
42
44
|
toggleDragMenu = _ref.toggleDragMenu,
|
|
45
|
+
hoveredCell = _ref.hoveredCell,
|
|
43
46
|
onClick = _ref.onClick,
|
|
44
47
|
editorView = _ref.editorView,
|
|
45
48
|
formatMessage = _ref.intl.formatMessage;
|
|
@@ -60,8 +63,37 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
|
|
|
60
63
|
var isRowHandleHovered = isRow && hoveredRows.length > 0;
|
|
61
64
|
var isColumnHandleHovered = isColumn && hoveredColumns.length > 0;
|
|
62
65
|
var hasMergedCells = (0, _react.useMemo)(function () {
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
var table = (0, _editorTables.findTable)(selection);
|
|
67
|
+
if (!table) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
var map = _editorTables.TableMap.get(table === null || table === void 0 ? void 0 : table.node);
|
|
71
|
+
if (!map.hasMergedCells() || indexes.length < 1) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
var mapByColumn = map.mapByColumn,
|
|
75
|
+
mapByRow = map.mapByRow;
|
|
76
|
+
|
|
77
|
+
// this handle when hover to first column or row which has merged cells.
|
|
78
|
+
if (hoveredCell && hoveredCell.rowIndex !== undefined && hoveredCell.colIndex !== undefined && selection instanceof _state.TextSelection) {
|
|
79
|
+
var rowIndex = hoveredCell.rowIndex,
|
|
80
|
+
colIndex = hoveredCell.colIndex;
|
|
81
|
+
var mergedPositionInRow = (0, _utils2.findDuplicatePosition)(mapByRow[rowIndex]);
|
|
82
|
+
var mergedPositionInCol = (0, _utils2.findDuplicatePosition)(mapByColumn[colIndex]);
|
|
83
|
+
var hasMergedCellsInFirstRowOrColumn = direction === 'column' ? mergedPositionInRow.includes(mapByRow[0][colIndex]) : mergedPositionInCol.includes(mapByColumn[0][rowIndex]);
|
|
84
|
+
var isHoveredOnFirstRowOrColumn = direction === 'column' ? hoveredCell.rowIndex === 0 && hasMergedCellsInFirstRowOrColumn : hoveredCell.colIndex === 0 && hasMergedCellsInFirstRowOrColumn;
|
|
85
|
+
if (isHoveredOnFirstRowOrColumn) {
|
|
86
|
+
var mergedSizes = direction === 'column' ? mapByRow[0].filter(function (el) {
|
|
87
|
+
return el === mapByRow[0][colIndex];
|
|
88
|
+
}).length : mapByColumn[0].filter(function (el) {
|
|
89
|
+
return el === mapByColumn[0][rowIndex];
|
|
90
|
+
}).length;
|
|
91
|
+
var mergedSelection = (0, _utils2.hasMergedCellsInSelection)(direction === 'column' ? [colIndex, colIndex + mergedSizes - 1] : [rowIndex, rowIndex + mergedSizes - 1], direction)(selection);
|
|
92
|
+
return mergedSelection;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return (0, _utils2.hasMergedCellsInSelection)(indexes, direction)(selection);
|
|
96
|
+
}, [indexes, selection, direction, hoveredCell]);
|
|
65
97
|
var handleIconProps = {
|
|
66
98
|
forceDefaultHandle: forceDefaultHandle,
|
|
67
99
|
isHandleHovered: isColumnHandleHovered || isRowHandleHovered,
|
|
@@ -148,6 +148,7 @@ var ColumnControls = exports.ColumnControls = function ColumnControls(_ref) {
|
|
|
148
148
|
direction: "column",
|
|
149
149
|
tableLocalId: localId || '',
|
|
150
150
|
indexes: indexes,
|
|
151
|
+
hoveredCell: hoveredCell,
|
|
151
152
|
previewWidth: previewWidth,
|
|
152
153
|
forceDefaultHandle: !isHover,
|
|
153
154
|
previewHeight: previewHeight,
|
|
@@ -151,6 +151,7 @@ var DragControlsComponent = function DragControlsComponent(_ref) {
|
|
|
151
151
|
previewWidth: tableWidth,
|
|
152
152
|
previewHeight: previewHeight,
|
|
153
153
|
appearance: appearance,
|
|
154
|
+
hoveredCell: hoveredCell,
|
|
154
155
|
onClick: handleClick,
|
|
155
156
|
onMouseOver: handleMouseOver,
|
|
156
157
|
onMouseOut: handleMouseOut,
|
package/dist/cjs/utils/index.js
CHANGED
|
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "anyChildCellMergedAcrossRow", {
|
|
|
9
9
|
return _nodes.anyChildCellMergedAcrossRow;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
+
Object.defineProperty(exports, "checkEdgeHasMergedCells", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function get() {
|
|
15
|
+
return _mergedCells.checkEdgeHasMergedCells;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
12
18
|
Object.defineProperty(exports, "checkIfHeaderColumnEnabled", {
|
|
13
19
|
enumerable: true,
|
|
14
20
|
get: function get() {
|
|
@@ -105,6 +111,12 @@ Object.defineProperty(exports, "findControlsHoverDecoration", {
|
|
|
105
111
|
return _decoration.findControlsHoverDecoration;
|
|
106
112
|
}
|
|
107
113
|
});
|
|
114
|
+
Object.defineProperty(exports, "findDuplicatePosition", {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
get: function get() {
|
|
117
|
+
return _mergedCells.findDuplicatePosition;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
108
120
|
Object.defineProperty(exports, "findNearestCellIndexToPoint", {
|
|
109
121
|
enumerable: true,
|
|
110
122
|
get: function get() {
|
|
@@ -231,6 +243,12 @@ Object.defineProperty(exports, "hasMergedCellsInRow", {
|
|
|
231
243
|
return _mergedCells.hasMergedCellsInRow;
|
|
232
244
|
}
|
|
233
245
|
});
|
|
246
|
+
Object.defineProperty(exports, "hasMergedCellsInSelection", {
|
|
247
|
+
enumerable: true,
|
|
248
|
+
get: function get() {
|
|
249
|
+
return _mergedCells.hasMergedCellsInSelection;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
234
252
|
Object.defineProperty(exports, "hasResizeHandler", {
|
|
235
253
|
enumerable: true,
|
|
236
254
|
get: function get() {
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.hasMergedCellsWithRowNextToRowIndex = exports.hasMergedCellsWithColumnNextToColumnIndex = exports.hasMergedCellsInRow = exports.hasMergedCellsInColumn = exports.hasMergedCellsInBetween = void 0;
|
|
7
|
+
exports.hasMergedCellsWithRowNextToRowIndex = exports.hasMergedCellsWithColumnNextToColumnIndex = exports.hasMergedCellsInSelection = exports.hasMergedCellsInRow = exports.hasMergedCellsInColumn = exports.hasMergedCellsInBetween = exports.getTableMapByRowOrColumn = exports.findDuplicatePosition = exports.checkEdgeHasMergedCells = void 0;
|
|
8
8
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
9
|
var _editorTables = require("@atlaskit/editor-tables");
|
|
10
10
|
var hasMergedCells = function hasMergedCells(indexes, normalizeRect) {
|
|
@@ -202,4 +202,98 @@ var hasMergedCellsWithRowNextToRowIndex = exports.hasMergedCellsWithRowNextToRow
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
return false;
|
|
205
|
+
};
|
|
206
|
+
var hasMergedCellsInSelection = exports.hasMergedCellsInSelection = function hasMergedCellsInSelection(indexes, type) {
|
|
207
|
+
return function (selection) {
|
|
208
|
+
var table = (0, _editorTables.findTable)(selection);
|
|
209
|
+
if (!table) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
var map = _editorTables.TableMap.get(table.node);
|
|
213
|
+
if (!map.hasMergedCells()) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
return checkEdgeHasMergedCells(indexes, map, type);
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* handle table map by preprocess table's map row or column.
|
|
222
|
+
*
|
|
223
|
+
* @param map TableMap
|
|
224
|
+
* @returns object including mapByRow and mapByColumn
|
|
225
|
+
*/
|
|
226
|
+
var getTableMapByRowOrColumn = exports.getTableMapByRowOrColumn = function getTableMapByRowOrColumn(map) {
|
|
227
|
+
var mapByRow = Array(map.height);
|
|
228
|
+
var mapByColumn = Array(map.width);
|
|
229
|
+
var mapCopy = (0, _toConsumableArray2.default)(map.map);
|
|
230
|
+
for (var i = 0; i < mapCopy.length; i++) {
|
|
231
|
+
var _mapByColumn$columnIn, _mapByRow$rowIndex;
|
|
232
|
+
var columnIndex = i % map.width;
|
|
233
|
+
mapByColumn[columnIndex] = [].concat((0, _toConsumableArray2.default)((_mapByColumn$columnIn = mapByColumn[columnIndex]) !== null && _mapByColumn$columnIn !== void 0 ? _mapByColumn$columnIn : []), [mapCopy[i]]);
|
|
234
|
+
var rowIndex = Math.trunc(i / map.width);
|
|
235
|
+
mapByRow[rowIndex] = [].concat((0, _toConsumableArray2.default)((_mapByRow$rowIndex = mapByRow[rowIndex]) !== null && _mapByRow$rowIndex !== void 0 ? _mapByRow$rowIndex : []), [mapCopy[i]]);
|
|
236
|
+
}
|
|
237
|
+
return {
|
|
238
|
+
mapByRow: mapByRow,
|
|
239
|
+
mapByColumn: mapByColumn
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
245
|
+
*
|
|
246
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
247
|
+
* @param tableMap - this return a TableMap object.
|
|
248
|
+
* @param direction - check selection is selected by row or column
|
|
249
|
+
* @returns boolean
|
|
250
|
+
*/
|
|
251
|
+
var checkEdgeHasMergedCells = exports.checkEdgeHasMergedCells = function checkEdgeHasMergedCells(indexes, tableMap, direction) {
|
|
252
|
+
var _getTableMapByRowOrCo = getTableMapByRowOrColumn(tableMap),
|
|
253
|
+
mapByRow = _getTableMapByRowOrCo.mapByRow,
|
|
254
|
+
mapByColumn = _getTableMapByRowOrCo.mapByColumn;
|
|
255
|
+
var map = 'row' === direction ? mapByRow : mapByColumn;
|
|
256
|
+
var lengthLimiter = direction === 'row' ? tableMap.width : tableMap.height;
|
|
257
|
+
var minIndex = Math.min.apply(Math, (0, _toConsumableArray2.default)(indexes));
|
|
258
|
+
var maxIndex = Math.max.apply(Math, (0, _toConsumableArray2.default)(indexes));
|
|
259
|
+
var isTopSideHaveMergedCells = false;
|
|
260
|
+
var isBottomSideHaveMergedCells = false;
|
|
261
|
+
var isOldMinIndex = !map[minIndex - 1] && !map[minIndex];
|
|
262
|
+
var isOldMaxIndex = !map[maxIndex + 1] && !map[maxIndex];
|
|
263
|
+
if (minIndex > 0 && !isOldMinIndex) {
|
|
264
|
+
var prevSelectionSet = map[minIndex - 1];
|
|
265
|
+
var minSelectionSet = map[minIndex];
|
|
266
|
+
for (var i = 0; i < lengthLimiter; i++) {
|
|
267
|
+
if (prevSelectionSet[i] === minSelectionSet[i]) {
|
|
268
|
+
isTopSideHaveMergedCells = true;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (maxIndex < map.length - 1 && !isOldMaxIndex) {
|
|
274
|
+
var afterSelectionSet = map[maxIndex + 1];
|
|
275
|
+
var maxSelectionSet = map[maxIndex];
|
|
276
|
+
for (var _i = 0; _i < lengthLimiter; _i++) {
|
|
277
|
+
if (afterSelectionSet[_i] === maxSelectionSet[_i]) {
|
|
278
|
+
isBottomSideHaveMergedCells = true;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return isTopSideHaveMergedCells || isBottomSideHaveMergedCells;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
288
|
+
*
|
|
289
|
+
* @param array this usually be the array including positions of the table map.
|
|
290
|
+
* @returns []
|
|
291
|
+
*/
|
|
292
|
+
var findDuplicatePosition = exports.findDuplicatePosition = function findDuplicatePosition(array) {
|
|
293
|
+
if (!array) {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
return array.filter(function (item, index) {
|
|
297
|
+
return array.indexOf(item) !== index;
|
|
298
|
+
});
|
|
205
299
|
};
|
package/dist/cjs/utils/nodes.js
CHANGED
|
@@ -63,8 +63,9 @@ var isLayoutSupported = exports.isLayoutSupported = function isLayoutSupported(s
|
|
|
63
63
|
var _state$schema$nodes = state.schema.nodes,
|
|
64
64
|
bodiedExtension = _state$schema$nodes.bodiedExtension,
|
|
65
65
|
layoutSection = _state$schema$nodes.layoutSection,
|
|
66
|
-
expand = _state$schema$nodes.expand
|
|
67
|
-
|
|
66
|
+
expand = _state$schema$nodes.expand,
|
|
67
|
+
extensionFrame = _state$schema$nodes.extensionFrame;
|
|
68
|
+
return !(0, _utils2.hasParentNodeOfType)([expand, layoutSection, bodiedExtension, extensionFrame])(state.selection) && !!permittedLayouts && (permittedLayouts === 'all' || permittedLayouts.indexOf('default') > -1 && permittedLayouts.indexOf('wide') > -1 && permittedLayouts.indexOf('full-width') > -1);
|
|
68
69
|
};
|
|
69
70
|
var getTableWidth = exports.getTableWidth = function getTableWidth(node) {
|
|
70
71
|
return getTableWidths(node).reduce(function (acc, current) {
|
|
@@ -111,7 +112,7 @@ var isTableNested = exports.isTableNested = function isTableNested(state) {
|
|
|
111
112
|
var tablePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
112
113
|
var parent = state.doc.resolve(tablePos).parent;
|
|
113
114
|
var nodeTypes = state.schema.nodes;
|
|
114
|
-
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension;
|
|
115
|
+
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension || parent.type === nodeTypes.extensionFrame;
|
|
115
116
|
};
|
|
116
117
|
var anyChildCellMergedAcrossRow = exports.anyChildCellMergedAcrossRow = function anyChildCellMergedAcrossRow(node) {
|
|
117
118
|
return (0, _utils.mapChildren)(node, function (child) {
|
|
@@ -4,12 +4,14 @@ import ReactDOM from 'react-dom';
|
|
|
4
4
|
import { injectIntl } from 'react-intl-next';
|
|
5
5
|
import { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
6
6
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
7
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { findTable, TableMap } from '@atlaskit/editor-tables';
|
|
7
9
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
8
10
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
9
11
|
import { getPluginState as getDnDPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
|
|
10
12
|
import { getPluginState } from '../../pm-plugins/plugin-factory';
|
|
11
13
|
import { TableCssClassName as ClassName } from '../../types';
|
|
12
|
-
import {
|
|
14
|
+
import { findDuplicatePosition, hasMergedCellsInSelection } from '../../utils';
|
|
13
15
|
import { dragTableInsertColumnButtonSize } from '../consts';
|
|
14
16
|
import { DragPreview } from '../DragPreview';
|
|
15
17
|
import { HandleIconComponent } from './HandleIconComponent';
|
|
@@ -25,6 +27,7 @@ const DragHandleComponent = ({
|
|
|
25
27
|
onMouseOver,
|
|
26
28
|
onMouseOut,
|
|
27
29
|
toggleDragMenu,
|
|
30
|
+
hoveredCell,
|
|
28
31
|
onClick,
|
|
29
32
|
editorView,
|
|
30
33
|
intl: {
|
|
@@ -50,7 +53,38 @@ const DragHandleComponent = ({
|
|
|
50
53
|
const isColumn = direction === 'column';
|
|
51
54
|
const isRowHandleHovered = isRow && hoveredRows.length > 0;
|
|
52
55
|
const isColumnHandleHovered = isColumn && hoveredColumns.length > 0;
|
|
53
|
-
const hasMergedCells = useMemo(() =>
|
|
56
|
+
const hasMergedCells = useMemo(() => {
|
|
57
|
+
const table = findTable(selection);
|
|
58
|
+
if (!table) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const map = TableMap.get(table === null || table === void 0 ? void 0 : table.node);
|
|
62
|
+
if (!map.hasMergedCells() || indexes.length < 1) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const {
|
|
66
|
+
mapByColumn,
|
|
67
|
+
mapByRow
|
|
68
|
+
} = map;
|
|
69
|
+
|
|
70
|
+
// this handle when hover to first column or row which has merged cells.
|
|
71
|
+
if (hoveredCell && hoveredCell.rowIndex !== undefined && hoveredCell.colIndex !== undefined && selection instanceof TextSelection) {
|
|
72
|
+
const {
|
|
73
|
+
rowIndex,
|
|
74
|
+
colIndex
|
|
75
|
+
} = hoveredCell;
|
|
76
|
+
const mergedPositionInRow = findDuplicatePosition(mapByRow[rowIndex]);
|
|
77
|
+
const mergedPositionInCol = findDuplicatePosition(mapByColumn[colIndex]);
|
|
78
|
+
const hasMergedCellsInFirstRowOrColumn = direction === 'column' ? mergedPositionInRow.includes(mapByRow[0][colIndex]) : mergedPositionInCol.includes(mapByColumn[0][rowIndex]);
|
|
79
|
+
const isHoveredOnFirstRowOrColumn = direction === 'column' ? hoveredCell.rowIndex === 0 && hasMergedCellsInFirstRowOrColumn : hoveredCell.colIndex === 0 && hasMergedCellsInFirstRowOrColumn;
|
|
80
|
+
if (isHoveredOnFirstRowOrColumn) {
|
|
81
|
+
const mergedSizes = direction === 'column' ? mapByRow[0].filter(el => el === mapByRow[0][colIndex]).length : mapByColumn[0].filter(el => el === mapByColumn[0][rowIndex]).length;
|
|
82
|
+
const mergedSelection = hasMergedCellsInSelection(direction === 'column' ? [colIndex, colIndex + mergedSizes - 1] : [rowIndex, rowIndex + mergedSizes - 1], direction)(selection);
|
|
83
|
+
return mergedSelection;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return hasMergedCellsInSelection(indexes, direction)(selection);
|
|
87
|
+
}, [indexes, selection, direction, hoveredCell]);
|
|
54
88
|
const handleIconProps = {
|
|
55
89
|
forceDefaultHandle,
|
|
56
90
|
isHandleHovered: isColumnHandleHovered || isRowHandleHovered,
|
|
@@ -8,4 +8,4 @@ export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getR
|
|
|
8
8
|
export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
|
|
9
9
|
export { getMergedCellsPositions } from './table';
|
|
10
10
|
export { updatePluginStateDecorations } from './update-plugin-state-decorations';
|
|
11
|
-
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween } from './merged-cells';
|
|
11
|
+
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, hasMergedCellsInSelection, findDuplicatePosition, checkEdgeHasMergedCells } from './merged-cells';
|
|
@@ -180,4 +180,95 @@ export const hasMergedCellsWithRowNextToRowIndex = (rowIndex, selection) => {
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
return false;
|
|
183
|
+
};
|
|
184
|
+
export const hasMergedCellsInSelection = (indexes, type) => selection => {
|
|
185
|
+
const table = findTable(selection);
|
|
186
|
+
if (!table) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
const map = TableMap.get(table.node);
|
|
190
|
+
if (!map.hasMergedCells()) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
return checkEdgeHasMergedCells(indexes, map, type);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* handle table map by preprocess table's map row or column.
|
|
198
|
+
*
|
|
199
|
+
* @param map TableMap
|
|
200
|
+
* @returns object including mapByRow and mapByColumn
|
|
201
|
+
*/
|
|
202
|
+
export const getTableMapByRowOrColumn = map => {
|
|
203
|
+
let mapByRow = Array(map.height);
|
|
204
|
+
let mapByColumn = Array(map.width);
|
|
205
|
+
const mapCopy = [...map.map];
|
|
206
|
+
for (let i = 0; i < mapCopy.length; i++) {
|
|
207
|
+
var _mapByColumn$columnIn, _mapByRow$rowIndex;
|
|
208
|
+
const columnIndex = i % map.width;
|
|
209
|
+
mapByColumn[columnIndex] = [...((_mapByColumn$columnIn = mapByColumn[columnIndex]) !== null && _mapByColumn$columnIn !== void 0 ? _mapByColumn$columnIn : []), mapCopy[i]];
|
|
210
|
+
const rowIndex = Math.trunc(i / map.width);
|
|
211
|
+
mapByRow[rowIndex] = [...((_mapByRow$rowIndex = mapByRow[rowIndex]) !== null && _mapByRow$rowIndex !== void 0 ? _mapByRow$rowIndex : []), mapCopy[i]];
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
mapByRow,
|
|
215
|
+
mapByColumn
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
221
|
+
*
|
|
222
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
223
|
+
* @param tableMap - this return a TableMap object.
|
|
224
|
+
* @param direction - check selection is selected by row or column
|
|
225
|
+
* @returns boolean
|
|
226
|
+
*/
|
|
227
|
+
export const checkEdgeHasMergedCells = (indexes, tableMap, direction) => {
|
|
228
|
+
const {
|
|
229
|
+
mapByRow,
|
|
230
|
+
mapByColumn
|
|
231
|
+
} = getTableMapByRowOrColumn(tableMap);
|
|
232
|
+
const map = 'row' === direction ? mapByRow : mapByColumn;
|
|
233
|
+
const lengthLimiter = direction === 'row' ? tableMap.width : tableMap.height;
|
|
234
|
+
let minIndex = Math.min(...indexes);
|
|
235
|
+
let maxIndex = Math.max(...indexes);
|
|
236
|
+
let isTopSideHaveMergedCells = false;
|
|
237
|
+
let isBottomSideHaveMergedCells = false;
|
|
238
|
+
let isOldMinIndex = !map[minIndex - 1] && !map[minIndex];
|
|
239
|
+
let isOldMaxIndex = !map[maxIndex + 1] && !map[maxIndex];
|
|
240
|
+
if (minIndex > 0 && !isOldMinIndex) {
|
|
241
|
+
const prevSelectionSet = map[minIndex - 1];
|
|
242
|
+
const minSelectionSet = map[minIndex];
|
|
243
|
+
for (let i = 0; i < lengthLimiter; i++) {
|
|
244
|
+
if (prevSelectionSet[i] === minSelectionSet[i]) {
|
|
245
|
+
isTopSideHaveMergedCells = true;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (maxIndex < map.length - 1 && !isOldMaxIndex) {
|
|
251
|
+
const afterSelectionSet = map[maxIndex + 1];
|
|
252
|
+
const maxSelectionSet = map[maxIndex];
|
|
253
|
+
for (let i = 0; i < lengthLimiter; i++) {
|
|
254
|
+
if (afterSelectionSet[i] === maxSelectionSet[i]) {
|
|
255
|
+
isBottomSideHaveMergedCells = true;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return isTopSideHaveMergedCells || isBottomSideHaveMergedCells;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
265
|
+
*
|
|
266
|
+
* @param array this usually be the array including positions of the table map.
|
|
267
|
+
* @returns []
|
|
268
|
+
*/
|
|
269
|
+
export const findDuplicatePosition = array => {
|
|
270
|
+
if (!array) {
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
return array.filter((item, index) => array.indexOf(item) !== index);
|
|
183
274
|
};
|
|
@@ -48,9 +48,10 @@ export const isLayoutSupported = state => {
|
|
|
48
48
|
const {
|
|
49
49
|
bodiedExtension,
|
|
50
50
|
layoutSection,
|
|
51
|
-
expand
|
|
51
|
+
expand,
|
|
52
|
+
extensionFrame
|
|
52
53
|
} = state.schema.nodes;
|
|
53
|
-
return !hasParentNodeOfType([expand, layoutSection, bodiedExtension])(state.selection) && !!permittedLayouts && (permittedLayouts === 'all' || permittedLayouts.indexOf('default') > -1 && permittedLayouts.indexOf('wide') > -1 && permittedLayouts.indexOf('full-width') > -1);
|
|
54
|
+
return !hasParentNodeOfType([expand, layoutSection, bodiedExtension, extensionFrame])(state.selection) && !!permittedLayouts && (permittedLayouts === 'all' || permittedLayouts.indexOf('default') > -1 && permittedLayouts.indexOf('wide') > -1 && permittedLayouts.indexOf('full-width') > -1);
|
|
54
55
|
};
|
|
55
56
|
export const getTableWidth = node => {
|
|
56
57
|
return getTableWidths(node).reduce((acc, current) => acc + current, 0);
|
|
@@ -94,7 +95,7 @@ function getTableWidths(node) {
|
|
|
94
95
|
export const isTableNested = (state, tablePos = 0) => {
|
|
95
96
|
const parent = state.doc.resolve(tablePos).parent;
|
|
96
97
|
const nodeTypes = state.schema.nodes;
|
|
97
|
-
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension;
|
|
98
|
+
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension || parent.type === nodeTypes.extensionFrame;
|
|
98
99
|
};
|
|
99
100
|
export const anyChildCellMergedAcrossRow = node => mapChildren(node, child => child.attrs.rowspan || 0).some(rowspan => rowspan > 1);
|
|
100
101
|
|
|
@@ -6,12 +6,14 @@ import ReactDOM from 'react-dom';
|
|
|
6
6
|
import { injectIntl } from 'react-intl-next';
|
|
7
7
|
import { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
8
8
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
9
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
10
|
+
import { findTable, TableMap } from '@atlaskit/editor-tables';
|
|
9
11
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
10
12
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
11
13
|
import { getPluginState as getDnDPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
|
|
12
14
|
import { getPluginState } from '../../pm-plugins/plugin-factory';
|
|
13
15
|
import { TableCssClassName as ClassName } from '../../types';
|
|
14
|
-
import {
|
|
16
|
+
import { findDuplicatePosition, hasMergedCellsInSelection } from '../../utils';
|
|
15
17
|
import { dragTableInsertColumnButtonSize } from '../consts';
|
|
16
18
|
import { DragPreview } from '../DragPreview';
|
|
17
19
|
import { HandleIconComponent } from './HandleIconComponent';
|
|
@@ -30,6 +32,7 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
|
|
|
30
32
|
onMouseOver = _ref.onMouseOver,
|
|
31
33
|
onMouseOut = _ref.onMouseOut,
|
|
32
34
|
toggleDragMenu = _ref.toggleDragMenu,
|
|
35
|
+
hoveredCell = _ref.hoveredCell,
|
|
33
36
|
onClick = _ref.onClick,
|
|
34
37
|
editorView = _ref.editorView,
|
|
35
38
|
formatMessage = _ref.intl.formatMessage;
|
|
@@ -50,8 +53,37 @@ var DragHandleComponent = function DragHandleComponent(_ref) {
|
|
|
50
53
|
var isRowHandleHovered = isRow && hoveredRows.length > 0;
|
|
51
54
|
var isColumnHandleHovered = isColumn && hoveredColumns.length > 0;
|
|
52
55
|
var hasMergedCells = useMemo(function () {
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
var table = findTable(selection);
|
|
57
|
+
if (!table) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
var map = TableMap.get(table === null || table === void 0 ? void 0 : table.node);
|
|
61
|
+
if (!map.hasMergedCells() || indexes.length < 1) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
var mapByColumn = map.mapByColumn,
|
|
65
|
+
mapByRow = map.mapByRow;
|
|
66
|
+
|
|
67
|
+
// this handle when hover to first column or row which has merged cells.
|
|
68
|
+
if (hoveredCell && hoveredCell.rowIndex !== undefined && hoveredCell.colIndex !== undefined && selection instanceof TextSelection) {
|
|
69
|
+
var rowIndex = hoveredCell.rowIndex,
|
|
70
|
+
colIndex = hoveredCell.colIndex;
|
|
71
|
+
var mergedPositionInRow = findDuplicatePosition(mapByRow[rowIndex]);
|
|
72
|
+
var mergedPositionInCol = findDuplicatePosition(mapByColumn[colIndex]);
|
|
73
|
+
var hasMergedCellsInFirstRowOrColumn = direction === 'column' ? mergedPositionInRow.includes(mapByRow[0][colIndex]) : mergedPositionInCol.includes(mapByColumn[0][rowIndex]);
|
|
74
|
+
var isHoveredOnFirstRowOrColumn = direction === 'column' ? hoveredCell.rowIndex === 0 && hasMergedCellsInFirstRowOrColumn : hoveredCell.colIndex === 0 && hasMergedCellsInFirstRowOrColumn;
|
|
75
|
+
if (isHoveredOnFirstRowOrColumn) {
|
|
76
|
+
var mergedSizes = direction === 'column' ? mapByRow[0].filter(function (el) {
|
|
77
|
+
return el === mapByRow[0][colIndex];
|
|
78
|
+
}).length : mapByColumn[0].filter(function (el) {
|
|
79
|
+
return el === mapByColumn[0][rowIndex];
|
|
80
|
+
}).length;
|
|
81
|
+
var mergedSelection = hasMergedCellsInSelection(direction === 'column' ? [colIndex, colIndex + mergedSizes - 1] : [rowIndex, rowIndex + mergedSizes - 1], direction)(selection);
|
|
82
|
+
return mergedSelection;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return hasMergedCellsInSelection(indexes, direction)(selection);
|
|
86
|
+
}, [indexes, selection, direction, hoveredCell]);
|
|
55
87
|
var handleIconProps = {
|
|
56
88
|
forceDefaultHandle: forceDefaultHandle,
|
|
57
89
|
isHandleHovered: isColumnHandleHovered || isRowHandleHovered,
|
|
@@ -139,6 +139,7 @@ export var ColumnControls = function ColumnControls(_ref) {
|
|
|
139
139
|
direction: "column",
|
|
140
140
|
tableLocalId: localId || '',
|
|
141
141
|
indexes: indexes,
|
|
142
|
+
hoveredCell: hoveredCell,
|
|
142
143
|
previewWidth: previewWidth,
|
|
143
144
|
forceDefaultHandle: !isHover,
|
|
144
145
|
previewHeight: previewHeight,
|
|
@@ -141,6 +141,7 @@ var DragControlsComponent = function DragControlsComponent(_ref) {
|
|
|
141
141
|
previewWidth: tableWidth,
|
|
142
142
|
previewHeight: previewHeight,
|
|
143
143
|
appearance: appearance,
|
|
144
|
+
hoveredCell: hoveredCell,
|
|
144
145
|
onClick: handleClick,
|
|
145
146
|
onMouseOver: handleMouseOver,
|
|
146
147
|
onMouseOut: handleMouseOut,
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -8,4 +8,4 @@ export { getRowHeights, isRowDeleteButtonVisible, getRowDeleteButtonParams, getR
|
|
|
8
8
|
export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
|
|
9
9
|
export { getMergedCellsPositions } from './table';
|
|
10
10
|
export { updatePluginStateDecorations } from './update-plugin-state-decorations';
|
|
11
|
-
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween } from './merged-cells';
|
|
11
|
+
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, hasMergedCellsInSelection, findDuplicatePosition, checkEdgeHasMergedCells } from './merged-cells';
|
|
@@ -195,4 +195,98 @@ export var hasMergedCellsWithRowNextToRowIndex = function hasMergedCellsWithRowN
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
return false;
|
|
198
|
+
};
|
|
199
|
+
export var hasMergedCellsInSelection = function hasMergedCellsInSelection(indexes, type) {
|
|
200
|
+
return function (selection) {
|
|
201
|
+
var table = findTable(selection);
|
|
202
|
+
if (!table) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
var map = TableMap.get(table.node);
|
|
206
|
+
if (!map.hasMergedCells()) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return checkEdgeHasMergedCells(indexes, map, type);
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* handle table map by preprocess table's map row or column.
|
|
215
|
+
*
|
|
216
|
+
* @param map TableMap
|
|
217
|
+
* @returns object including mapByRow and mapByColumn
|
|
218
|
+
*/
|
|
219
|
+
export var getTableMapByRowOrColumn = function getTableMapByRowOrColumn(map) {
|
|
220
|
+
var mapByRow = Array(map.height);
|
|
221
|
+
var mapByColumn = Array(map.width);
|
|
222
|
+
var mapCopy = _toConsumableArray(map.map);
|
|
223
|
+
for (var i = 0; i < mapCopy.length; i++) {
|
|
224
|
+
var _mapByColumn$columnIn, _mapByRow$rowIndex;
|
|
225
|
+
var columnIndex = i % map.width;
|
|
226
|
+
mapByColumn[columnIndex] = [].concat(_toConsumableArray((_mapByColumn$columnIn = mapByColumn[columnIndex]) !== null && _mapByColumn$columnIn !== void 0 ? _mapByColumn$columnIn : []), [mapCopy[i]]);
|
|
227
|
+
var rowIndex = Math.trunc(i / map.width);
|
|
228
|
+
mapByRow[rowIndex] = [].concat(_toConsumableArray((_mapByRow$rowIndex = mapByRow[rowIndex]) !== null && _mapByRow$rowIndex !== void 0 ? _mapByRow$rowIndex : []), [mapCopy[i]]);
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
mapByRow: mapByRow,
|
|
232
|
+
mapByColumn: mapByColumn
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
238
|
+
*
|
|
239
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
240
|
+
* @param tableMap - this return a TableMap object.
|
|
241
|
+
* @param direction - check selection is selected by row or column
|
|
242
|
+
* @returns boolean
|
|
243
|
+
*/
|
|
244
|
+
export var checkEdgeHasMergedCells = function checkEdgeHasMergedCells(indexes, tableMap, direction) {
|
|
245
|
+
var _getTableMapByRowOrCo = getTableMapByRowOrColumn(tableMap),
|
|
246
|
+
mapByRow = _getTableMapByRowOrCo.mapByRow,
|
|
247
|
+
mapByColumn = _getTableMapByRowOrCo.mapByColumn;
|
|
248
|
+
var map = 'row' === direction ? mapByRow : mapByColumn;
|
|
249
|
+
var lengthLimiter = direction === 'row' ? tableMap.width : tableMap.height;
|
|
250
|
+
var minIndex = Math.min.apply(Math, _toConsumableArray(indexes));
|
|
251
|
+
var maxIndex = Math.max.apply(Math, _toConsumableArray(indexes));
|
|
252
|
+
var isTopSideHaveMergedCells = false;
|
|
253
|
+
var isBottomSideHaveMergedCells = false;
|
|
254
|
+
var isOldMinIndex = !map[minIndex - 1] && !map[minIndex];
|
|
255
|
+
var isOldMaxIndex = !map[maxIndex + 1] && !map[maxIndex];
|
|
256
|
+
if (minIndex > 0 && !isOldMinIndex) {
|
|
257
|
+
var prevSelectionSet = map[minIndex - 1];
|
|
258
|
+
var minSelectionSet = map[minIndex];
|
|
259
|
+
for (var i = 0; i < lengthLimiter; i++) {
|
|
260
|
+
if (prevSelectionSet[i] === minSelectionSet[i]) {
|
|
261
|
+
isTopSideHaveMergedCells = true;
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (maxIndex < map.length - 1 && !isOldMaxIndex) {
|
|
267
|
+
var afterSelectionSet = map[maxIndex + 1];
|
|
268
|
+
var maxSelectionSet = map[maxIndex];
|
|
269
|
+
for (var _i = 0; _i < lengthLimiter; _i++) {
|
|
270
|
+
if (afterSelectionSet[_i] === maxSelectionSet[_i]) {
|
|
271
|
+
isBottomSideHaveMergedCells = true;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return isTopSideHaveMergedCells || isBottomSideHaveMergedCells;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
281
|
+
*
|
|
282
|
+
* @param array this usually be the array including positions of the table map.
|
|
283
|
+
* @returns []
|
|
284
|
+
*/
|
|
285
|
+
export var findDuplicatePosition = function findDuplicatePosition(array) {
|
|
286
|
+
if (!array) {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
return array.filter(function (item, index) {
|
|
290
|
+
return array.indexOf(item) !== index;
|
|
291
|
+
});
|
|
198
292
|
};
|
package/dist/esm/utils/nodes.js
CHANGED
|
@@ -56,8 +56,9 @@ export var isLayoutSupported = function isLayoutSupported(state) {
|
|
|
56
56
|
var _state$schema$nodes = state.schema.nodes,
|
|
57
57
|
bodiedExtension = _state$schema$nodes.bodiedExtension,
|
|
58
58
|
layoutSection = _state$schema$nodes.layoutSection,
|
|
59
|
-
expand = _state$schema$nodes.expand
|
|
60
|
-
|
|
59
|
+
expand = _state$schema$nodes.expand,
|
|
60
|
+
extensionFrame = _state$schema$nodes.extensionFrame;
|
|
61
|
+
return !hasParentNodeOfType([expand, layoutSection, bodiedExtension, extensionFrame])(state.selection) && !!permittedLayouts && (permittedLayouts === 'all' || permittedLayouts.indexOf('default') > -1 && permittedLayouts.indexOf('wide') > -1 && permittedLayouts.indexOf('full-width') > -1);
|
|
61
62
|
};
|
|
62
63
|
export var getTableWidth = function getTableWidth(node) {
|
|
63
64
|
return getTableWidths(node).reduce(function (acc, current) {
|
|
@@ -104,7 +105,7 @@ export var isTableNested = function isTableNested(state) {
|
|
|
104
105
|
var tablePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
105
106
|
var parent = state.doc.resolve(tablePos).parent;
|
|
106
107
|
var nodeTypes = state.schema.nodes;
|
|
107
|
-
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension;
|
|
108
|
+
return parent.type === nodeTypes.layoutColumn || parent.type === nodeTypes.expand || parent.type === nodeTypes.bodiedExtension || parent.type === nodeTypes.extensionFrame;
|
|
108
109
|
};
|
|
109
110
|
export var anyChildCellMergedAcrossRow = function anyChildCellMergedAcrossRow(node) {
|
|
110
111
|
return mapChildren(node, function (child) {
|
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import type { WrappedComponentProps } from 'react-intl-next';
|
|
4
4
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import type { TriggerType } from '../../pm-plugins/drag-and-drop/types';
|
|
6
|
-
import type { TableDirection } from '../../types';
|
|
6
|
+
import type { CellHoverMeta, TableDirection } from '../../types';
|
|
7
7
|
export type DragHandleAppearance = 'default' | 'selected' | 'disabled' | 'danger' | 'placeholder';
|
|
8
8
|
type DragHandleProps = {
|
|
9
9
|
tableLocalId: string;
|
|
@@ -11,6 +11,7 @@ type DragHandleProps = {
|
|
|
11
11
|
forceDefaultHandle?: boolean;
|
|
12
12
|
previewWidth?: number;
|
|
13
13
|
previewHeight?: number;
|
|
14
|
+
hoveredCell?: CellHoverMeta;
|
|
14
15
|
direction?: TableDirection;
|
|
15
16
|
appearance?: DragHandleAppearance;
|
|
16
17
|
onClick?: MouseEventHandler;
|
|
@@ -9,4 +9,4 @@ export type { RowParams } from './row-controls';
|
|
|
9
9
|
export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
|
|
10
10
|
export { getMergedCellsPositions } from './table';
|
|
11
11
|
export { updatePluginStateDecorations } from './update-plugin-state-decorations';
|
|
12
|
-
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, } from './merged-cells';
|
|
12
|
+
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, hasMergedCellsInSelection, findDuplicatePosition, checkEdgeHasMergedCells, } from './merged-cells';
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { TableMap } from '@atlaskit/editor-tables';
|
|
2
3
|
type MergeType = 'row' | 'column';
|
|
3
4
|
export declare const hasMergedCellsInColumn: (columnIndexes: number | number[]) => (selection: Selection) => boolean;
|
|
4
5
|
export declare const hasMergedCellsInRow: (rowIndexes: number | number[]) => (selection: Selection) => boolean;
|
|
5
6
|
export declare const hasMergedCellsInBetween: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
|
|
6
7
|
export declare const hasMergedCellsWithColumnNextToColumnIndex: (colIndex: number, selection: Selection) => boolean;
|
|
7
8
|
export declare const hasMergedCellsWithRowNextToRowIndex: (rowIndex: number, selection: Selection) => boolean;
|
|
9
|
+
export declare const hasMergedCellsInSelection: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* handle table map by preprocess table's map row or column.
|
|
12
|
+
*
|
|
13
|
+
* @param map TableMap
|
|
14
|
+
* @returns object including mapByRow and mapByColumn
|
|
15
|
+
*/
|
|
16
|
+
export declare const getTableMapByRowOrColumn: (map: TableMap) => {
|
|
17
|
+
mapByRow: any[];
|
|
18
|
+
mapByColumn: any[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
22
|
+
*
|
|
23
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
24
|
+
* @param tableMap - this return a TableMap object.
|
|
25
|
+
* @param direction - check selection is selected by row or column
|
|
26
|
+
* @returns boolean
|
|
27
|
+
*/
|
|
28
|
+
export declare const checkEdgeHasMergedCells: (indexes: number[], tableMap: TableMap, direction: 'row' | 'column') => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
31
|
+
*
|
|
32
|
+
* @param array this usually be the array including positions of the table map.
|
|
33
|
+
* @returns []
|
|
34
|
+
*/
|
|
35
|
+
export declare const findDuplicatePosition: (array: number[]) => number[];
|
|
8
36
|
export {};
|
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import type { WrappedComponentProps } from 'react-intl-next';
|
|
4
4
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
5
|
import type { TriggerType } from '../../pm-plugins/drag-and-drop/types';
|
|
6
|
-
import type { TableDirection } from '../../types';
|
|
6
|
+
import type { CellHoverMeta, TableDirection } from '../../types';
|
|
7
7
|
export type DragHandleAppearance = 'default' | 'selected' | 'disabled' | 'danger' | 'placeholder';
|
|
8
8
|
type DragHandleProps = {
|
|
9
9
|
tableLocalId: string;
|
|
@@ -11,6 +11,7 @@ type DragHandleProps = {
|
|
|
11
11
|
forceDefaultHandle?: boolean;
|
|
12
12
|
previewWidth?: number;
|
|
13
13
|
previewHeight?: number;
|
|
14
|
+
hoveredCell?: CellHoverMeta;
|
|
14
15
|
direction?: TableDirection;
|
|
15
16
|
appearance?: DragHandleAppearance;
|
|
16
17
|
onClick?: MouseEventHandler;
|
|
@@ -9,4 +9,4 @@ export type { RowParams } from './row-controls';
|
|
|
9
9
|
export { getSelectedTableInfo, getSelectedCellInfo } from './analytics';
|
|
10
10
|
export { getMergedCellsPositions } from './table';
|
|
11
11
|
export { updatePluginStateDecorations } from './update-plugin-state-decorations';
|
|
12
|
-
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, } from './merged-cells';
|
|
12
|
+
export { hasMergedCellsInColumn, hasMergedCellsInRow, hasMergedCellsInBetween, hasMergedCellsInSelection, findDuplicatePosition, checkEdgeHasMergedCells, } from './merged-cells';
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { TableMap } from '@atlaskit/editor-tables';
|
|
2
3
|
type MergeType = 'row' | 'column';
|
|
3
4
|
export declare const hasMergedCellsInColumn: (columnIndexes: number | number[]) => (selection: Selection) => boolean;
|
|
4
5
|
export declare const hasMergedCellsInRow: (rowIndexes: number | number[]) => (selection: Selection) => boolean;
|
|
5
6
|
export declare const hasMergedCellsInBetween: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
|
|
6
7
|
export declare const hasMergedCellsWithColumnNextToColumnIndex: (colIndex: number, selection: Selection) => boolean;
|
|
7
8
|
export declare const hasMergedCellsWithRowNextToRowIndex: (rowIndex: number, selection: Selection) => boolean;
|
|
9
|
+
export declare const hasMergedCellsInSelection: (indexes: number[], type: MergeType) => (selection: Selection) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* handle table map by preprocess table's map row or column.
|
|
12
|
+
*
|
|
13
|
+
* @param map TableMap
|
|
14
|
+
* @returns object including mapByRow and mapByColumn
|
|
15
|
+
*/
|
|
16
|
+
export declare const getTableMapByRowOrColumn: (map: TableMap) => {
|
|
17
|
+
mapByRow: any[];
|
|
18
|
+
mapByColumn: any[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
22
|
+
*
|
|
23
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
24
|
+
* @param tableMap - this return a TableMap object.
|
|
25
|
+
* @param direction - check selection is selected by row or column
|
|
26
|
+
* @returns boolean
|
|
27
|
+
*/
|
|
28
|
+
export declare const checkEdgeHasMergedCells: (indexes: number[], tableMap: TableMap, direction: 'row' | 'column') => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
31
|
+
*
|
|
32
|
+
* @param array this usually be the array including positions of the table map.
|
|
33
|
+
* @returns []
|
|
34
|
+
*/
|
|
35
|
+
export declare const findDuplicatePosition: (array: number[]) => number[];
|
|
8
36
|
export {};
|
package/package.json
CHANGED
|
@@ -8,7 +8,9 @@ import { injectIntl } from 'react-intl-next';
|
|
|
8
8
|
|
|
9
9
|
import { tableMessages as messages } from '@atlaskit/editor-common/messages';
|
|
10
10
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
11
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
11
12
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
13
|
+
import { findTable, TableMap } from '@atlaskit/editor-tables';
|
|
12
14
|
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
13
15
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
14
16
|
import { token } from '@atlaskit/tokens';
|
|
@@ -16,9 +18,9 @@ import { token } from '@atlaskit/tokens';
|
|
|
16
18
|
import { getPluginState as getDnDPluginState } from '../../pm-plugins/drag-and-drop/plugin-factory';
|
|
17
19
|
import type { TriggerType } from '../../pm-plugins/drag-and-drop/types';
|
|
18
20
|
import { getPluginState } from '../../pm-plugins/plugin-factory';
|
|
19
|
-
import type { TableDirection } from '../../types';
|
|
20
21
|
import { TableCssClassName as ClassName } from '../../types';
|
|
21
|
-
import {
|
|
22
|
+
import type { CellHoverMeta, TableDirection } from '../../types';
|
|
23
|
+
import { findDuplicatePosition, hasMergedCellsInSelection } from '../../utils';
|
|
22
24
|
import { dragTableInsertColumnButtonSize } from '../consts';
|
|
23
25
|
import { DragPreview } from '../DragPreview';
|
|
24
26
|
|
|
@@ -37,6 +39,7 @@ type DragHandleProps = {
|
|
|
37
39
|
forceDefaultHandle?: boolean;
|
|
38
40
|
previewWidth?: number;
|
|
39
41
|
previewHeight?: number;
|
|
42
|
+
hoveredCell?: CellHoverMeta;
|
|
40
43
|
direction?: TableDirection;
|
|
41
44
|
appearance?: DragHandleAppearance;
|
|
42
45
|
onClick?: MouseEventHandler;
|
|
@@ -62,6 +65,7 @@ const DragHandleComponent = ({
|
|
|
62
65
|
onMouseOver,
|
|
63
66
|
onMouseOut,
|
|
64
67
|
toggleDragMenu,
|
|
68
|
+
hoveredCell,
|
|
65
69
|
onClick,
|
|
66
70
|
editorView,
|
|
67
71
|
intl: { formatMessage },
|
|
@@ -83,13 +87,64 @@ const DragHandleComponent = ({
|
|
|
83
87
|
const isRowHandleHovered = isRow && hoveredRows.length > 0;
|
|
84
88
|
const isColumnHandleHovered = isColumn && hoveredColumns.length > 0;
|
|
85
89
|
|
|
86
|
-
const hasMergedCells = useMemo(
|
|
87
|
-
()
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
const hasMergedCells = useMemo(() => {
|
|
91
|
+
const table = findTable(selection);
|
|
92
|
+
if (!table) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const map = TableMap.get(table?.node);
|
|
97
|
+
|
|
98
|
+
if (!map.hasMergedCells() || indexes.length < 1) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { mapByColumn, mapByRow } = map;
|
|
103
|
+
|
|
104
|
+
// this handle when hover to first column or row which has merged cells.
|
|
105
|
+
if (
|
|
106
|
+
hoveredCell &&
|
|
107
|
+
hoveredCell.rowIndex !== undefined &&
|
|
108
|
+
hoveredCell.colIndex !== undefined &&
|
|
109
|
+
selection instanceof TextSelection
|
|
110
|
+
) {
|
|
111
|
+
const { rowIndex, colIndex } = hoveredCell;
|
|
112
|
+
|
|
113
|
+
const mergedPositionInRow = findDuplicatePosition(mapByRow[rowIndex]);
|
|
114
|
+
const mergedPositionInCol = findDuplicatePosition(mapByColumn[colIndex]);
|
|
115
|
+
|
|
116
|
+
const hasMergedCellsInFirstRowOrColumn =
|
|
117
|
+
direction === 'column'
|
|
118
|
+
? mergedPositionInRow.includes(mapByRow[0][colIndex])
|
|
119
|
+
: mergedPositionInCol.includes(mapByColumn[0][rowIndex]);
|
|
120
|
+
|
|
121
|
+
const isHoveredOnFirstRowOrColumn =
|
|
122
|
+
direction === 'column'
|
|
123
|
+
? hoveredCell.rowIndex === 0 && hasMergedCellsInFirstRowOrColumn
|
|
124
|
+
: hoveredCell.colIndex === 0 && hasMergedCellsInFirstRowOrColumn;
|
|
125
|
+
|
|
126
|
+
if (isHoveredOnFirstRowOrColumn) {
|
|
127
|
+
const mergedSizes =
|
|
128
|
+
direction === 'column'
|
|
129
|
+
? mapByRow[0].filter((el: number) => el === mapByRow[0][colIndex])
|
|
130
|
+
.length
|
|
131
|
+
: mapByColumn[0].filter(
|
|
132
|
+
(el: number) => el === mapByColumn[0][rowIndex],
|
|
133
|
+
).length;
|
|
134
|
+
|
|
135
|
+
const mergedSelection = hasMergedCellsInSelection(
|
|
136
|
+
direction === 'column'
|
|
137
|
+
? [colIndex, colIndex + mergedSizes - 1]
|
|
138
|
+
: [rowIndex, rowIndex + mergedSizes - 1],
|
|
139
|
+
direction,
|
|
140
|
+
)(selection);
|
|
141
|
+
|
|
142
|
+
return mergedSelection;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return hasMergedCellsInSelection(indexes, direction)(selection);
|
|
147
|
+
}, [indexes, selection, direction, hoveredCell]);
|
|
93
148
|
|
|
94
149
|
const handleIconProps = {
|
|
95
150
|
forceDefaultHandle,
|
package/src/utils/index.ts
CHANGED
|
@@ -225,3 +225,107 @@ export const hasMergedCellsWithRowNextToRowIndex = (
|
|
|
225
225
|
|
|
226
226
|
return false;
|
|
227
227
|
};
|
|
228
|
+
|
|
229
|
+
export const hasMergedCellsInSelection =
|
|
230
|
+
(indexes: number[], type: MergeType) =>
|
|
231
|
+
(selection: Selection): boolean => {
|
|
232
|
+
const table = findTable(selection);
|
|
233
|
+
if (!table) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const map = TableMap.get(table.node);
|
|
238
|
+
|
|
239
|
+
if (!map.hasMergedCells()) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return checkEdgeHasMergedCells(indexes, map, type);
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* handle table map by preprocess table's map row or column.
|
|
248
|
+
*
|
|
249
|
+
* @param map TableMap
|
|
250
|
+
* @returns object including mapByRow and mapByColumn
|
|
251
|
+
*/
|
|
252
|
+
export const getTableMapByRowOrColumn = (map: TableMap) => {
|
|
253
|
+
let mapByRow = Array(map.height);
|
|
254
|
+
let mapByColumn = Array(map.width);
|
|
255
|
+
|
|
256
|
+
const mapCopy = [...map.map];
|
|
257
|
+
|
|
258
|
+
for (let i = 0; i < mapCopy.length; i++) {
|
|
259
|
+
const columnIndex = i % map.width;
|
|
260
|
+
mapByColumn[columnIndex] = [
|
|
261
|
+
...(mapByColumn[columnIndex] ?? []),
|
|
262
|
+
mapCopy[i],
|
|
263
|
+
];
|
|
264
|
+
const rowIndex = Math.trunc(i / map.width);
|
|
265
|
+
mapByRow[rowIndex] = [...(mapByRow[rowIndex] ?? []), mapCopy[i]];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return { mapByRow, mapByColumn };
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* this check the selection has merged cells with previous/next col or row.
|
|
273
|
+
*
|
|
274
|
+
* @param indexes - this get the indexes of the selection,e.g. [0,1] for selecting first two rows or columns.
|
|
275
|
+
* @param tableMap - this return a TableMap object.
|
|
276
|
+
* @param direction - check selection is selected by row or column
|
|
277
|
+
* @returns boolean
|
|
278
|
+
*/
|
|
279
|
+
export const checkEdgeHasMergedCells = (
|
|
280
|
+
indexes: number[],
|
|
281
|
+
tableMap: TableMap,
|
|
282
|
+
direction: 'row' | 'column',
|
|
283
|
+
): boolean => {
|
|
284
|
+
const { mapByRow, mapByColumn } = getTableMapByRowOrColumn(tableMap);
|
|
285
|
+
const map = 'row' === direction ? mapByRow : mapByColumn;
|
|
286
|
+
const lengthLimiter = direction === 'row' ? tableMap.width : tableMap.height;
|
|
287
|
+
|
|
288
|
+
let minIndex = Math.min(...indexes);
|
|
289
|
+
let maxIndex = Math.max(...indexes);
|
|
290
|
+
let isTopSideHaveMergedCells = false;
|
|
291
|
+
let isBottomSideHaveMergedCells = false;
|
|
292
|
+
let isOldMinIndex = !map[minIndex - 1] && !map[minIndex];
|
|
293
|
+
let isOldMaxIndex = !map[maxIndex + 1] && !map[maxIndex];
|
|
294
|
+
|
|
295
|
+
if (minIndex > 0 && !isOldMinIndex) {
|
|
296
|
+
const prevSelectionSet = map[minIndex - 1];
|
|
297
|
+
const minSelectionSet = map[minIndex];
|
|
298
|
+
for (let i = 0; i < lengthLimiter; i++) {
|
|
299
|
+
if (prevSelectionSet[i] === minSelectionSet[i]) {
|
|
300
|
+
isTopSideHaveMergedCells = true;
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (maxIndex < map.length - 1 && !isOldMaxIndex) {
|
|
307
|
+
const afterSelectionSet = map[maxIndex + 1];
|
|
308
|
+
const maxSelectionSet = map[maxIndex];
|
|
309
|
+
|
|
310
|
+
for (let i = 0; i < lengthLimiter; i++) {
|
|
311
|
+
if (afterSelectionSet[i] === maxSelectionSet[i]) {
|
|
312
|
+
isBottomSideHaveMergedCells = true;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return isTopSideHaveMergedCells || isBottomSideHaveMergedCells;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* this function will find the duplicate position in the array(table map position array).
|
|
322
|
+
*
|
|
323
|
+
* @param array this usually be the array including positions of the table map.
|
|
324
|
+
* @returns []
|
|
325
|
+
*/
|
|
326
|
+
export const findDuplicatePosition = (array: number[]): number[] => {
|
|
327
|
+
if (!array) {
|
|
328
|
+
return [];
|
|
329
|
+
}
|
|
330
|
+
return array.filter((item, index) => array.indexOf(item) !== index);
|
|
331
|
+
};
|
package/src/utils/nodes.ts
CHANGED
|
@@ -65,12 +65,16 @@ export const checkIfNumberColumnEnabled = (selection: Selection): boolean =>
|
|
|
65
65
|
|
|
66
66
|
export const isLayoutSupported = (state: EditorState): boolean => {
|
|
67
67
|
const { permittedLayouts } = pluginKey.getState(state)?.pluginConfig || {};
|
|
68
|
-
const { bodiedExtension, layoutSection, expand } =
|
|
68
|
+
const { bodiedExtension, layoutSection, expand, extensionFrame } =
|
|
69
|
+
state.schema.nodes;
|
|
69
70
|
|
|
70
71
|
return (
|
|
71
|
-
!hasParentNodeOfType([
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
!hasParentNodeOfType([
|
|
73
|
+
expand,
|
|
74
|
+
layoutSection,
|
|
75
|
+
bodiedExtension,
|
|
76
|
+
extensionFrame,
|
|
77
|
+
])(state.selection) &&
|
|
74
78
|
!!permittedLayouts &&
|
|
75
79
|
(permittedLayouts === 'all' ||
|
|
76
80
|
(permittedLayouts.indexOf('default') > -1 &&
|
|
@@ -150,7 +154,8 @@ export const isTableNested = (state: EditorState, tablePos = 0): boolean => {
|
|
|
150
154
|
return (
|
|
151
155
|
parent.type === nodeTypes.layoutColumn ||
|
|
152
156
|
parent.type === nodeTypes.expand ||
|
|
153
|
-
parent.type === nodeTypes.bodiedExtension
|
|
157
|
+
parent.type === nodeTypes.bodiedExtension ||
|
|
158
|
+
parent.type === nodeTypes.extensionFrame
|
|
154
159
|
);
|
|
155
160
|
};
|
|
156
161
|
|