@seafile/sdoc-editor 0.3.16 → 0.3.17
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/dist/assets/css/simple-editor.css +1 -1
- package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +5 -1
- package/dist/basic-sdk/extension/constants/index.js +1 -1
- package/dist/basic-sdk/extension/constants/menus-config.js +6 -0
- package/dist/basic-sdk/extension/plugins/table/constants/index.js +1 -1
- package/dist/basic-sdk/extension/plugins/table/dialogs/index.js +3 -0
- package/dist/basic-sdk/extension/plugins/table/dialogs/split-cell-setting-dialog.js +99 -0
- package/dist/basic-sdk/extension/plugins/table/helpers.js +324 -1
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/combine-cells.js +32 -0
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/index.css +0 -4
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/index.js +6 -0
- package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/index.js +31 -4
- package/dist/basic-sdk/extension/plugins/table/render/index.css +1 -11
- package/dist/basic-sdk/extension/plugins/table/render/index.js +35 -7
- package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +34 -15
- package/dist/basic-sdk/extension/plugins/table/render/render-row.js +5 -118
- package/dist/basic-sdk/extension/plugins/table/render/resize-handlers/{resize-handler.js → column-resize-handler.js} +2 -2
- package/dist/basic-sdk/extension/plugins/table/render/resize-handlers/index.js +17 -4
- package/dist/basic-sdk/extension/plugins/table/render/resize-handlers/row-resize-handler.js +89 -0
- package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js +12 -13
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +7 -1
- package/public/locales/zh_CN/sdoc-editor.json +7 -1
- /package/dist/basic-sdk/extension/plugins/table/{dialog → dialogs}/custom-table-size-dialog/index.css +0 -0
- /package/dist/basic-sdk/extension/plugins/table/{dialog → dialogs}/custom-table-size-dialog/index.js +0 -0
- /package/dist/basic-sdk/extension/plugins/table/{dialog → dialogs}/custom-table-size-dialog/number-input.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState, useRef } from 'react';
|
|
2
|
-
import CustomTableSizeDialog from '../../plugins/table/
|
|
2
|
+
import { CustomTableSizeDialog, SplitCellSettingDialog } from '../../plugins/table/dialogs';
|
|
3
3
|
import AddLinkDialog from '../../plugins/link/dialog/add-link-dialog';
|
|
4
4
|
import SelectFileDialog from '../select-file-dialog/index.js';
|
|
5
5
|
import EventBus from '../../../utils/event-bus';
|
|
@@ -77,6 +77,10 @@ const InsertElementDialog = _ref => {
|
|
|
77
77
|
{
|
|
78
78
|
return /*#__PURE__*/React.createElement(CustomTableSizeDialog, props);
|
|
79
79
|
}
|
|
80
|
+
case ELEMENT_TYPE.TABLE_CELL:
|
|
81
|
+
{
|
|
82
|
+
return /*#__PURE__*/React.createElement(SplitCellSettingDialog, props);
|
|
83
|
+
}
|
|
80
84
|
case ELEMENT_TYPE.LINK:
|
|
81
85
|
{
|
|
82
86
|
return /*#__PURE__*/React.createElement(AddLinkDialog, props);
|
|
@@ -5,7 +5,7 @@ export { DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, DEFAULT_FONT
|
|
|
5
5
|
export { FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE } from './font';
|
|
6
6
|
export { DIFF_TYPE, ADDED_STYLE, DELETED_STYLE } from './diff-view';
|
|
7
7
|
export { KEYBOARD, MAC_HOTKEYS, WIN_HOTKEYS } from './keyboard';
|
|
8
|
-
export { UNDO, REDO, TEXT_STYLE, TEXT_STYLE_MAP, TEXT_STYLE_MORE, TEXT_ALIGN, REMOVE_TABLE, CLEAR_FORMAT, MENUS_CONFIG_MAP, SIDE_TRANSFORM_MENUS_CONFIG, SIDE_INSERT_MENUS_CONFIG } from './menus-config';
|
|
8
|
+
export { UNDO, REDO, TEXT_STYLE, TEXT_STYLE_MAP, TEXT_STYLE_MORE, TEXT_ALIGN, REMOVE_TABLE, COMBINE_CELL, CLEAR_FORMAT, MENUS_CONFIG_MAP, SIDE_TRANSFORM_MENUS_CONFIG, SIDE_INSERT_MENUS_CONFIG } from './menus-config';
|
|
9
9
|
export const HEADERS = [HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6];
|
|
10
10
|
export const HEADER_TITLE_MAP = {
|
|
11
11
|
[TITLE]: 'Title',
|
|
@@ -4,6 +4,7 @@ export const UNDO = 'undo';
|
|
|
4
4
|
export const REDO = 'redo';
|
|
5
5
|
export const CLEAR_FORMAT = 'clear_format';
|
|
6
6
|
export const REMOVE_TABLE = 'remove_table';
|
|
7
|
+
export const COMBINE_CELL = 'combine_cell';
|
|
7
8
|
|
|
8
9
|
// text style
|
|
9
10
|
export const TEXT_STYLE = 'text_style';
|
|
@@ -89,6 +90,11 @@ export const MENUS_CONFIG_MAP = {
|
|
|
89
90
|
iconClass: 'sdocfont sdoc-delete-table',
|
|
90
91
|
text: 'Delete_table'
|
|
91
92
|
},
|
|
93
|
+
[COMBINE_CELL]: {
|
|
94
|
+
id: "sdoc_".concat(COMBINE_CELL),
|
|
95
|
+
iconClass: 'sdocfont sdoc-merge-cell',
|
|
96
|
+
text: 'Combine_cell'
|
|
97
|
+
},
|
|
92
98
|
[TEXT_STYLE]: [{
|
|
93
99
|
id: ITALIC,
|
|
94
100
|
iconClass: 'sdocfont sdoc-italic',
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Alert, Row, Col, FormGroup, Label, Input } from 'reactstrap';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { getSelectedInfo, splitCell } from '../helpers';
|
|
5
|
+
const SplitCellSettingDialog = _ref => {
|
|
6
|
+
let {
|
|
7
|
+
editor,
|
|
8
|
+
closeDialog
|
|
9
|
+
} = _ref;
|
|
10
|
+
const {
|
|
11
|
+
t
|
|
12
|
+
} = useTranslation();
|
|
13
|
+
const {
|
|
14
|
+
cell
|
|
15
|
+
} = getSelectedInfo(editor);
|
|
16
|
+
const {
|
|
17
|
+
rowspan = 1,
|
|
18
|
+
colspan = 1
|
|
19
|
+
} = cell;
|
|
20
|
+
const [rowNumber, setRowNumber] = useState(rowspan);
|
|
21
|
+
const [columnNumber, setColumnNumber] = useState(colspan);
|
|
22
|
+
const CELL_SPLIT_MAX_ROWS = rowspan;
|
|
23
|
+
const CELL_SPLIT_MAX_COLUMNS = colspan;
|
|
24
|
+
const [errorMessage, setErrorMessage] = useState('');
|
|
25
|
+
const onRowNumberChange = useCallback(e => {
|
|
26
|
+
setRowNumber(e.target.value);
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, []);
|
|
29
|
+
const onColumnNumberChange = useCallback(e => {
|
|
30
|
+
setColumnNumber(e.target.value);
|
|
31
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
32
|
+
}, []);
|
|
33
|
+
const handleSubmit = useCallback(() => {
|
|
34
|
+
const parsedRowNumber = parseInt(rowNumber);
|
|
35
|
+
const parsedColumnNumber = parseInt(columnNumber);
|
|
36
|
+
if (!parsedRowNumber || !parsedColumnNumber || parsedRowNumber < 0 || parsedColumnNumber < 0) {
|
|
37
|
+
setErrorMessage(t('Please_enter_a_non-negative_integer'));
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
let targetRowNumber = parsedRowNumber;
|
|
41
|
+
let targetColumnNumber = parsedColumnNumber;
|
|
42
|
+
if (parsedRowNumber > CELL_SPLIT_MAX_ROWS) {
|
|
43
|
+
targetRowNumber = CELL_SPLIT_MAX_ROWS;
|
|
44
|
+
setRowNumber(targetRowNumber);
|
|
45
|
+
setErrorMessage(t('The_maximum_row_number_is_{number}').replace('{number}', CELL_SPLIT_MAX_ROWS));
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (parsedColumnNumber > CELL_SPLIT_MAX_COLUMNS) {
|
|
49
|
+
targetColumnNumber = CELL_SPLIT_MAX_COLUMNS;
|
|
50
|
+
setColumnNumber(targetColumnNumber);
|
|
51
|
+
setErrorMessage(t('The_maximum_column_number_is_{number}').replace('{number}', CELL_SPLIT_MAX_COLUMNS));
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
splitCell(editor, targetRowNumber, targetColumnNumber);
|
|
55
|
+
closeDialog();
|
|
56
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
57
|
+
}, [rowNumber, columnNumber]);
|
|
58
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
59
|
+
isOpen: true,
|
|
60
|
+
autoFocus: false,
|
|
61
|
+
toggle: closeDialog,
|
|
62
|
+
zIndex: 1071,
|
|
63
|
+
returnFocusAfterClose: true
|
|
64
|
+
}, /*#__PURE__*/React.createElement(ModalHeader, {
|
|
65
|
+
toggle: closeDialog
|
|
66
|
+
}, t('Split_cell')), /*#__PURE__*/React.createElement(ModalBody, null, /*#__PURE__*/React.createElement(Row, null, /*#__PURE__*/React.createElement(Col, {
|
|
67
|
+
md: 6
|
|
68
|
+
}, /*#__PURE__*/React.createElement(FormGroup, null, /*#__PURE__*/React.createElement(Label, {
|
|
69
|
+
for: "row-number"
|
|
70
|
+
}, t('Row_number')), /*#__PURE__*/React.createElement(Input, {
|
|
71
|
+
id: "row-number",
|
|
72
|
+
name: "row-number",
|
|
73
|
+
type: "number",
|
|
74
|
+
min: 1,
|
|
75
|
+
value: rowNumber,
|
|
76
|
+
onChange: onRowNumberChange
|
|
77
|
+
}))), /*#__PURE__*/React.createElement(Col, {
|
|
78
|
+
md: 6
|
|
79
|
+
}, /*#__PURE__*/React.createElement(FormGroup, null, /*#__PURE__*/React.createElement(Label, {
|
|
80
|
+
for: "column-number"
|
|
81
|
+
}, t('Column_number')), /*#__PURE__*/React.createElement(Input, {
|
|
82
|
+
id: "column-number",
|
|
83
|
+
name: "column-number",
|
|
84
|
+
type: "number",
|
|
85
|
+
min: 1,
|
|
86
|
+
value: columnNumber,
|
|
87
|
+
onChange: onColumnNumberChange
|
|
88
|
+
})))), errorMessage && /*#__PURE__*/React.createElement(Alert, {
|
|
89
|
+
className: "mt-2 mb-0",
|
|
90
|
+
color: "danger"
|
|
91
|
+
}, t(errorMessage))), /*#__PURE__*/React.createElement(ModalFooter, null, /*#__PURE__*/React.createElement(Button, {
|
|
92
|
+
color: "secondary",
|
|
93
|
+
onClick: closeDialog
|
|
94
|
+
}, t('Cancel')), /*#__PURE__*/React.createElement(Button, {
|
|
95
|
+
color: "primary",
|
|
96
|
+
onClick: handleSubmit
|
|
97
|
+
}, t('Submit'))));
|
|
98
|
+
};
|
|
99
|
+
export default SplitCellSettingDialog;
|
|
@@ -41,6 +41,18 @@ export const isTableMenuDisabled = (editor, readonly) => {
|
|
|
41
41
|
if (match) return true;
|
|
42
42
|
return false;
|
|
43
43
|
};
|
|
44
|
+
export const isCombineCellsDisabled = (editor, readonly) => {
|
|
45
|
+
if (readonly) return true;
|
|
46
|
+
const {
|
|
47
|
+
selection,
|
|
48
|
+
tableSelectedRange
|
|
49
|
+
} = editor;
|
|
50
|
+
if (!selection) return true;
|
|
51
|
+
if (!ObjectUtils.isSameObject(tableSelectedRange, EMPTY_SELECTED_RANGE)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
};
|
|
44
56
|
export const generateTableCell = () => {
|
|
45
57
|
return {
|
|
46
58
|
id: slugid.nice(),
|
|
@@ -99,9 +111,13 @@ export const generateEmptyTable = (editor, tableProps) => {
|
|
|
99
111
|
type: ELEMENT_TYPE.TABLE,
|
|
100
112
|
children: children,
|
|
101
113
|
columns,
|
|
102
|
-
|
|
114
|
+
ui: {
|
|
103
115
|
alternate_highlight,
|
|
104
116
|
alternate_highlight_color
|
|
117
|
+
},
|
|
118
|
+
style: {
|
|
119
|
+
gridTemplateColumns: "repeat(".concat(colsCount, ", ").concat(columnWidth, "px)"),
|
|
120
|
+
gridAutoRows: "minmax(".concat(TABLE_ROW_MIN_HEIGHT, "px, auto)")
|
|
105
121
|
}
|
|
106
122
|
};
|
|
107
123
|
};
|
|
@@ -219,6 +235,61 @@ export const insertTableRow = function (editor, table, rowIndex) {
|
|
|
219
235
|
});
|
|
220
236
|
const focusPath = [...targetPath, 0];
|
|
221
237
|
focusEditor(editor, focusPath);
|
|
238
|
+
|
|
239
|
+
// handle cells with the rowspan > 1
|
|
240
|
+
if (position === TABLE_ELEMENT_POSITION.AFTER) {
|
|
241
|
+
handleCombinedCellsAfterInsertTableRow(editor, tablePath, table, rowIndex);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
export const handleCombinedCellsAfterInsertTableRow = (editor, tablePath, table, rowIndex) => {
|
|
245
|
+
// important background info: the new row is inserted after rowIndex
|
|
246
|
+
const cells = table.children[rowIndex].children;
|
|
247
|
+
for (let i = 0, len = cells.length; i < len; i++) {
|
|
248
|
+
const {
|
|
249
|
+
is_combined,
|
|
250
|
+
rowspan,
|
|
251
|
+
colspan
|
|
252
|
+
} = cells[i];
|
|
253
|
+
if (is_combined) {
|
|
254
|
+
for (let ri = rowIndex - 1; ri >= 0; ri--) {
|
|
255
|
+
const {
|
|
256
|
+
is_combined: ri_is_combined,
|
|
257
|
+
rowspan: ri_rowspan,
|
|
258
|
+
colspan: ri_colspan
|
|
259
|
+
} = table.children[ri].children[i];
|
|
260
|
+
if (!ri_is_combined && ri + ri_rowspan - 1 > rowIndex) {
|
|
261
|
+
Transforms.setNodes(editor, {
|
|
262
|
+
rowspan: ri_rowspan + 1
|
|
263
|
+
}, {
|
|
264
|
+
at: [...tablePath, ri, i]
|
|
265
|
+
});
|
|
266
|
+
for (let j = 0; j < ri_colspan; j++) {
|
|
267
|
+
Transforms.setNodes(editor, {
|
|
268
|
+
'is_combined': true
|
|
269
|
+
}, {
|
|
270
|
+
at: [...tablePath, rowIndex + 1, i + j]
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
if (rowspan > 1) {
|
|
278
|
+
Transforms.setNodes(editor, {
|
|
279
|
+
rowspan: rowspan + 1
|
|
280
|
+
}, {
|
|
281
|
+
at: [...tablePath, rowIndex, i]
|
|
282
|
+
});
|
|
283
|
+
for (let j = 0; j < colspan; j++) {
|
|
284
|
+
Transforms.setNodes(editor, {
|
|
285
|
+
'is_combined': true
|
|
286
|
+
}, {
|
|
287
|
+
at: [...tablePath, rowIndex + 1, i + j]
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
222
293
|
};
|
|
223
294
|
export const insertTableColumn = function (editor, table, columnIndex) {
|
|
224
295
|
let position = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : TABLE_ELEMENT_POSITION.AFTER;
|
|
@@ -238,6 +309,60 @@ export const insertTableColumn = function (editor, table, columnIndex) {
|
|
|
238
309
|
}
|
|
239
310
|
const focusPath = [...tablePath, 0, newCellIndex, 0];
|
|
240
311
|
focusEditor(editor, focusPath);
|
|
312
|
+
|
|
313
|
+
// handle cells with the colspan > 1
|
|
314
|
+
if (position === TABLE_ELEMENT_POSITION.AFTER) {
|
|
315
|
+
handleCombinedCellsAfterInsertTableColumn(editor, tablePath, table, columnIndex);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
export const handleCombinedCellsAfterInsertTableColumn = (editor, tablePath, table, columnIndex) => {
|
|
319
|
+
// important background info: the new column is inserted after columnIndex
|
|
320
|
+
for (let i = 0, len = table.children.length; i < len; i++) {
|
|
321
|
+
const {
|
|
322
|
+
is_combined,
|
|
323
|
+
rowspan,
|
|
324
|
+
colspan
|
|
325
|
+
} = table.children[i].children[columnIndex];
|
|
326
|
+
if (is_combined) {
|
|
327
|
+
for (let ci = columnIndex - 1; ci >= 0; ci--) {
|
|
328
|
+
const {
|
|
329
|
+
is_combined: ci_is_combined,
|
|
330
|
+
rowspan: ci_rowspan,
|
|
331
|
+
colspan: ci_colspan
|
|
332
|
+
} = table.children[i].children[ci];
|
|
333
|
+
if (!ci_is_combined && ci + ci_colspan - 1 > columnIndex) {
|
|
334
|
+
Transforms.setNodes(editor, {
|
|
335
|
+
colspan: ci_colspan + 1
|
|
336
|
+
}, {
|
|
337
|
+
at: [...tablePath, i, ci]
|
|
338
|
+
});
|
|
339
|
+
for (let j = 0; j < ci_rowspan; j++) {
|
|
340
|
+
Transforms.setNodes(editor, {
|
|
341
|
+
'is_combined': true
|
|
342
|
+
}, {
|
|
343
|
+
at: [...tablePath, i + j, columnIndex + 1]
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
if (colspan > 1) {
|
|
351
|
+
Transforms.setNodes(editor, {
|
|
352
|
+
colspan: colspan + 1
|
|
353
|
+
}, {
|
|
354
|
+
at: [...tablePath, i, columnIndex]
|
|
355
|
+
});
|
|
356
|
+
for (let j = 0; j < rowspan; j++) {
|
|
357
|
+
Transforms.setNodes(editor, {
|
|
358
|
+
'is_combined': true
|
|
359
|
+
}, {
|
|
360
|
+
at: [...tablePath, i + j, columnIndex + 1]
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
241
366
|
};
|
|
242
367
|
export const insertTableElement = function (editor, type) {
|
|
243
368
|
let position = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : TABLE_ELEMENT_POSITION.AFTER;
|
|
@@ -260,6 +385,12 @@ export const insertTableElement = function (editor, type) {
|
|
|
260
385
|
Transforms.insertNodes(editor, row, {
|
|
261
386
|
at: targetPath
|
|
262
387
|
});
|
|
388
|
+
// handle combined cells
|
|
389
|
+
if (!(rowIndex == 0 && position === TABLE_ELEMENT_POSITION.BEFORE)) {
|
|
390
|
+
const targetRowIndex = position === TABLE_ELEMENT_POSITION.AFTER ? rowIndex : rowIndex - 1;
|
|
391
|
+
const currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
|
|
392
|
+
handleCombinedCellsAfterInsertTableRow(editor, tablePath, currentTable, targetRowIndex);
|
|
393
|
+
}
|
|
263
394
|
}
|
|
264
395
|
const focusPath = [...targetPath, cellIndex];
|
|
265
396
|
focusEditor(editor, focusPath);
|
|
@@ -279,12 +410,121 @@ export const insertTableElement = function (editor, type) {
|
|
|
279
410
|
at: newCellPath
|
|
280
411
|
});
|
|
281
412
|
}
|
|
413
|
+
// handle combined cells
|
|
414
|
+
if (!(cellIndex == 0 && position === TABLE_ELEMENT_POSITION.BEFORE)) {
|
|
415
|
+
const targetColumnIndex = position === TABLE_ELEMENT_POSITION.AFTER ? cellIndex : cellIndex - 1;
|
|
416
|
+
const currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
|
|
417
|
+
handleCombinedCellsAfterInsertTableColumn(editor, tablePath, currentTable, targetColumnIndex);
|
|
418
|
+
}
|
|
282
419
|
}
|
|
283
420
|
const focusPath = [...tablePath, rowIndex, cellIndex + 1, 0];
|
|
284
421
|
focusEditor(editor, focusPath);
|
|
285
422
|
return;
|
|
286
423
|
}
|
|
287
424
|
};
|
|
425
|
+
export const combineCells = editor => {
|
|
426
|
+
const {
|
|
427
|
+
tablePath
|
|
428
|
+
} = getSelectedInfo(editor);
|
|
429
|
+
const {
|
|
430
|
+
minColIndex,
|
|
431
|
+
maxColIndex,
|
|
432
|
+
minRowIndex,
|
|
433
|
+
maxRowIndex
|
|
434
|
+
} = editor.tableSelectedRange;
|
|
435
|
+
let newCellContent = [];
|
|
436
|
+
for (let i = minRowIndex; i < maxRowIndex + 1; i++) {
|
|
437
|
+
for (let j = minColIndex; j < maxColIndex + 1; j++) {
|
|
438
|
+
let nodePath = [...tablePath, i, j];
|
|
439
|
+
let node = Editor.node(editor, nodePath);
|
|
440
|
+
if (node[0].is_combined) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
Transforms.setNodes(editor, {
|
|
444
|
+
'is_combined': true
|
|
445
|
+
}, {
|
|
446
|
+
at: nodePath
|
|
447
|
+
});
|
|
448
|
+
newCellContent = newCellContent.concat(node[0].children);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
const targetCellPath = [...tablePath, minRowIndex, minColIndex];
|
|
452
|
+
const newCell = generateTableCell();
|
|
453
|
+
newCell.children = newCellContent;
|
|
454
|
+
newCell.rowspan = maxRowIndex - minRowIndex + 1;
|
|
455
|
+
newCell.colspan = maxColIndex - minColIndex + 1;
|
|
456
|
+
// keep row.chilren.length not changed
|
|
457
|
+
Transforms.removeNodes(editor, {
|
|
458
|
+
at: targetCellPath
|
|
459
|
+
});
|
|
460
|
+
Transforms.insertNodes(editor, newCell, {
|
|
461
|
+
at: targetCellPath
|
|
462
|
+
});
|
|
463
|
+
focusEditor(editor, targetCellPath);
|
|
464
|
+
|
|
465
|
+
// for clicking the 'combine cell' icon in the toolbar
|
|
466
|
+
const eventBus = EventBus.getInstance();
|
|
467
|
+
eventBus.dispatch(INTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE);
|
|
468
|
+
};
|
|
469
|
+
export const splitCell = (editor, rowNumber, columnNumber) => {
|
|
470
|
+
if (rowNumber == 1 && columnNumber == 1) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
const {
|
|
474
|
+
cell,
|
|
475
|
+
rowIndex,
|
|
476
|
+
cellIndex,
|
|
477
|
+
cellPath,
|
|
478
|
+
tablePath
|
|
479
|
+
} = getSelectedInfo(editor);
|
|
480
|
+
const {
|
|
481
|
+
rowspan,
|
|
482
|
+
colspan
|
|
483
|
+
} = cell;
|
|
484
|
+
const rowspanBase = Math.floor(rowspan / rowNumber);
|
|
485
|
+
const rowspanLeft = rowspan % rowNumber;
|
|
486
|
+
const colspanBase = Math.floor(colspan / columnNumber);
|
|
487
|
+
const colspanLeft = colspan % columnNumber;
|
|
488
|
+
const cellNumber = rowNumber * columnNumber;
|
|
489
|
+
const dataBlockNumber = Math.ceil(cell.children.length / cellNumber);
|
|
490
|
+
let firstNewCell;
|
|
491
|
+
let rowspanSum = 0;
|
|
492
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
493
|
+
let newRowSpan = rowspanBase + (i + 1 <= rowspanLeft ? 1 : 0);
|
|
494
|
+
let colspanSum = 0;
|
|
495
|
+
for (let j = 0; j < columnNumber; j++) {
|
|
496
|
+
const newCell = generateTableCell();
|
|
497
|
+
let startIndex = (i * columnNumber + j) * dataBlockNumber;
|
|
498
|
+
if (startIndex < cell.children.length) {
|
|
499
|
+
let endIndex = Math.min(startIndex + dataBlockNumber, cell.children.length);
|
|
500
|
+
newCell.children = cell.children.slice(startIndex, endIndex);
|
|
501
|
+
}
|
|
502
|
+
newCell.rowspan = newRowSpan;
|
|
503
|
+
newCell.colspan = colspanBase + (j + 1 <= colspanLeft ? 1 : 0);
|
|
504
|
+
const newRowIndex = rowIndex + rowspanSum;
|
|
505
|
+
const newCellIndex = cellIndex + colspanSum;
|
|
506
|
+
const targetCellPath = [...tablePath, newRowIndex, newCellIndex];
|
|
507
|
+
if (i == 0 && j == 0) {
|
|
508
|
+
firstNewCell = newCell;
|
|
509
|
+
} else {
|
|
510
|
+
Transforms.removeNodes(editor, {
|
|
511
|
+
at: targetCellPath
|
|
512
|
+
});
|
|
513
|
+
Transforms.insertNodes(editor, newCell, {
|
|
514
|
+
at: targetCellPath
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
colspanSum += newCell.colspan;
|
|
518
|
+
}
|
|
519
|
+
rowspanSum += newRowSpan;
|
|
520
|
+
}
|
|
521
|
+
Transforms.removeNodes(editor, {
|
|
522
|
+
at: cellPath
|
|
523
|
+
});
|
|
524
|
+
Transforms.insertNodes(editor, firstNewCell, {
|
|
525
|
+
at: cellPath
|
|
526
|
+
});
|
|
527
|
+
};
|
|
288
528
|
export const removeTable = (editor, path) => {
|
|
289
529
|
let validPath = path;
|
|
290
530
|
if (!validPath) {
|
|
@@ -336,6 +576,7 @@ export const removeTableElement = (editor, type) => {
|
|
|
336
576
|
focusEditor(editor, focusPath);
|
|
337
577
|
return;
|
|
338
578
|
}
|
|
579
|
+
handleCombinedCellsBeforeDeleteTableRow(editor, tablePath, table, rowIndex);
|
|
339
580
|
Transforms.removeNodes(editor, {
|
|
340
581
|
at: rowPath
|
|
341
582
|
});
|
|
@@ -378,6 +619,7 @@ export const removeTableElement = (editor, type) => {
|
|
|
378
619
|
const newColumns = columns.slice(0);
|
|
379
620
|
newColumns.splice(cellIndex, 1);
|
|
380
621
|
updateColumnWidth(editor, table, newColumns);
|
|
622
|
+
handleCombinedCellsBeforeDeleteTableColumn(editor, tablePath, table, cellIndex);
|
|
381
623
|
for (let i = 0; i < tableSize[0]; i++) {
|
|
382
624
|
const cellPath = [...tablePath, i, cellIndex];
|
|
383
625
|
Transforms.removeNodes(editor, {
|
|
@@ -390,6 +632,87 @@ export const removeTableElement = (editor, type) => {
|
|
|
390
632
|
return;
|
|
391
633
|
}
|
|
392
634
|
};
|
|
635
|
+
|
|
636
|
+
// handle combined cells before deleting a row
|
|
637
|
+
export const handleCombinedCellsBeforeDeleteTableRow = (editor, tablePath, table, rowIndex) => {
|
|
638
|
+
const cells = table.children[rowIndex].children;
|
|
639
|
+
for (let i = 0, len = cells.length; i < len; i++) {
|
|
640
|
+
const {
|
|
641
|
+
is_combined,
|
|
642
|
+
rowspan,
|
|
643
|
+
colspan
|
|
644
|
+
} = cells[i];
|
|
645
|
+
if (is_combined) {
|
|
646
|
+
for (let ri = rowIndex - 1; ri >= 0; ri--) {
|
|
647
|
+
const {
|
|
648
|
+
is_combined: ri_is_combined,
|
|
649
|
+
rowspan: ri_rowspan
|
|
650
|
+
} = table.children[ri].children[i];
|
|
651
|
+
if (!ri_is_combined && ri + ri_rowspan - 1 >= rowIndex) {
|
|
652
|
+
Transforms.setNodes(editor, {
|
|
653
|
+
rowspan: ri_rowspan - 1
|
|
654
|
+
}, {
|
|
655
|
+
at: [...tablePath, ri, i]
|
|
656
|
+
});
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
} else {
|
|
661
|
+
if (rowspan > 1) {
|
|
662
|
+
const targetCellPath = [...tablePath, rowIndex + 1, i];
|
|
663
|
+
const newCell = generateTableCell();
|
|
664
|
+
newCell.rowspan = rowspan - 1;
|
|
665
|
+
newCell.colspan = colspan;
|
|
666
|
+
Transforms.removeNodes(editor, {
|
|
667
|
+
at: targetCellPath
|
|
668
|
+
});
|
|
669
|
+
Transforms.insertNodes(editor, newCell, {
|
|
670
|
+
at: targetCellPath
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// handle combined cells before deleting a column
|
|
678
|
+
export const handleCombinedCellsBeforeDeleteTableColumn = (editor, tablePath, table, columnIndex) => {
|
|
679
|
+
for (let i = 0, len = table.children.length; i < len; i++) {
|
|
680
|
+
const {
|
|
681
|
+
is_combined,
|
|
682
|
+
rowspan,
|
|
683
|
+
colspan
|
|
684
|
+
} = table.children[i].children[columnIndex];
|
|
685
|
+
if (is_combined) {
|
|
686
|
+
for (let ci = columnIndex - 1; ci >= 0; ci--) {
|
|
687
|
+
const {
|
|
688
|
+
is_combined: ci_is_combined,
|
|
689
|
+
colspan: ci_colspan
|
|
690
|
+
} = table.children[i].children[ci];
|
|
691
|
+
if (!ci_is_combined && ci + ci_colspan - 1 >= columnIndex) {
|
|
692
|
+
Transforms.setNodes(editor, {
|
|
693
|
+
colspan: ci_colspan - 1
|
|
694
|
+
}, {
|
|
695
|
+
at: [...tablePath, i, ci]
|
|
696
|
+
});
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
} else {
|
|
701
|
+
if (colspan > 1) {
|
|
702
|
+
const targetCellPath = [...tablePath, i, columnIndex + 1];
|
|
703
|
+
const newCell = generateTableCell();
|
|
704
|
+
newCell.rowspan = rowspan;
|
|
705
|
+
newCell.colspan = colspan - 1;
|
|
706
|
+
Transforms.removeNodes(editor, {
|
|
707
|
+
at: targetCellPath
|
|
708
|
+
});
|
|
709
|
+
Transforms.insertNodes(editor, newCell, {
|
|
710
|
+
at: targetCellPath
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
};
|
|
393
716
|
export const setTableSelectedRange = (editor, range) => {
|
|
394
717
|
if (range) {
|
|
395
718
|
editor.tableSelectedRange = range;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { MenuItem } from '../../../../commons';
|
|
4
|
+
import { MENUS_CONFIG_MAP, COMBINE_CELL } from '../../../../constants';
|
|
5
|
+
import { isCombineCellsDisabled, combineCells } from '../../helpers';
|
|
6
|
+
const CombineCells = _ref => {
|
|
7
|
+
let {
|
|
8
|
+
isRichEditor,
|
|
9
|
+
className,
|
|
10
|
+
editor,
|
|
11
|
+
readonly
|
|
12
|
+
} = _ref;
|
|
13
|
+
const [disabled, setDisabled] = useState(false);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const disabled = isCombineCellsDisabled(editor, readonly);
|
|
16
|
+
setDisabled(disabled);
|
|
17
|
+
}, [editor, editor.tableSelectedRange, readonly]);
|
|
18
|
+
const _combineCells = useCallback(() => {
|
|
19
|
+
if (readonly) return;
|
|
20
|
+
combineCells(editor);
|
|
21
|
+
}, [editor, readonly]);
|
|
22
|
+
const menuConfig = MENUS_CONFIG_MAP[COMBINE_CELL];
|
|
23
|
+
const props = _objectSpread(_objectSpread({
|
|
24
|
+
isRichEditor,
|
|
25
|
+
disabled: disabled,
|
|
26
|
+
isActive: false
|
|
27
|
+
}, menuConfig), {}, {
|
|
28
|
+
onMouseDown: _combineCells
|
|
29
|
+
});
|
|
30
|
+
return /*#__PURE__*/React.createElement(MenuItem, props);
|
|
31
|
+
};
|
|
32
|
+
export default CombineCells;
|
|
@@ -4,6 +4,7 @@ import { MenuGroup } from '../../../../commons';
|
|
|
4
4
|
import { isAllInTable } from '../../helpers';
|
|
5
5
|
import CellBackgroundColorMenu from './cell-bg-color-menu';
|
|
6
6
|
import CellTextAlignMenu from './cell-text-align-menu';
|
|
7
|
+
import CombineCells from './combine-cells';
|
|
7
8
|
import RemoveTable from './remove-table-menu';
|
|
8
9
|
import TableColumnMenu from './table-column-menu';
|
|
9
10
|
import TableRowMenu from './table-row-menu';
|
|
@@ -32,6 +33,11 @@ const ActiveTableMenu = _ref => {
|
|
|
32
33
|
isRichEditor: isRichEditor,
|
|
33
34
|
className: className,
|
|
34
35
|
readonly: readonly
|
|
36
|
+
}), /*#__PURE__*/React.createElement(CombineCells, {
|
|
37
|
+
editor: editor,
|
|
38
|
+
isRichEditor: isRichEditor,
|
|
39
|
+
className: className,
|
|
40
|
+
readonly: readonly
|
|
35
41
|
}), /*#__PURE__*/React.createElement(RemoveTable, {
|
|
36
42
|
editor: editor,
|
|
37
43
|
isRichEditor: isRichEditor,
|
|
@@ -4,9 +4,11 @@ import ObjectUtils from '../../../../../utils/object-utils';
|
|
|
4
4
|
import { ElementPopover } from '../../../../commons';
|
|
5
5
|
import { ELEMENT_TYPE } from '../../../../constants';
|
|
6
6
|
import { getSelectedNodeByType } from '../../../../core';
|
|
7
|
-
import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from '../../constants';
|
|
8
|
-
import { insertTableElement, removeTableElement } from '../../helpers';
|
|
7
|
+
import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, EMPTY_SELECTED_RANGE } from '../../constants';
|
|
8
|
+
import { insertTableElement, removeTableElement, getSelectedInfo, combineCells } from '../../helpers';
|
|
9
9
|
import InsertTableElement from './insert-table-element';
|
|
10
|
+
import EventBus from '../../../../../utils/event-bus';
|
|
11
|
+
import { INTERNAL_EVENT } from '../../../../../constants';
|
|
10
12
|
import './index.css';
|
|
11
13
|
class TableContextMenu extends React.Component {
|
|
12
14
|
constructor(props) {
|
|
@@ -51,10 +53,22 @@ class TableContextMenu extends React.Component {
|
|
|
51
53
|
className: "dropdown-item"
|
|
52
54
|
}, this.props.t(title));
|
|
53
55
|
};
|
|
56
|
+
this.combineCells = () => {
|
|
57
|
+
const {
|
|
58
|
+
editor
|
|
59
|
+
} = this.props;
|
|
60
|
+
combineCells(editor);
|
|
61
|
+
};
|
|
62
|
+
this.toggleSplitCellSettingDialog = () => {
|
|
63
|
+
this.eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
|
|
64
|
+
type: ELEMENT_TYPE.TABLE_CELL
|
|
65
|
+
});
|
|
66
|
+
};
|
|
54
67
|
this.state = {
|
|
55
68
|
contextStyle: {}
|
|
56
69
|
};
|
|
57
70
|
this.position = null;
|
|
71
|
+
this.eventBus = EventBus.getInstance();
|
|
58
72
|
}
|
|
59
73
|
componentDidMount() {
|
|
60
74
|
this.position = this.props.contextMenuPosition;
|
|
@@ -75,7 +89,8 @@ class TableContextMenu extends React.Component {
|
|
|
75
89
|
contextStyle
|
|
76
90
|
} = this.state;
|
|
77
91
|
const {
|
|
78
|
-
editor
|
|
92
|
+
editor,
|
|
93
|
+
t
|
|
79
94
|
} = this.props;
|
|
80
95
|
const currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
|
|
81
96
|
if (!currentTable) return null;
|
|
@@ -89,6 +104,8 @@ class TableContextMenu extends React.Component {
|
|
|
89
104
|
const selectedCols = tableSelectedRange.maxColIndex - tableSelectedRange.minColIndex + 1;
|
|
90
105
|
const canAddRowsCount = currentRowsCount + selectedRows > TABLE_MAX_ROWS ? TABLE_MAX_ROWS - currentRowsCount : selectedRows;
|
|
91
106
|
const canAddColsCount = currentColumnsCount + selectedCols > TABLE_MAX_COLUMNS ? TABLE_MAX_COLUMNS - currentColumnsCount : selectedCols;
|
|
107
|
+
const enableCombineCell = !ObjectUtils.isSameObject(tableSelectedRange, EMPTY_SELECTED_RANGE);
|
|
108
|
+
const enableSplitCell = !enableCombineCell;
|
|
92
109
|
return /*#__PURE__*/React.createElement(ElementPopover, {
|
|
93
110
|
className: "sdoc-context-menu"
|
|
94
111
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -121,7 +138,17 @@ class TableContextMenu extends React.Component {
|
|
|
121
138
|
insertTableElement: this.insertTableElement
|
|
122
139
|
}), /*#__PURE__*/React.createElement("div", {
|
|
123
140
|
className: 'seafile-divider dropdown-divider'
|
|
124
|
-
}), this.renderRemoveBtn(TABLE_ELEMENT.ROW, 'Delete_row'), this.renderRemoveBtn(TABLE_ELEMENT.COLUMN, 'Delete_column'), this.renderRemoveBtn(TABLE_ELEMENT.TABLE, 'Delete_table')
|
|
141
|
+
}), this.renderRemoveBtn(TABLE_ELEMENT.ROW, 'Delete_row'), this.renderRemoveBtn(TABLE_ELEMENT.COLUMN, 'Delete_column'), this.renderRemoveBtn(TABLE_ELEMENT.TABLE, 'Delete_table'), /*#__PURE__*/React.createElement("div", {
|
|
142
|
+
className: 'seafile-divider dropdown-divider'
|
|
143
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
144
|
+
className: "dropdown-item",
|
|
145
|
+
disabled: !enableCombineCell,
|
|
146
|
+
onMouseDown: this.combineCells
|
|
147
|
+
}, t('Combine_cell')), /*#__PURE__*/React.createElement("button", {
|
|
148
|
+
className: "dropdown-item",
|
|
149
|
+
disabled: !enableSplitCell,
|
|
150
|
+
onMouseDown: this.toggleSplitCellSettingDialog
|
|
151
|
+
}, t('Split_cell'))));
|
|
125
152
|
}
|
|
126
153
|
}
|
|
127
154
|
export default withTranslation('sdoc-editor')(TableContextMenu);
|
|
@@ -40,18 +40,16 @@
|
|
|
40
40
|
|
|
41
41
|
.sdoc-table-wrapper .sdoc-table-container {
|
|
42
42
|
width: fit-content;
|
|
43
|
-
display:
|
|
43
|
+
display: grid;
|
|
44
44
|
overflow: hidden;
|
|
45
45
|
cursor: text;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
.sdoc-table-wrapper .table-row {
|
|
49
|
-
display: table-row ;
|
|
50
49
|
height: auto;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
.sdoc-table-wrapper .table-cell {
|
|
54
|
-
display: table-cell;
|
|
55
53
|
padding: 10px 10px;
|
|
56
54
|
border-right: 1px solid #ccc;
|
|
57
55
|
border-bottom: 1px solid #ccc;
|
|
@@ -59,14 +57,6 @@
|
|
|
59
57
|
vertical-align: top;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
.sdoc-table-wrapper .table-row:first-child .table-cell {
|
|
63
|
-
border-top: 1px solid #ddd;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.sdoc-table-wrapper .table-row .table-cell:first-child {
|
|
67
|
-
border-left: 1px solid #ddd;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
60
|
.sdoc-table-wrapper .cell-selected {
|
|
71
61
|
caret-color: transparent;
|
|
72
62
|
position: relative;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
1
2
|
import React, { useRef, useState, useEffect, useCallback } from 'react';
|
|
2
3
|
import classnames from 'classnames';
|
|
3
4
|
import throttle from 'lodash.throttle';
|
|
@@ -7,7 +8,7 @@ import { EMPTY_SELECTED_RANGE, TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from '../co
|
|
|
7
8
|
import { ResizeHandlersContext, TableSelectedRangeContext, SettingSelectRangeContext } from './hooks';
|
|
8
9
|
import EventBus from '../../../../utils/event-bus';
|
|
9
10
|
import { INTERNAL_EVENT } from '../../../../constants';
|
|
10
|
-
import { getTableColumns, setTableSelectedRange, getFirstTableCell } from '../helpers';
|
|
11
|
+
import { getTableColumns, setTableSelectedRange, getFirstTableCell, getRowHeight } from '../helpers';
|
|
11
12
|
import ObjectUtils from '../../../../utils/object-utils';
|
|
12
13
|
import ResizeHandlers from './resize-handlers';
|
|
13
14
|
import { registerResizeEvents, unregisterResizeEvents } from '../../../../utils/mouse-event';
|
|
@@ -17,7 +18,7 @@ import { findPath } from '../../../core';
|
|
|
17
18
|
import './index.css';
|
|
18
19
|
import './alternate-color.css';
|
|
19
20
|
const Table = _ref => {
|
|
20
|
-
var _element$
|
|
21
|
+
var _element$ui, _element$ui2;
|
|
21
22
|
let {
|
|
22
23
|
className,
|
|
23
24
|
attributes,
|
|
@@ -29,6 +30,8 @@ const Table = _ref => {
|
|
|
29
30
|
const table = useRef(null);
|
|
30
31
|
const [startRowIndex, setStartRowIndex] = useState(0);
|
|
31
32
|
const [startColIndex, setStartColIndex] = useState(0);
|
|
33
|
+
const [startRowSpan, setStartRowSpan] = useState(1);
|
|
34
|
+
const [startColSpan, setStartColSpan] = useState(1);
|
|
32
35
|
const [isSettingSelectRange, setIsSettingSelectRange] = useState(false);
|
|
33
36
|
const [selectedRange, setSelectedRange] = useState(EMPTY_SELECTED_RANGE);
|
|
34
37
|
const oldColumns = getTableColumns(editor, element);
|
|
@@ -38,8 +41,11 @@ const Table = _ref => {
|
|
|
38
41
|
if (event.button !== 0) return; // right click not deal
|
|
39
42
|
setIsSettingSelectRange(true);
|
|
40
43
|
const tableCell = getFirstTableCell(event.target);
|
|
44
|
+
const cellData = tableCell.style.gridArea.split(' / ');
|
|
41
45
|
setStartRowIndex(Number(tableCell.getAttribute('row-index')));
|
|
42
46
|
setStartColIndex(Number(tableCell.getAttribute('cell-index')));
|
|
47
|
+
setStartRowSpan(Number(cellData[2].split(' ')[1]));
|
|
48
|
+
setStartColSpan(Number(cellData[3].split(' ')[1]));
|
|
43
49
|
setSelectedRange(EMPTY_SELECTED_RANGE);
|
|
44
50
|
setTableSelectedRange(editor, EMPTY_SELECTED_RANGE);
|
|
45
51
|
|
|
@@ -49,6 +55,8 @@ const Table = _ref => {
|
|
|
49
55
|
setIsSettingSelectRange(false);
|
|
50
56
|
setStartColIndex(0);
|
|
51
57
|
setStartRowIndex(0);
|
|
58
|
+
setStartRowSpan(1);
|
|
59
|
+
setStartColSpan(1);
|
|
52
60
|
|
|
53
61
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
62
|
}, []);
|
|
@@ -74,11 +82,14 @@ const Table = _ref => {
|
|
|
74
82
|
const tableCell = getFirstTableCell(event.target);
|
|
75
83
|
const endRowIndex = Number(tableCell.getAttribute('row-index'));
|
|
76
84
|
const endColIndex = Number(tableCell.getAttribute('cell-index'));
|
|
85
|
+
const cellData = tableCell.style.gridArea.split(' / ');
|
|
86
|
+
const endRowSpan = Number(cellData[2].split(' ')[1]);
|
|
87
|
+
const endColSpan = Number(cellData[3].split(' ')[1]);
|
|
77
88
|
const newSelectedRange = {
|
|
78
89
|
minRowIndex: Math.min(startRowIndex, endRowIndex),
|
|
79
|
-
maxRowIndex:
|
|
90
|
+
maxRowIndex: startRowIndex < endRowIndex ? endRowIndex + endRowSpan - 1 : startRowIndex + startRowSpan - 1,
|
|
80
91
|
minColIndex: Math.min(startColIndex, endColIndex),
|
|
81
|
-
maxColIndex:
|
|
92
|
+
maxColIndex: startColIndex < endColIndex ? endColIndex + endColSpan - 1 : startColIndex + startColSpan - 1
|
|
82
93
|
};
|
|
83
94
|
if (!ObjectUtils.isSameObject(selectedRange, EMPTY_SELECTED_RANGE)) {
|
|
84
95
|
event.preventDefault();
|
|
@@ -97,14 +108,18 @@ const Table = _ref => {
|
|
|
97
108
|
// same cell
|
|
98
109
|
if (newSelectedRange.minRowIndex === newSelectedRange.maxRowIndex && newSelectedRange.minColIndex === newSelectedRange.maxColIndex) {
|
|
99
110
|
setSelectedRange(EMPTY_SELECTED_RANGE);
|
|
111
|
+
setTableSelectedRange(editor, EMPTY_SELECTED_RANGE);
|
|
100
112
|
return;
|
|
101
113
|
}
|
|
102
114
|
setSelectedRange(newSelectedRange);
|
|
115
|
+
setTableSelectedRange(editor, newSelectedRange);
|
|
103
116
|
}, 200);
|
|
104
117
|
const onMouseUp = event => {
|
|
118
|
+
/*
|
|
105
119
|
if (!ObjectUtils.isSameObject(selectedRange, EMPTY_SELECTED_RANGE)) {
|
|
106
120
|
setTableSelectedRange(editor, selectedRange);
|
|
107
121
|
}
|
|
122
|
+
*/
|
|
108
123
|
resetState();
|
|
109
124
|
};
|
|
110
125
|
registerResizeEvents({
|
|
@@ -157,6 +172,11 @@ const Table = _ref => {
|
|
|
157
172
|
'sdoc-table-selected': isSelected,
|
|
158
173
|
'sdoc-table-selected-range': !ObjectUtils.isSameObject(selectedRange, EMPTY_SELECTED_RANGE)
|
|
159
174
|
});
|
|
175
|
+
let style = element.style ? _objectSpread({}, element.style) : {};
|
|
176
|
+
const columnWidthList = columns.map(item => "".concat(item.width, "px"));
|
|
177
|
+
style.gridTemplateColumns = columnWidthList.join(' ');
|
|
178
|
+
const rowHeightList = element.children.map((item, index) => getRowHeight(item, index));
|
|
179
|
+
style.gridAutoRows = rowHeightList.map(item => "minmax(".concat(item, "px, auto)")).join(' ');
|
|
160
180
|
return /*#__PURE__*/React.createElement(TableSelectedRangeContext.Provider, {
|
|
161
181
|
value: selectedRange
|
|
162
182
|
}, /*#__PURE__*/React.createElement(ResizeHandlersContext.Provider, {
|
|
@@ -171,8 +191,9 @@ const Table = _ref => {
|
|
|
171
191
|
setSelectedRange: setSelectedRangeByClick
|
|
172
192
|
}), /*#__PURE__*/React.createElement("div", {
|
|
173
193
|
className: classnames(tableContainerClassName, {
|
|
174
|
-
[TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP[element === null || element === void 0 ? void 0 : (_element$
|
|
194
|
+
[TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP[element === null || element === void 0 ? void 0 : (_element$ui = element.ui) === null || _element$ui === void 0 ? void 0 : _element$ui.alternate_highlight_color]]: element === null || element === void 0 ? void 0 : (_element$ui2 = element.ui) === null || _element$ui2 === void 0 ? void 0 : _element$ui2.alternate_highlight
|
|
175
195
|
}),
|
|
196
|
+
style: style,
|
|
176
197
|
onMouseDown: onMouseDown,
|
|
177
198
|
ref: table,
|
|
178
199
|
"data-id": element.id
|
|
@@ -192,12 +213,19 @@ function renderTable(props) {
|
|
|
192
213
|
} = props;
|
|
193
214
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
194
215
|
const editor = useSlateStatic();
|
|
216
|
+
const columns = getTableColumns(editor, element);
|
|
217
|
+
let style = element.style ? _objectSpread({}, element.style) : {};
|
|
218
|
+
const columnWidthList = columns.map(item => "".concat(item.width, "px"));
|
|
219
|
+
style.gridTemplateColumns = columnWidthList.join(' ');
|
|
220
|
+
const rowHeightList = element.children.map((item, index) => getRowHeight(item, index));
|
|
221
|
+
style.gridAutoRows = rowHeightList.map(item => "minmax(".concat(item, "px, auto)")).join(' ');
|
|
195
222
|
return /*#__PURE__*/React.createElement(TableRoot, {
|
|
196
|
-
columns:
|
|
223
|
+
columns: columns,
|
|
197
224
|
attributes: attributes
|
|
198
225
|
}, /*#__PURE__*/React.createElement("div", {
|
|
199
226
|
className: classnames('sdoc-table-container', attributes.className, className),
|
|
200
|
-
"data-id": element.id
|
|
227
|
+
"data-id": element.id,
|
|
228
|
+
style: style
|
|
201
229
|
}, children));
|
|
202
230
|
}
|
|
203
231
|
return /*#__PURE__*/React.createElement(Table, props);
|
|
@@ -21,8 +21,6 @@ const TableCell = _ref => {
|
|
|
21
21
|
const pathLength = cellPath.length;
|
|
22
22
|
const rowIndex = cellPath[pathLength - 2];
|
|
23
23
|
const cellIndex = cellPath[pathLength - 1];
|
|
24
|
-
const column = columns ? columns[cellIndex] : {};
|
|
25
|
-
const columnWidth = (column === null || column === void 0 ? void 0 : column.width) || 0;
|
|
26
24
|
const {
|
|
27
25
|
minColIndex,
|
|
28
26
|
maxColIndex,
|
|
@@ -55,12 +53,22 @@ const TableCell = _ref => {
|
|
|
55
53
|
style['backgroundColor'] = isSelected ? colorBlend(SELECTED_TABLE_CELL_BACKGROUND_COLOR, color, 0.9) : color;
|
|
56
54
|
}
|
|
57
55
|
}
|
|
56
|
+
if (element.is_combined) {
|
|
57
|
+
style.display = 'none';
|
|
58
|
+
}
|
|
59
|
+
if (rowIndex == 0) {
|
|
60
|
+
style.borderTop = '1px solid #ddd';
|
|
61
|
+
}
|
|
62
|
+
if (cellIndex == 0) {
|
|
63
|
+
style.borderLeft = '1px solid #ddd';
|
|
64
|
+
}
|
|
65
|
+
const {
|
|
66
|
+
rowspan = 1,
|
|
67
|
+
colspan = 1
|
|
68
|
+
} = element;
|
|
69
|
+
style.gridArea = "".concat(rowIndex + 1, " / ").concat(cellIndex + 1, " / span ").concat(rowspan, " / span ").concat(colspan);
|
|
58
70
|
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
59
|
-
style: _objectSpread(_objectSpread(
|
|
60
|
-
minWidth: columnWidth,
|
|
61
|
-
width: columnWidth,
|
|
62
|
-
maxWidth: columnWidth
|
|
63
|
-
}),
|
|
71
|
+
style: _objectSpread(_objectSpread({}, element.style), style),
|
|
64
72
|
className: classnames('table-cell', attributes.className, {
|
|
65
73
|
'cell-selected': isSelected,
|
|
66
74
|
'cell-light-height-left-border': isSelectedFirstCell,
|
|
@@ -86,8 +94,11 @@ function renderTableCell(props) {
|
|
|
86
94
|
|
|
87
95
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
88
96
|
const editor = useSlateStatic();
|
|
89
|
-
const cellPath = findPath(editor, element);
|
|
97
|
+
const cellPath = findPath(editor, element, [0, 0]);
|
|
90
98
|
if (!cellPath) return null;
|
|
99
|
+
const pathLength = cellPath.length;
|
|
100
|
+
const rowIndex = cellPath[pathLength - 2];
|
|
101
|
+
const cellIndex = cellPath[pathLength - 1];
|
|
91
102
|
|
|
92
103
|
// const cellValue = element;
|
|
93
104
|
let style = attributes.style || {};
|
|
@@ -97,14 +108,22 @@ function renderTableCell(props) {
|
|
|
97
108
|
if (ObjectUtils.hasProperty(element.style, TABLE_CELL_STYLE.BACKGROUND_COLOR) && element.style[TABLE_CELL_STYLE.BACKGROUND_COLOR]) {
|
|
98
109
|
style['backgroundColor'] = element.style[TABLE_CELL_STYLE.BACKGROUND_COLOR];
|
|
99
110
|
}
|
|
100
|
-
|
|
101
|
-
|
|
111
|
+
if (element.is_combined) {
|
|
112
|
+
style.display = 'none';
|
|
113
|
+
}
|
|
114
|
+
if (rowIndex == 0) {
|
|
115
|
+
style.borderTop = '1px solid #ddd';
|
|
116
|
+
}
|
|
117
|
+
if (cellIndex == 0) {
|
|
118
|
+
style.borderLeft = '1px solid #ddd';
|
|
119
|
+
}
|
|
120
|
+
const {
|
|
121
|
+
rowspan = 1,
|
|
122
|
+
colspan = 1
|
|
123
|
+
} = element;
|
|
124
|
+
style.gridArea = "".concat(rowIndex + 1, " / ").concat(cellIndex + 1, " / span ").concat(rowspan, " / span ").concat(colspan);
|
|
102
125
|
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
103
|
-
style: _objectSpread(_objectSpread(
|
|
104
|
-
minWidth: width,
|
|
105
|
-
width: width,
|
|
106
|
-
maxWidth: width
|
|
107
|
-
}),
|
|
126
|
+
style: _objectSpread(_objectSpread({}, element.style), style),
|
|
108
127
|
className: classnames('table-cell', attributes.className),
|
|
109
128
|
"data-id": element.id
|
|
110
129
|
}), children);
|
|
@@ -1,121 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
|
3
|
-
import classnames from 'classnames';
|
|
4
|
-
import { useSlateStatic, useReadOnly } from '@seafile/slate-react';
|
|
5
|
-
import { ReactEditor } from '@seafile/slate-react';
|
|
6
|
-
import { findPath } from '../../../core';
|
|
7
|
-
import { TABLE_ROW_MIN_HEIGHT } from '../constants';
|
|
8
|
-
import { getRowHeight, updateTableRowHeight } from '../helpers';
|
|
9
|
-
import { eventStopPropagation, getMouseDownInfo, getMouseMoveInfo, registerResizeEvents, unregisterResizeEvents } from '../../../../utils/mouse-event';
|
|
10
|
-
import { useSettingSelectRangeContext, useResizeHandlersContext } from './hooks';
|
|
11
|
-
import { useScrollContext } from '../../../../hooks/use-scroll-context';
|
|
12
|
-
const TableRow = _ref => {
|
|
13
|
-
let {
|
|
14
|
-
element,
|
|
15
|
-
attributes,
|
|
16
|
-
children
|
|
17
|
-
} = _ref;
|
|
18
|
-
const editor = useSlateStatic();
|
|
19
|
-
const isSettingSelectRange = useSettingSelectRangeContext();
|
|
20
|
-
const columns = useResizeHandlersContext();
|
|
21
|
-
const [isResizing, setIsResizing] = useState(false);
|
|
22
|
-
const [mouseDownInfo, setMouseDownInfo] = useState({});
|
|
23
|
-
const rowPath = findPath(editor, element);
|
|
24
|
-
const pathLength = rowPath ? rowPath.length : 0;
|
|
25
|
-
const rowIndex = rowPath ? rowPath[pathLength - 1] : -1;
|
|
26
|
-
const rowHeight = getRowHeight(element, rowIndex);
|
|
27
|
-
const tableRow = useRef(rowHeight);
|
|
28
|
-
const [height, setHeight] = useState(rowHeight);
|
|
29
|
-
const scrollContent = useScrollContext();
|
|
30
|
-
const onMouseDown = useCallback(event => {
|
|
31
|
-
eventStopPropagation(event);
|
|
32
|
-
const mouseDownInfo = getMouseDownInfo(event, scrollContent.current);
|
|
33
|
-
setMouseDownInfo(mouseDownInfo);
|
|
34
|
-
setIsResizing(true);
|
|
35
|
-
|
|
36
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
|
-
}, []);
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (!isResizing) return;
|
|
40
|
-
const onMouseMove = event => {
|
|
41
|
-
eventStopPropagation(event);
|
|
42
|
-
const mouseMoveInfo = getMouseMoveInfo(event, mouseDownInfo, scrollContent.current);
|
|
43
|
-
const newHeight = tableRow.current + mouseMoveInfo.displacementY;
|
|
44
|
-
const validHeight = Math.max(TABLE_ROW_MIN_HEIGHT, newHeight);
|
|
45
|
-
setHeight(validHeight);
|
|
46
|
-
};
|
|
47
|
-
const onMouseUp = event => {
|
|
48
|
-
eventStopPropagation(event);
|
|
49
|
-
setIsResizing(false);
|
|
50
|
-
tableRow.current = height;
|
|
51
|
-
updateTableRowHeight(editor, element, height);
|
|
52
|
-
};
|
|
53
|
-
registerResizeEvents({
|
|
54
|
-
'mousemove': onMouseMove,
|
|
55
|
-
'mouseup': onMouseUp
|
|
56
|
-
});
|
|
57
|
-
return () => {
|
|
58
|
-
unregisterResizeEvents({
|
|
59
|
-
'mousemove': onMouseMove,
|
|
60
|
-
'mouseup': onMouseUp
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
|
-
}, [isResizing, mouseDownInfo, element, attributes, height]);
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
const rowDom = ReactEditor.toDOMNode(editor, element);
|
|
68
|
-
if (!rowDom) return;
|
|
69
|
-
tableRow.current = rowDom.clientHeight;
|
|
70
|
-
|
|
71
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
-
}, [columns, element]);
|
|
73
|
-
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
74
|
-
className: classnames('table-row position-relative', attributes.className),
|
|
75
|
-
style: _objectSpread(_objectSpread({}, attributes.style), {}, {
|
|
76
|
-
height: height,
|
|
77
|
-
maxHeight: 'fit-content'
|
|
78
|
-
}),
|
|
79
|
-
"data-id": element.id
|
|
80
|
-
}), children, !isSettingSelectRange && /*#__PURE__*/React.createElement("div", {
|
|
81
|
-
className: classnames('table-row-height-just position-absolute', {
|
|
82
|
-
'resizing': isResizing
|
|
83
|
-
}),
|
|
84
|
-
contentEditable: false,
|
|
85
|
-
onMouseDown: onMouseDown
|
|
86
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
87
|
-
className: "table-row-height-just-color-tip"
|
|
88
|
-
})));
|
|
89
|
-
};
|
|
1
|
+
import React from 'react';
|
|
90
2
|
function renderTableRow(props) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
attributes,
|
|
96
|
-
children,
|
|
97
|
-
element
|
|
98
|
-
} = props;
|
|
99
|
-
|
|
100
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
101
|
-
const editor = useSlateStatic();
|
|
102
|
-
const rowPath = findPath(editor, element);
|
|
103
|
-
if (!rowPath) return null;
|
|
104
|
-
const pathLength = rowPath.length;
|
|
105
|
-
const rowIndex = rowPath[pathLength - 1];
|
|
106
|
-
const {
|
|
107
|
-
style = {}
|
|
108
|
-
} = element;
|
|
109
|
-
const height = getRowHeight(element, rowIndex);
|
|
110
|
-
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
111
|
-
className: classnames('table-row', attributes.className),
|
|
112
|
-
style: _objectSpread(_objectSpread(_objectSpread({}, attributes.style), style), {}, {
|
|
113
|
-
height,
|
|
114
|
-
maxHeight: 'fit-content'
|
|
115
|
-
}),
|
|
116
|
-
"data-id": element.id
|
|
117
|
-
}), children);
|
|
118
|
-
}
|
|
119
|
-
return /*#__PURE__*/React.createElement(TableRow, props);
|
|
3
|
+
const {
|
|
4
|
+
children
|
|
5
|
+
} = props;
|
|
6
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
120
7
|
}
|
|
121
8
|
export default renderTableRow;
|
|
@@ -6,7 +6,7 @@ import { useTableRootContext } from '../hooks';
|
|
|
6
6
|
import { TABLE_CELL_MIN_WIDTH } from '../../constants';
|
|
7
7
|
import { getTableColumns, updateColumnWidth } from '../../helpers';
|
|
8
8
|
import { eventStopPropagation, getMouseDownInfo, getMouseMoveInfo, registerResizeEvents, unregisterResizeEvents } from '../../../../../utils/mouse-event';
|
|
9
|
-
const
|
|
9
|
+
const ColumnResizeHandler = _ref => {
|
|
10
10
|
let {
|
|
11
11
|
column,
|
|
12
12
|
left: initLeft,
|
|
@@ -115,4 +115,4 @@ const ResizeHandler = _ref => {
|
|
|
115
115
|
className: "table-cell-width-just-color-tip"
|
|
116
116
|
}));
|
|
117
117
|
};
|
|
118
|
-
export default
|
|
118
|
+
export default ColumnResizeHandler;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useSlateStatic } from '@seafile/slate-react';
|
|
3
3
|
import FirstColumnResizeHandler from './first-column-left-resize-handler';
|
|
4
|
-
import
|
|
4
|
+
import ColumnResizeHandler from './column-resize-handler';
|
|
5
|
+
import RowResizeHandler from './row-resize-handler';
|
|
5
6
|
import { getNode, findPath } from '../../../../core';
|
|
6
7
|
import { useResizeHandlersContext } from '../hooks';
|
|
7
|
-
import { getTableColumns } from '../../helpers';
|
|
8
|
+
import { getRowHeight, getTableColumns } from '../../helpers';
|
|
9
|
+
import { TABLE_ROW_STYLE } from '../../constants';
|
|
8
10
|
const ResizeHandlers = _ref => {
|
|
9
11
|
let {
|
|
10
12
|
element
|
|
@@ -15,8 +17,19 @@ const ResizeHandlers = _ref => {
|
|
|
15
17
|
if (!tablePath) return null;
|
|
16
18
|
const table = getNode(editor, tablePath);
|
|
17
19
|
if (!table) return null;
|
|
20
|
+
const rows = element.children;
|
|
21
|
+
let rowBottom = 0;
|
|
18
22
|
let columnLeft = 0;
|
|
19
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null,
|
|
23
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, rows.map((row, index) => {
|
|
24
|
+
rowBottom += getRowHeight(row, index);
|
|
25
|
+
return /*#__PURE__*/React.createElement(RowResizeHandler, {
|
|
26
|
+
key: index,
|
|
27
|
+
row: row,
|
|
28
|
+
rowBottom: rowBottom,
|
|
29
|
+
index: index,
|
|
30
|
+
element: element
|
|
31
|
+
});
|
|
32
|
+
}), /*#__PURE__*/React.createElement(FirstColumnResizeHandler, {
|
|
20
33
|
key: "column-0-left",
|
|
21
34
|
column: columns[0],
|
|
22
35
|
left: 0,
|
|
@@ -24,7 +37,7 @@ const ResizeHandlers = _ref => {
|
|
|
24
37
|
element: element
|
|
25
38
|
}), columns.map((column, columnIndex) => {
|
|
26
39
|
columnLeft = columnLeft + column.width;
|
|
27
|
-
return /*#__PURE__*/React.createElement(
|
|
40
|
+
return /*#__PURE__*/React.createElement(ColumnResizeHandler, {
|
|
28
41
|
key: columnIndex,
|
|
29
42
|
column: column,
|
|
30
43
|
left: columnLeft,
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import classnames from 'classnames';
|
|
3
|
+
import { useSlateStatic } from '@seafile/slate-react';
|
|
4
|
+
import { ReactEditor } from '@seafile/slate-react';
|
|
5
|
+
import { TABLE_ROW_MIN_HEIGHT } from '../../constants';
|
|
6
|
+
import { getRowHeight, updateTableRowHeight } from '../../helpers';
|
|
7
|
+
import { eventStopPropagation, getMouseDownInfo, getMouseMoveInfo, registerResizeEvents, unregisterResizeEvents } from '../../../../../utils/mouse-event';
|
|
8
|
+
import { useScrollContext } from '../../../../../hooks/use-scroll-context';
|
|
9
|
+
const RowResizeHandler = _ref => {
|
|
10
|
+
let {
|
|
11
|
+
row,
|
|
12
|
+
index,
|
|
13
|
+
rowBottom: initRowBottom,
|
|
14
|
+
element
|
|
15
|
+
} = _ref;
|
|
16
|
+
const editor = useSlateStatic();
|
|
17
|
+
const [rowBottom, setRowBottom] = useState(initRowBottom);
|
|
18
|
+
const [isResizing, setIsResizing] = useState(false);
|
|
19
|
+
const [mouseDownInfo, setMouseDownInfo] = useState({});
|
|
20
|
+
const [style, setStyle] = useState({});
|
|
21
|
+
const rowHeight = getRowHeight(row, index);
|
|
22
|
+
const tableRow = useRef(rowHeight);
|
|
23
|
+
const [height, setHeight] = useState(rowHeight);
|
|
24
|
+
const scrollContent = useScrollContext();
|
|
25
|
+
const onMouseDown = useCallback(event => {
|
|
26
|
+
eventStopPropagation(event);
|
|
27
|
+
const mouseDownInfo = getMouseDownInfo(event, scrollContent.current);
|
|
28
|
+
setMouseDownInfo(mouseDownInfo);
|
|
29
|
+
setStyle({
|
|
30
|
+
top: initRowBottom - 2.5
|
|
31
|
+
});
|
|
32
|
+
setIsResizing(true);
|
|
33
|
+
|
|
34
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
+
}, []);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!isResizing) return;
|
|
38
|
+
const onMouseMove = event => {
|
|
39
|
+
eventStopPropagation(event);
|
|
40
|
+
const mouseMoveInfo = getMouseMoveInfo(event, mouseDownInfo, scrollContent.current);
|
|
41
|
+
const newHeight = tableRow.current + mouseMoveInfo.displacementY;
|
|
42
|
+
const validHeight = Math.max(TABLE_ROW_MIN_HEIGHT, newHeight);
|
|
43
|
+
setHeight(validHeight);
|
|
44
|
+
setStyle({
|
|
45
|
+
top: rowBottom - tableRow.current + validHeight - 2.5
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const onMouseUp = event => {
|
|
49
|
+
eventStopPropagation(event);
|
|
50
|
+
setIsResizing(false);
|
|
51
|
+
tableRow.current = height;
|
|
52
|
+
updateTableRowHeight(editor, row, height);
|
|
53
|
+
};
|
|
54
|
+
registerResizeEvents({
|
|
55
|
+
'mousemove': onMouseMove,
|
|
56
|
+
'mouseup': onMouseUp
|
|
57
|
+
});
|
|
58
|
+
return () => {
|
|
59
|
+
unregisterResizeEvents({
|
|
60
|
+
'mousemove': onMouseMove,
|
|
61
|
+
'mouseup': onMouseUp
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
66
|
+
}, [isResizing, mouseDownInfo, rowBottom, element, height]);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const cell = row.children.filter(cell => !cell.is_combined && (!cell.rowspan || cell.rowspan == 1))[0];
|
|
69
|
+
if (!cell) return;
|
|
70
|
+
const rowDom = ReactEditor.toDOMNode(editor, cell);
|
|
71
|
+
if (!rowDom) return;
|
|
72
|
+
tableRow.current = rowDom.clientHeight;
|
|
73
|
+
setRowBottom(initRowBottom - height + tableRow.current);
|
|
74
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
|
+
}, [row, initRowBottom]);
|
|
76
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
77
|
+
className: classnames('table-row-height-just position-absolute', {
|
|
78
|
+
'resizing': isResizing
|
|
79
|
+
}),
|
|
80
|
+
contentEditable: false,
|
|
81
|
+
style: isResizing ? style : {
|
|
82
|
+
top: rowBottom - 2.5
|
|
83
|
+
},
|
|
84
|
+
onMouseDown: onMouseDown
|
|
85
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
86
|
+
className: "table-row-height-just-color-tip"
|
|
87
|
+
}));
|
|
88
|
+
};
|
|
89
|
+
export default RowResizeHandler;
|
package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js
CHANGED
|
@@ -28,24 +28,23 @@ const RowHeader = _ref => {
|
|
|
28
28
|
const currentCell = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
|
|
29
29
|
const currentCellPath = currentCell ? findPath(editor, currentCell, [-1, -1]) : [-1, -1];
|
|
30
30
|
const pathLength = currentCellPath.length;
|
|
31
|
+
const updateRowHeight = () => {
|
|
32
|
+
const cell = row.children.filter(cell => !cell.is_combined && (!cell.rowspan || cell.rowspan == 1))[0];
|
|
33
|
+
if (!cell) return;
|
|
34
|
+
const rowDom = ReactEditor.toDOMNode(editor, cell);
|
|
35
|
+
if (!rowDom) return;
|
|
36
|
+
if (rowHeight === rowDom.clientHeight) return;
|
|
37
|
+
setRowHeight(rowDom.clientHeight);
|
|
38
|
+
};
|
|
31
39
|
useEffect(() => {
|
|
32
40
|
if (elementHasImage(row)) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const rowDom = ReactEditor.toDOMNode(editor, row);
|
|
36
|
-
if (!rowDom) return;
|
|
37
|
-
if (rowHeight === rowDom.clientHeight) return;
|
|
38
|
-
setRowHeight(rowDom.clientHeight);
|
|
39
|
-
}, 300);
|
|
41
|
+
// There is a delay in image loading
|
|
42
|
+
const time = setTimeout(updateRowHeight, 300);
|
|
40
43
|
return () => {
|
|
41
44
|
clearTimeout(time);
|
|
42
45
|
};
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
if (!rowDom) return;
|
|
46
|
-
if (rowHeight === rowDom.clientHeight) return;
|
|
47
|
-
setRowHeight(rowDom.clientHeight);
|
|
48
|
-
|
|
47
|
+
updateRowHeight();
|
|
49
48
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
49
|
}, [columns, row, index]);
|
|
51
50
|
const onMouseMove = useCallback(event => {
|
|
@@ -90,7 +89,7 @@ const RowHeader = _ref => {
|
|
|
90
89
|
'range-selected-tip': !isSelectedARow && isSelectedSomeRow || currentCellPath[pathLength - 2] === index
|
|
91
90
|
}),
|
|
92
91
|
style: {
|
|
93
|
-
height:
|
|
92
|
+
height: rowHeight + 1
|
|
94
93
|
},
|
|
95
94
|
ref: rowHeaderRef,
|
|
96
95
|
onClick: () => selectRange(index),
|
package/package.json
CHANGED
|
@@ -417,5 +417,11 @@
|
|
|
417
417
|
"Freezed": "Freezed",
|
|
418
418
|
"Callout": "Callout",
|
|
419
419
|
"The_current_location_does_not_support_pasting": "The current location does not support pasting ",
|
|
420
|
-
"Please_enter...": "Please enter..."
|
|
420
|
+
"Please_enter...": "Please enter...",
|
|
421
|
+
"Combine_cell": "Combine cells",
|
|
422
|
+
"Split_cell": "Split cell",
|
|
423
|
+
"Row_number": "Row number",
|
|
424
|
+
"Column_number": "Column number",
|
|
425
|
+
"The_maximum_row_number_is_{number}": "The maximum row number is {number}",
|
|
426
|
+
"The_maximum_column_number_is_{number}": "The maximum column number is {number}"
|
|
421
427
|
}
|
|
@@ -417,5 +417,11 @@
|
|
|
417
417
|
"Freezed": "已冻结",
|
|
418
418
|
"Callout": "高亮块",
|
|
419
419
|
"The_current_location_does_not_support_pasting": "当前位置不支持粘贴",
|
|
420
|
-
"Please_enter...": "请输入..."
|
|
420
|
+
"Please_enter...": "请输入...",
|
|
421
|
+
"Combine_cell": "合并单元格",
|
|
422
|
+
"Split_cell": "拆分单元格",
|
|
423
|
+
"Row_number": "行数",
|
|
424
|
+
"Column_number": "列数",
|
|
425
|
+
"The_maximum_row_number_is_{number}": "最大行数为 {number}",
|
|
426
|
+
"The_maximum_column_number_is_{number}": "最大列数为 {number}"
|
|
421
427
|
}
|
|
File without changes
|
/package/dist/basic-sdk/extension/plugins/table/{dialog → dialogs}/custom-table-size-dialog/index.js
RENAMED
|
File without changes
|
|
File without changes
|