@seafile/sdoc-editor 0.5.14 → 0.5.16
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/basic-sdk/constants/index.js +4 -1
- package/dist/basic-sdk/editor/editable-article.js +7 -4
- package/dist/basic-sdk/extension/constants/index.js +1 -0
- package/dist/basic-sdk/extension/plugins/table/constants/index.js +4 -1
- package/dist/basic-sdk/extension/plugins/table/helpers.js +312 -1
- package/dist/basic-sdk/extension/plugins/table/render/drag-handlers/column-drag-handler.js +17 -0
- package/dist/basic-sdk/extension/plugins/table/render/drag-handlers/index.js +45 -0
- package/dist/basic-sdk/extension/plugins/table/render/drag-handlers/row-drag-handler.js +17 -0
- package/dist/basic-sdk/extension/plugins/table/render/index.js +10 -4
- package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +55 -7
- package/dist/basic-sdk/extension/plugins/table/render/table-header/columns-header/column-header.js +28 -4
- package/dist/basic-sdk/extension/plugins/table/render/table-header/columns-header/index.js +6 -2
- package/dist/basic-sdk/extension/plugins/table/render/table-header/index.css +11 -0
- package/dist/basic-sdk/extension/plugins/table/render/table-header/index.js +63 -20
- package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/index.js +6 -2
- package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js +28 -4
- package/dist/basic-sdk/extension/toolbar/side-toolbar/event.js +3 -0
- package/dist/basic-sdk/extension/toolbar/side-toolbar/index.js +4 -2
- package/package.json +1 -1
- package/public/locales/en/sdoc-editor.json +3 -1
- package/public/locales/zh_CN/sdoc-editor.json +3 -1
- package/public/media/sdoc-editor-font/iconfont.svg +0 -3
|
@@ -19,7 +19,10 @@ export const INTERNAL_EVENT = {
|
|
|
19
19
|
UPDATE_SEARCH_REPLACE_HIGHLIGHT: 'update_search_replace_highlight',
|
|
20
20
|
TABLE_CELL_MOUSE_ENTER: 'table_cell_mouse_enter',
|
|
21
21
|
HANDLE_MENTION_TEMP_CHOSEN: 'handle_mention_temp_chosen',
|
|
22
|
-
UPDATE_MENTION_TEMP_CONTENT: 'update_mention_temp_content'
|
|
22
|
+
UPDATE_MENTION_TEMP_CONTENT: 'update_mention_temp_content',
|
|
23
|
+
TABLE_COLUMN_START_DRAG: 'table_column_start_drag',
|
|
24
|
+
TABLE_SHOW_DRAG_HANDLER: 'table_show_drag_handler',
|
|
25
|
+
TABLE_HIDE_DRAG_HANDLER: 'table_show_drag_handler'
|
|
23
26
|
};
|
|
24
27
|
export const REVISION_DIFF_KEY = 'diff';
|
|
25
28
|
export const REVISION_DIFF_VALUE = '1';
|
|
@@ -14,6 +14,7 @@ import { ArticleContainer } from '../layout';
|
|
|
14
14
|
import { useScrollContext } from '../hooks/use-scroll-context';
|
|
15
15
|
import { SetNodeToDecorations } from '../highlight';
|
|
16
16
|
import { IMAGE } from '../extension/constants';
|
|
17
|
+
import { isPreventResetTableSelectedRange } from '../extension/plugins/table/helpers';
|
|
17
18
|
const EditableArticle = _ref => {
|
|
18
19
|
let {
|
|
19
20
|
isShowComment,
|
|
@@ -31,10 +32,12 @@ const EditableArticle = _ref => {
|
|
|
31
32
|
const eventProxy = useMemo(() => new EventProxy(editor), []);
|
|
32
33
|
const onMouseDown = useCallback(event => {
|
|
33
34
|
if (event.button === 0) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const isPreventReset = isPreventResetTableSelectedRange(event);
|
|
36
|
+
if (!isPreventReset) {
|
|
37
|
+
editor.reSetTableSelectedRange();
|
|
38
|
+
const eventBus = EventBus.getInstance();
|
|
39
|
+
eventBus.dispatch(INTERNAL_EVENT.CANCEL_TABLE_SELECT_RANGE);
|
|
40
|
+
}
|
|
38
41
|
}
|
|
39
42
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
43
|
}, []);
|
|
@@ -21,6 +21,7 @@ export const HEADER_TITLE_MAP = {
|
|
|
21
21
|
};
|
|
22
22
|
export const TRANSPARENT = 'transparent';
|
|
23
23
|
export const CLIPBOARD_FORMAT_KEY = 'x-slate-fragment';
|
|
24
|
+
export const TABLE_DRAG_KEY = 'drag-table/json';
|
|
24
25
|
export const CLIPBOARD_ORIGIN_SDOC_KEY = 'origin-sdoc-uuid';
|
|
25
26
|
export const INSERT_FILE_DISPLAY_TYPE = ['text_link', 'icon_link', 'card_link'];
|
|
26
27
|
export const INSERT_POSITION = {
|
|
@@ -46,4 +46,7 @@ export const RESIZE_MASK_BOTTOM = 'bottom';
|
|
|
46
46
|
export const RESIZE_MASK_LEFT = 'left';
|
|
47
47
|
export const RESIZE_HANDLER_ROW = 'row';
|
|
48
48
|
export const RESIZE_HANDLER_COLUMN = 'column';
|
|
49
|
-
export const RESIZE_HANDLER_FIRST_COLUMN = 'first_column';
|
|
49
|
+
export const RESIZE_HANDLER_FIRST_COLUMN = 'first_column';
|
|
50
|
+
export const DRAG_HANDLER_ROW = 'row';
|
|
51
|
+
export const DRAG_HANDLER_COLUMN = 'column';
|
|
52
|
+
export const CELL_SELECTED = 'cell-selected';
|
|
@@ -5,7 +5,7 @@ import { ReactEditor } from '@seafile/slate-react';
|
|
|
5
5
|
import deepCopy from 'deep-copy';
|
|
6
6
|
import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, getSelectedElems, focusEditor, getNode, findPath, replaceNodeChildren, replaceNode, getSelectedNodeEntryByType, getAboveBlockNode } from '../../core';
|
|
7
7
|
import { ELEMENT_TYPE, KEYBOARD, CLIPBOARD_FORMAT_KEY, INSERT_POSITION } from '../../constants';
|
|
8
|
-
import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, TABLE_ROW_STYLE, INHERIT_CELL_STYLE_WHEN_SELECT_MULTIPLE, INHERIT_CELL_STYLE_WHEN_SELECT_SINGLE, TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from './constants';
|
|
8
|
+
import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, TABLE_ROW_STYLE, INHERIT_CELL_STYLE_WHEN_SELECT_MULTIPLE, INHERIT_CELL_STYLE_WHEN_SELECT_SINGLE, TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP, CELL_SELECTED, DRAG_HANDLER_COLUMN, DRAG_HANDLER_ROW } from './constants';
|
|
9
9
|
import EventBus from '../../../utils/event-bus';
|
|
10
10
|
import { INTERNAL_EVENT, PAGE_EDIT_AREA_WIDTH } from '../../../constants';
|
|
11
11
|
import ObjectUtils from '../../../utils/object-utils';
|
|
@@ -1426,6 +1426,8 @@ export const focusClosestCellWhenJustifyCellSize = (editor, adjustingCell) => {
|
|
|
1426
1426
|
const cellPath = ReactEditor.findPath(editor, adjustingCell);
|
|
1427
1427
|
focusEditor(editor, Editor.end(editor, cellPath));
|
|
1428
1428
|
};
|
|
1429
|
+
|
|
1430
|
+
// Search main cell of combined cell
|
|
1429
1431
|
const searchCombinedMainCell = (table, startRowIndex, startColIndex) => {
|
|
1430
1432
|
for (let rowIndex = startRowIndex; rowIndex >= 0; rowIndex--) {
|
|
1431
1433
|
const row = table.children[rowIndex];
|
|
@@ -1534,4 +1536,313 @@ export const adjustCombinedCellRange = (table, range) => {
|
|
|
1534
1536
|
if (isRowCombined && isColCombined) return EMPTY_SELECTED_RANGE;
|
|
1535
1537
|
}
|
|
1536
1538
|
return range;
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* Do not reset table selected range, when drag table column / row
|
|
1543
|
+
* @param {MouseEvent} event
|
|
1544
|
+
* @returns {Boolean}
|
|
1545
|
+
*/
|
|
1546
|
+
export const isPreventResetTableSelectedRange = event => {
|
|
1547
|
+
const {
|
|
1548
|
+
target
|
|
1549
|
+
} = event;
|
|
1550
|
+
const draggable = target.getAttribute('draggable');
|
|
1551
|
+
const isColumnHeader = target.classList.contains('sdoc-table-column-header');
|
|
1552
|
+
const isRowHeader = target.classList.contains('sdoc-table-row-header');
|
|
1553
|
+
const isHeader = isColumnHeader || isRowHeader;
|
|
1554
|
+
const isPreventReset = isHeader || draggable === 'true';
|
|
1555
|
+
return isPreventReset;
|
|
1556
|
+
};
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* Check drag type, column or row
|
|
1560
|
+
*/
|
|
1561
|
+
export const getTableDragType = (table, selectedRange) => {
|
|
1562
|
+
const rowCount = table.children.length;
|
|
1563
|
+
const {
|
|
1564
|
+
minRowIndex,
|
|
1565
|
+
maxRowIndex
|
|
1566
|
+
} = selectedRange;
|
|
1567
|
+
const isSelectColumn = minRowIndex === 0 && maxRowIndex === rowCount - 1;
|
|
1568
|
+
return isSelectColumn ? DRAG_HANDLER_COLUMN : DRAG_HANDLER_ROW;
|
|
1569
|
+
};
|
|
1570
|
+
const updateTableColumns = (editor, table, targetColIndex, startColIndex, endColIndex) => {
|
|
1571
|
+
const columns = [...table.columns];
|
|
1572
|
+
const deleteCount = endColIndex - startColIndex + 1;
|
|
1573
|
+
const newColumns = columns.splice(startColIndex, deleteCount);
|
|
1574
|
+
columns.splice(targetColIndex, 0, ...newColumns);
|
|
1575
|
+
updateColumnWidth(editor, table, columns);
|
|
1576
|
+
};
|
|
1577
|
+
export const moveColumns = (editor, targetColIndex, startColIndex, endColIndex) => {
|
|
1578
|
+
// Get selected table information
|
|
1579
|
+
const {
|
|
1580
|
+
table,
|
|
1581
|
+
tablePath
|
|
1582
|
+
} = getSelectedInfo(editor);
|
|
1583
|
+
// Check if moving columns forward or backward
|
|
1584
|
+
const isMoveToFroward = targetColIndex < startColIndex;
|
|
1585
|
+
|
|
1586
|
+
// Iterate over each row in the table
|
|
1587
|
+
table.children.forEach((row, rowIndex) => {
|
|
1588
|
+
if (isMoveToFroward) {
|
|
1589
|
+
// Calculate target and source paths for moving columns forward
|
|
1590
|
+
const targetPath = [...tablePath, rowIndex, targetColIndex];
|
|
1591
|
+
const sourcePath = [...tablePath, rowIndex, endColIndex];
|
|
1592
|
+
|
|
1593
|
+
// Move columns forward by inserting nodes
|
|
1594
|
+
for (let insertIndex = endColIndex; insertIndex >= startColIndex; insertIndex--) {
|
|
1595
|
+
const insertNode = row.children[insertIndex];
|
|
1596
|
+
Transforms.removeNodes(editor, {
|
|
1597
|
+
at: sourcePath
|
|
1598
|
+
});
|
|
1599
|
+
Transforms.insertNodes(editor, insertNode, {
|
|
1600
|
+
at: targetPath
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
} else {
|
|
1604
|
+
// Calculate target and source paths for moving columns backward
|
|
1605
|
+
const targetPath = [...tablePath, rowIndex, targetColIndex - 1];
|
|
1606
|
+
const sourcePath = [...tablePath, rowIndex, startColIndex];
|
|
1607
|
+
|
|
1608
|
+
// Move columns backward by inserting nodes
|
|
1609
|
+
for (let insertIndex = startColIndex; insertIndex <= endColIndex; insertIndex++) {
|
|
1610
|
+
const insertNode = row.children[insertIndex];
|
|
1611
|
+
Transforms.removeNodes(editor, {
|
|
1612
|
+
at: sourcePath
|
|
1613
|
+
});
|
|
1614
|
+
Transforms.insertNodes(editor, insertNode, {
|
|
1615
|
+
at: targetPath
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
// Update table columns after moving
|
|
1622
|
+
updateTableColumns(editor, table, targetColIndex, startColIndex, endColIndex);
|
|
1623
|
+
|
|
1624
|
+
// Set new selected range after moving columns
|
|
1625
|
+
const newSelectRange = {
|
|
1626
|
+
minRowIndex: 0,
|
|
1627
|
+
maxRowIndex: table.children.length - 1,
|
|
1628
|
+
minColIndex: targetColIndex,
|
|
1629
|
+
maxColIndex: targetColIndex + endColIndex - startColIndex
|
|
1630
|
+
};
|
|
1631
|
+
setTableSelectedRange(editor, newSelectRange);
|
|
1632
|
+
};
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* Calculate the new selected range after dragging a column or row in the table.
|
|
1636
|
+
* @param {Object} table - The table object containing columns and rows.
|
|
1637
|
+
* @param {string} moveType - The type of drag operation (DRAG_HANDLER_COLUMN for column, DRAG_HANDLER_ROW for row).
|
|
1638
|
+
* @param {number} targetIndex - The index of the target column or row after dragging.
|
|
1639
|
+
* @param {number} startIndex - The index of the starting column or row before dragging.
|
|
1640
|
+
* @param {number} endIndex - The index of the ending column or row before dragging.
|
|
1641
|
+
* @returns {Object} - The new selected range after the drag operation.
|
|
1642
|
+
*/
|
|
1643
|
+
export const getTableSelectedRangeAfterDrag = (table, moveType, targetIndex, startIndex, endIndex) => {
|
|
1644
|
+
// Calculate the total number of columns and rows in the table
|
|
1645
|
+
const colCount = table.columns.length;
|
|
1646
|
+
const rowCount = table.children.length;
|
|
1647
|
+
|
|
1648
|
+
// Initialize the new selected range with full table range
|
|
1649
|
+
const newSelectRange = {
|
|
1650
|
+
minRowIndex: 0,
|
|
1651
|
+
maxRowIndex: rowCount - 1,
|
|
1652
|
+
minColIndex: 0,
|
|
1653
|
+
maxColIndex: colCount - 1
|
|
1654
|
+
};
|
|
1655
|
+
|
|
1656
|
+
// Determine if the drag movement is forward or backward
|
|
1657
|
+
const isMoveToFroward = targetIndex < startIndex;
|
|
1658
|
+
|
|
1659
|
+
// Adjust selected range based on the type of drag operation
|
|
1660
|
+
if (moveType === DRAG_HANDLER_COLUMN) {
|
|
1661
|
+
if (isMoveToFroward) {
|
|
1662
|
+
newSelectRange.minColIndex = targetIndex;
|
|
1663
|
+
newSelectRange.maxColIndex = targetIndex + endIndex - startIndex;
|
|
1664
|
+
} else {
|
|
1665
|
+
const moveCount = endIndex - startIndex + 1;
|
|
1666
|
+
newSelectRange.minColIndex = targetIndex - moveCount;
|
|
1667
|
+
newSelectRange.maxColIndex = targetIndex - 1;
|
|
1668
|
+
}
|
|
1669
|
+
} else {
|
|
1670
|
+
if (isMoveToFroward) {
|
|
1671
|
+
newSelectRange.minRowIndex = targetIndex;
|
|
1672
|
+
newSelectRange.maxRowIndex = targetIndex + endIndex - startIndex;
|
|
1673
|
+
} else {
|
|
1674
|
+
const moveCount = endIndex - startIndex + 1;
|
|
1675
|
+
newSelectRange.minRowIndex = targetIndex - moveCount;
|
|
1676
|
+
newSelectRange.maxRowIndex = targetIndex - 1;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return newSelectRange;
|
|
1680
|
+
};
|
|
1681
|
+
export const moveRows = (editor, targetRowIndex, startRowIndex, endRowIndex) => {
|
|
1682
|
+
const {
|
|
1683
|
+
table,
|
|
1684
|
+
tablePath
|
|
1685
|
+
} = getSelectedInfo(editor);
|
|
1686
|
+
const isMoveToFroward = targetRowIndex < startRowIndex;
|
|
1687
|
+
const targetPath = [...tablePath, isMoveToFroward ? targetRowIndex : targetRowIndex - 1];
|
|
1688
|
+
const sourcePath = [...tablePath, isMoveToFroward ? endRowIndex : startRowIndex];
|
|
1689
|
+
if (isMoveToFroward) {
|
|
1690
|
+
for (let insertIndex = endRowIndex; insertIndex >= startRowIndex; insertIndex--) {
|
|
1691
|
+
const insertNode = table.children[insertIndex];
|
|
1692
|
+
Transforms.removeNodes(editor, {
|
|
1693
|
+
at: sourcePath
|
|
1694
|
+
});
|
|
1695
|
+
Transforms.insertNodes(editor, insertNode, {
|
|
1696
|
+
at: targetPath
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
} else {
|
|
1700
|
+
for (let insertIndex = startRowIndex; insertIndex <= endRowIndex; insertIndex++) {
|
|
1701
|
+
const insertNode = table.children[insertIndex];
|
|
1702
|
+
Transforms.removeNodes(editor, {
|
|
1703
|
+
at: sourcePath
|
|
1704
|
+
});
|
|
1705
|
+
Transforms.insertNodes(editor, insertNode, {
|
|
1706
|
+
at: targetPath
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
const newSelectRange = {
|
|
1711
|
+
minRowIndex: targetRowIndex,
|
|
1712
|
+
maxRowIndex: targetRowIndex + endRowIndex - startRowIndex,
|
|
1713
|
+
minColIndex: 0,
|
|
1714
|
+
maxColIndex: table.children.length - 1
|
|
1715
|
+
};
|
|
1716
|
+
setTableSelectedRange(editor, newSelectRange);
|
|
1717
|
+
};
|
|
1718
|
+
export const generateDragMoveElement = tipText => {
|
|
1719
|
+
const canvasId = 'sdoc-drag-image';
|
|
1720
|
+
let canvas = document.getElementById(canvasId);
|
|
1721
|
+
if (!canvas) {
|
|
1722
|
+
canvas = document.createElement('canvas');
|
|
1723
|
+
canvas.width = 150;
|
|
1724
|
+
canvas.height = 30;
|
|
1725
|
+
canvas.id = canvasId;
|
|
1726
|
+
document.body.appendChild(canvas);
|
|
1727
|
+
}
|
|
1728
|
+
canvas.style.display = 'block';
|
|
1729
|
+
canvas.style.position = 'fixed';
|
|
1730
|
+
const context = canvas.getContext('2d');
|
|
1731
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
1732
|
+
context.textAlign = 'center';
|
|
1733
|
+
context.fillStyle = 'rgb(66, 129, 219)';
|
|
1734
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
1735
|
+
context.font = '12px';
|
|
1736
|
+
context.textBaseline = 'middle';
|
|
1737
|
+
context.fillStyle = 'white';
|
|
1738
|
+
context.fillText(tipText, canvas.width / 2, canvas.height / 2);
|
|
1739
|
+
return canvas;
|
|
1740
|
+
};
|
|
1741
|
+
export const isHideDragHandlerLine = (editor, displayType, table, cellPath) => {
|
|
1742
|
+
const pathLength = cellPath.length;
|
|
1743
|
+
const rowIndex = cellPath[pathLength - 2];
|
|
1744
|
+
const cellIndex = cellPath[pathLength - 1];
|
|
1745
|
+
let preCellDom = null;
|
|
1746
|
+
if (displayType === DRAG_HANDLER_COLUMN && cellIndex > 1) {
|
|
1747
|
+
const prevCell = table.children[rowIndex].children[cellIndex - 1];
|
|
1748
|
+
preCellDom = ReactEditor.toDOMNode(editor, prevCell);
|
|
1749
|
+
} else if (displayType === DRAG_HANDLER_ROW && rowIndex > 1) {
|
|
1750
|
+
const prevCell = table.children[rowIndex - 1].children[cellIndex];
|
|
1751
|
+
preCellDom = ReactEditor.toDOMNode(editor, prevCell);
|
|
1752
|
+
}
|
|
1753
|
+
const isPrevCellSelected = preCellDom ? preCellDom.classList.contains(CELL_SELECTED) : false;
|
|
1754
|
+
|
|
1755
|
+
// Check if the previous cell is selected
|
|
1756
|
+
if (isPrevCellSelected) return true;
|
|
1757
|
+
|
|
1758
|
+
// Check if the combined cell
|
|
1759
|
+
if (displayType === DRAG_HANDLER_COLUMN) {
|
|
1760
|
+
const isCombined = table.children.some(row => row.children[cellIndex].is_combined);
|
|
1761
|
+
return isCombined;
|
|
1762
|
+
} else {
|
|
1763
|
+
const isCombined = table.children[rowIndex].children.some(cell => cell.is_combined);
|
|
1764
|
+
return isCombined;
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
export const getTableRowSelectedRange = (table, rowIndex) => {
|
|
1768
|
+
const row = table.children[rowIndex];
|
|
1769
|
+
const columnCount = row.children.length;
|
|
1770
|
+
let minRowIndex = rowIndex;
|
|
1771
|
+
let maxRowIndex = rowIndex;
|
|
1772
|
+
let minColIndex = 0;
|
|
1773
|
+
let maxColIndex = columnCount - 1;
|
|
1774
|
+
const findRowRange = findRowIndex => {
|
|
1775
|
+
let checkRow = table.children[findRowIndex];
|
|
1776
|
+
const combinedIndexes = checkRow.children.reduce((acc, cell, index) => {
|
|
1777
|
+
if (cell.is_combined) acc.push(index);
|
|
1778
|
+
if (cell.rowspan > 1) {
|
|
1779
|
+
maxRowIndex = Math.max(maxRowIndex, findRowIndex + cell.rowspan - 1);
|
|
1780
|
+
findRowRange(maxRowIndex);
|
|
1781
|
+
}
|
|
1782
|
+
return acc;
|
|
1783
|
+
}, []);
|
|
1784
|
+
combinedIndexes.some(combinedIndex => {
|
|
1785
|
+
const {
|
|
1786
|
+
rowIndex: mainCellRowIndex,
|
|
1787
|
+
currentCell
|
|
1788
|
+
} = searchCombinedMainCell(table, findRowIndex, combinedIndex);
|
|
1789
|
+
if (minRowIndex > mainCellRowIndex) {
|
|
1790
|
+
minRowIndex = mainCellRowIndex;
|
|
1791
|
+
findRowRange(minRowIndex, 0);
|
|
1792
|
+
return false;
|
|
1793
|
+
} else if (maxRowIndex < mainCellRowIndex + currentCell.rowspan - 1) {
|
|
1794
|
+
maxRowIndex = mainCellRowIndex + currentCell.rowspan - 1;
|
|
1795
|
+
findRowRange(maxRowIndex, 0);
|
|
1796
|
+
return false;
|
|
1797
|
+
}
|
|
1798
|
+
return false;
|
|
1799
|
+
});
|
|
1800
|
+
};
|
|
1801
|
+
findRowRange(rowIndex);
|
|
1802
|
+
return {
|
|
1803
|
+
minRowIndex,
|
|
1804
|
+
maxRowIndex,
|
|
1805
|
+
minColIndex,
|
|
1806
|
+
maxColIndex
|
|
1807
|
+
};
|
|
1808
|
+
};
|
|
1809
|
+
export const getTableColumnSelectedRange = (table, columnIndex) => {
|
|
1810
|
+
let minRowIndex = 0;
|
|
1811
|
+
let maxRowIndex = table.children.length - 1;
|
|
1812
|
+
let minColIndex = columnIndex;
|
|
1813
|
+
let maxColIndex = columnIndex;
|
|
1814
|
+
const findColRange = findColIndex => {
|
|
1815
|
+
let combinedIndexes = [];
|
|
1816
|
+
table.children.forEach((row, rowIndex) => {
|
|
1817
|
+
const cell = row.children[findColIndex];
|
|
1818
|
+
if (cell.is_combined) combinedIndexes.push(rowIndex);
|
|
1819
|
+
if (cell.colspan > 1) {
|
|
1820
|
+
maxColIndex = Math.max(maxColIndex, findColIndex + cell.colspan - 1);
|
|
1821
|
+
findColRange(maxColIndex);
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1824
|
+
combinedIndexes.some(combinedIndex => {
|
|
1825
|
+
const {
|
|
1826
|
+
cellIndex: mainCellColIndex,
|
|
1827
|
+
currentCell
|
|
1828
|
+
} = searchCombinedMainCell(table, combinedIndex, findColIndex);
|
|
1829
|
+
if (minColIndex > mainCellColIndex) {
|
|
1830
|
+
minColIndex = mainCellColIndex;
|
|
1831
|
+
findColRange(minColIndex, 0);
|
|
1832
|
+
return false;
|
|
1833
|
+
} else if (maxColIndex < mainCellColIndex + currentCell.colspan - 1) {
|
|
1834
|
+
maxColIndex = mainCellColIndex + currentCell.colspan - 1;
|
|
1835
|
+
findColRange(maxColIndex, 0);
|
|
1836
|
+
return false;
|
|
1837
|
+
}
|
|
1838
|
+
return false;
|
|
1839
|
+
});
|
|
1840
|
+
};
|
|
1841
|
+
findColRange(columnIndex);
|
|
1842
|
+
return {
|
|
1843
|
+
minRowIndex,
|
|
1844
|
+
maxRowIndex,
|
|
1845
|
+
minColIndex,
|
|
1846
|
+
maxColIndex
|
|
1847
|
+
};
|
|
1537
1848
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../../render/index.css';
|
|
3
|
+
const ColumnDragHandler = _ref => {
|
|
4
|
+
let {
|
|
5
|
+
left
|
|
6
|
+
} = _ref;
|
|
7
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
8
|
+
className: "table-cell-width-just position-absolute resizing",
|
|
9
|
+
contentEditable: false,
|
|
10
|
+
style: {
|
|
11
|
+
left
|
|
12
|
+
}
|
|
13
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
14
|
+
className: "table-cell-width-just-color-tip"
|
|
15
|
+
}));
|
|
16
|
+
};
|
|
17
|
+
export default ColumnDragHandler;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import RowDragHandler from './row-drag-handler';
|
|
3
|
+
import ColumnDragHandler from './column-drag-handler';
|
|
4
|
+
import EventBus from '../../../../../utils/event-bus';
|
|
5
|
+
import { INTERNAL_EVENT } from '../../../../../constants';
|
|
6
|
+
import { DRAG_HANDLER_ROW, DRAG_HANDLER_COLUMN } from '../../constants';
|
|
7
|
+
const DragHandlers = _ref => {
|
|
8
|
+
let {
|
|
9
|
+
table
|
|
10
|
+
} = _ref;
|
|
11
|
+
const [linePosition, setLinePosition] = useState({
|
|
12
|
+
top: 0,
|
|
13
|
+
left: 0
|
|
14
|
+
});
|
|
15
|
+
const [displayType, setDisplayType] = useState('');
|
|
16
|
+
const tableID = table.id;
|
|
17
|
+
const handleShowResizeHandler = useCallback(_ref2 => {
|
|
18
|
+
let {
|
|
19
|
+
displayType,
|
|
20
|
+
left,
|
|
21
|
+
top,
|
|
22
|
+
tableId
|
|
23
|
+
} = _ref2;
|
|
24
|
+
if (tableId !== tableID) return;
|
|
25
|
+
const maskOffset = 2;
|
|
26
|
+
setLinePosition({
|
|
27
|
+
top,
|
|
28
|
+
left: left - maskOffset
|
|
29
|
+
});
|
|
30
|
+
setDisplayType(displayType);
|
|
31
|
+
}, [tableID]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const eventBus = EventBus.getInstance();
|
|
34
|
+
const unsubscribe = eventBus.subscribe(INTERNAL_EVENT.TABLE_SHOW_DRAG_HANDLER, handleShowResizeHandler);
|
|
35
|
+
return () => {
|
|
36
|
+
unsubscribe();
|
|
37
|
+
};
|
|
38
|
+
}, [handleShowResizeHandler]);
|
|
39
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, displayType === DRAG_HANDLER_ROW && /*#__PURE__*/React.createElement(RowDragHandler, {
|
|
40
|
+
top: linePosition.top
|
|
41
|
+
}), displayType === DRAG_HANDLER_COLUMN && /*#__PURE__*/React.createElement(ColumnDragHandler, {
|
|
42
|
+
left: linePosition.left
|
|
43
|
+
}));
|
|
44
|
+
};
|
|
45
|
+
export default DragHandlers;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../../render/index.css';
|
|
3
|
+
const RowDragHandler = _ref => {
|
|
4
|
+
let {
|
|
5
|
+
top
|
|
6
|
+
} = _ref;
|
|
7
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
8
|
+
className: "table-row-height-just position-absolute resizing",
|
|
9
|
+
contentEditable: false,
|
|
10
|
+
style: {
|
|
11
|
+
top
|
|
12
|
+
}
|
|
13
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
14
|
+
className: "table-row-height-just-color-tip"
|
|
15
|
+
}));
|
|
16
|
+
};
|
|
17
|
+
export default RowDragHandler;
|
|
@@ -16,6 +16,7 @@ import TableRoot from './table-root';
|
|
|
16
16
|
import TableHeader from './table-header';
|
|
17
17
|
import { findPath } from '../../../core';
|
|
18
18
|
import ResizeMask from './resize-mask';
|
|
19
|
+
import DragHandlers from './drag-handlers';
|
|
19
20
|
import './index.css';
|
|
20
21
|
import './alternate-color.css';
|
|
21
22
|
const Table = _ref => {
|
|
@@ -40,6 +41,7 @@ const Table = _ref => {
|
|
|
40
41
|
const [resizeCellMaskInfo, setResizeCellMaskInfo] = useState({});
|
|
41
42
|
const [isShowResizeHandlers, setIsShowResizeHandlers] = useState(false);
|
|
42
43
|
const [isDraggingResizeHandler, setIsDraggingResizeHandler] = useState(false);
|
|
44
|
+
const [isDragMove, setIsDragMove] = useState(false);
|
|
43
45
|
const onMouseDown = useCallback(event => {
|
|
44
46
|
if (event.button !== 0) return; // right click not deal
|
|
45
47
|
setIsSettingSelectRange(true);
|
|
@@ -68,12 +70,12 @@ const Table = _ref => {
|
|
|
68
70
|
setSelectedRange(range);
|
|
69
71
|
setTableSelectedRange(editor, range);
|
|
70
72
|
const {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
minRowIndex,
|
|
74
|
+
minColIndex
|
|
73
75
|
} = range;
|
|
74
76
|
const selection = {
|
|
75
77
|
offset: 0,
|
|
76
|
-
path: [...path,
|
|
78
|
+
path: [...path, minRowIndex, minColIndex, 0]
|
|
77
79
|
};
|
|
78
80
|
Transforms.setSelection(editor, {
|
|
79
81
|
anchor: selection,
|
|
@@ -200,8 +202,10 @@ const Table = _ref => {
|
|
|
200
202
|
columns: columns,
|
|
201
203
|
attributes: attributes
|
|
202
204
|
}, isSelected && /*#__PURE__*/React.createElement(TableHeader, {
|
|
205
|
+
editor: editor,
|
|
203
206
|
table: element,
|
|
204
|
-
setSelectedRange: setSelectedRangeByClick
|
|
207
|
+
setSelectedRange: setSelectedRangeByClick,
|
|
208
|
+
setIsDragMove: setIsDragMove
|
|
205
209
|
}), /*#__PURE__*/React.createElement("div", {
|
|
206
210
|
className: classnames(tableContainerClassName),
|
|
207
211
|
style: style,
|
|
@@ -220,6 +224,8 @@ const Table = _ref => {
|
|
|
220
224
|
element: element,
|
|
221
225
|
resizeCellMaskInfo: resizeCellMaskInfo,
|
|
222
226
|
isDraggingResizeHandler: isDraggingResizeHandler
|
|
227
|
+
}), isDragMove && /*#__PURE__*/React.createElement(DragHandlers, {
|
|
228
|
+
table: element
|
|
223
229
|
}))))));
|
|
224
230
|
};
|
|
225
231
|
function renderTable(props) {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
-
import React, { useCallback, useMemo } from 'react';
|
|
2
|
+
import React, { useCallback, useMemo, useRef } from 'react';
|
|
3
3
|
import classnames from 'classnames';
|
|
4
4
|
import { useSlateStatic, useReadOnly } from '@seafile/slate-react';
|
|
5
5
|
import { Editor, Transforms } from '@seafile/slate';
|
|
6
6
|
import ObjectUtils from '../../../../utils/object-utils';
|
|
7
7
|
import { findPath, focusEditor } from '../../../core';
|
|
8
8
|
import { useTableSelectedRangeContext } from './hooks';
|
|
9
|
-
import { EMPTY_SELECTED_RANGE, SELECTED_TABLE_CELL_BACKGROUND_COLOR, TABLE_CELL_STYLE } from '../constants';
|
|
10
|
-
import { colorBlend, getHighlightClass } from '../helpers';
|
|
9
|
+
import { CELL_SELECTED, DRAG_HANDLER_COLUMN, EMPTY_SELECTED_RANGE, SELECTED_TABLE_CELL_BACKGROUND_COLOR, TABLE_CELL_STYLE } from '../constants';
|
|
10
|
+
import { colorBlend, getHighlightClass, getResizeMaskCellInfo, getTableDragType, moveColumns, moveRows, isHideDragHandlerLine, getTableSelectedRangeAfterDrag } from '../helpers';
|
|
11
11
|
import EventBus from '../../../../utils/event-bus';
|
|
12
12
|
import { INTERNAL_EVENT } from '../../../../constants';
|
|
13
|
+
import { TABLE_DRAG_KEY } from '../../../constants';
|
|
13
14
|
const TableCell = _ref => {
|
|
14
15
|
let {
|
|
15
16
|
attributes,
|
|
@@ -36,6 +37,9 @@ const TableCell = _ref => {
|
|
|
36
37
|
const isSelectedLastCell = isSelected && cellIndex === maxColIndex;
|
|
37
38
|
const isSelectedFirstRow = isSelected && rowIndex === minRowIndex;
|
|
38
39
|
const isSelectedLastRow = isSelected && rowIndex === maxRowIndex;
|
|
40
|
+
const eventBus = EventBus.getInstance();
|
|
41
|
+
const tableId = tableEntry[0].id;
|
|
42
|
+
const canDrop = useRef(false);
|
|
39
43
|
const onContextMenu = useCallback(event => {
|
|
40
44
|
const path = findPath(editor, element);
|
|
41
45
|
focusEditor(editor, path);
|
|
@@ -74,8 +78,6 @@ const TableCell = _ref => {
|
|
|
74
78
|
style = _objectSpread(_objectSpread({}, element.style), style);
|
|
75
79
|
}
|
|
76
80
|
const onMouseMove = mouseDownEvent => {
|
|
77
|
-
const eventBus = EventBus.getInstance();
|
|
78
|
-
const tableId = tableEntry[0].id;
|
|
79
81
|
eventBus.dispatch(INTERNAL_EVENT.TABLE_CELL_MOUSE_ENTER, {
|
|
80
82
|
mouseDownEvent,
|
|
81
83
|
cell: element,
|
|
@@ -86,10 +88,54 @@ const TableCell = _ref => {
|
|
|
86
88
|
};
|
|
87
89
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
88
90
|
const highlightClass = useMemo(() => getHighlightClass(editor, cellPath), []);
|
|
91
|
+
const onDragOver = useCallback(event => {
|
|
92
|
+
const {
|
|
93
|
+
target
|
|
94
|
+
} = event;
|
|
95
|
+
const table = tableEntry[0];
|
|
96
|
+
const displayType = getTableDragType(table, selectedRange);
|
|
97
|
+
const resizeMaskCellInfo = getResizeMaskCellInfo(editor, table, rowIndex, cellIndex);
|
|
98
|
+
const cellInfo = _objectSpread(_objectSpread({}, resizeMaskCellInfo), {}, {
|
|
99
|
+
displayType,
|
|
100
|
+
mouseDownEvent: event,
|
|
101
|
+
tableId
|
|
102
|
+
});
|
|
103
|
+
const isHideHandleLine = isHideDragHandlerLine(editor, displayType, table, cellPath);
|
|
104
|
+
canDrop.current = !isHideHandleLine;
|
|
105
|
+
if (target.classList.contains(CELL_SELECTED) || isHideHandleLine) {
|
|
106
|
+
cellInfo.top = -9999;
|
|
107
|
+
cellInfo.left = -9999;
|
|
108
|
+
}
|
|
109
|
+
eventBus.dispatch(INTERNAL_EVENT.TABLE_SHOW_DRAG_HANDLER, cellInfo);
|
|
110
|
+
}, [cellIndex, cellPath, editor, eventBus, rowIndex, selectedRange, tableEntry, tableId]);
|
|
111
|
+
const handleDrop = useCallback(event => {
|
|
112
|
+
event.stopPropagation();
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
if (!canDrop.current) return;
|
|
115
|
+
const {
|
|
116
|
+
target
|
|
117
|
+
} = event;
|
|
118
|
+
if (target.classList.contains(CELL_SELECTED)) return;
|
|
119
|
+
const dragDataJson = event.dataTransfer.getData(TABLE_DRAG_KEY);
|
|
120
|
+
if (!dragDataJson) return;
|
|
121
|
+
const dragData = JSON.parse(dragDataJson);
|
|
122
|
+
if (dragData) {
|
|
123
|
+
const {
|
|
124
|
+
tableId: dragTableId,
|
|
125
|
+
startIndex,
|
|
126
|
+
endIndex,
|
|
127
|
+
dragType
|
|
128
|
+
} = dragData;
|
|
129
|
+
if (dragTableId !== tableId) return;
|
|
130
|
+
dragType === DRAG_HANDLER_COLUMN ? moveColumns(editor, cellIndex, startIndex, endIndex) : moveRows(editor, rowIndex, startIndex, endIndex);
|
|
131
|
+
const range = dragType === DRAG_HANDLER_COLUMN ? getTableSelectedRangeAfterDrag(tableEntry[0], dragType, cellIndex, startIndex, endIndex) : getTableSelectedRangeAfterDrag(tableEntry[0], dragType, rowIndex, startIndex, endIndex);
|
|
132
|
+
eventBus.dispatch(INTERNAL_EVENT.SET_TABLE_SELECT_RANGE, tableEntry[0], range);
|
|
133
|
+
}
|
|
134
|
+
}, [cellIndex, editor, eventBus, rowIndex, tableEntry, tableId]);
|
|
89
135
|
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
90
136
|
style: _objectSpread(_objectSpread({}, element.style), style),
|
|
91
137
|
className: classnames('table-cell', attributes.className, highlightClass, {
|
|
92
|
-
|
|
138
|
+
[CELL_SELECTED]: isSelected,
|
|
93
139
|
'cell-light-height-left-border': isSelectedFirstCell,
|
|
94
140
|
'cell-light-height-right-border': isSelectedLastCell,
|
|
95
141
|
'cell-light-height-top-border': isSelectedFirstRow,
|
|
@@ -99,7 +145,9 @@ const TableCell = _ref => {
|
|
|
99
145
|
"row-index": rowIndex,
|
|
100
146
|
"cell-index": cellIndex,
|
|
101
147
|
onContextMenu: onContextMenu,
|
|
102
|
-
onMouseMove: onMouseMove
|
|
148
|
+
onMouseMove: onMouseMove,
|
|
149
|
+
onDragOver: onDragOver,
|
|
150
|
+
onDrop: handleDrop
|
|
103
151
|
}), /*#__PURE__*/React.createElement("div", {
|
|
104
152
|
className: "sdoc-cell-container"
|
|
105
153
|
}, children));
|
package/dist/basic-sdk/extension/plugins/table/render/table-header/columns-header/column-header.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useCallback } from 'react';
|
|
1
|
+
import React, { useRef, useCallback, useMemo } from 'react';
|
|
2
2
|
import classnames from 'classnames';
|
|
3
3
|
import { useSlateStatic } from '@seafile/slate-react';
|
|
4
4
|
import ObjectUtils from '../../../../../../utils/object-utils';
|
|
@@ -13,15 +13,35 @@ const ColumnHeader = _ref => {
|
|
|
13
13
|
setAddIconPosition,
|
|
14
14
|
setInsertColumnIndex,
|
|
15
15
|
selectRange,
|
|
16
|
-
tableSize
|
|
16
|
+
tableSize,
|
|
17
|
+
handleDragStart,
|
|
18
|
+
handleDragEnd
|
|
17
19
|
} = _ref;
|
|
18
20
|
const editor = useSlateStatic();
|
|
21
|
+
const {
|
|
22
|
+
tableSelectedRange
|
|
23
|
+
} = editor;
|
|
19
24
|
const columnHeaderRef = useRef(null);
|
|
20
25
|
const tableRoot = useTableRootContext();
|
|
21
26
|
const selectedRange = useTableSelectedRangeContext();
|
|
22
27
|
const currentCell = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
|
|
23
28
|
const currentCellPath = currentCell ? findPath(editor, currentCell, [-1, -1]) : [-1, -1];
|
|
24
29
|
const pathLength = currentCellPath.length;
|
|
30
|
+
const canDrag = useMemo(() => {
|
|
31
|
+
const {
|
|
32
|
+
minRowIndex,
|
|
33
|
+
maxRowIndex,
|
|
34
|
+
minColIndex,
|
|
35
|
+
maxColIndex
|
|
36
|
+
} = tableSelectedRange;
|
|
37
|
+
const [rowNum] = tableSize;
|
|
38
|
+
const isSelectColumn = minRowIndex === 0 && maxRowIndex === rowNum - 1;
|
|
39
|
+
const isSelectRangeColumn = minColIndex <= index && index <= maxColIndex;
|
|
40
|
+
const isSelectAllColumn = minColIndex === 0 && maxColIndex === tableSize[1] - 1;
|
|
41
|
+
if (tableSize[1] === 1 || isSelectAllColumn) return false;
|
|
42
|
+
if (isSelectColumn && isSelectRangeColumn) return true;
|
|
43
|
+
return false;
|
|
44
|
+
}, [index, tableSelectedRange, tableSize]);
|
|
25
45
|
const onMouseMove = useCallback(event => {
|
|
26
46
|
const {
|
|
27
47
|
left,
|
|
@@ -58,15 +78,19 @@ const ColumnHeader = _ref => {
|
|
|
58
78
|
return /*#__PURE__*/React.createElement("div", {
|
|
59
79
|
className: classnames('sdoc-table-column-header h-100', {
|
|
60
80
|
'range-selected': isSelectedAColumn && isSelectedRangeColumn,
|
|
61
|
-
'range-selected-tip': !isSelectedAColumn && isSelectedRangeColumn || currentCellPath[pathLength - 1] === index
|
|
81
|
+
'range-selected-tip': !isSelectedAColumn && isSelectedRangeColumn || currentCellPath[pathLength - 1] === index,
|
|
82
|
+
'drag': canDrag
|
|
62
83
|
}),
|
|
63
84
|
ref: columnHeaderRef,
|
|
64
85
|
onMouseMove: onMouseMove,
|
|
65
86
|
onMouseLeave: onMouseLeave,
|
|
66
87
|
onClick: () => selectRange(index),
|
|
88
|
+
onDragStart: handleDragStart,
|
|
89
|
+
onDragEnd: handleDragEnd,
|
|
67
90
|
style: {
|
|
68
91
|
width: column.width
|
|
69
|
-
}
|
|
92
|
+
},
|
|
93
|
+
draggable: canDrag
|
|
70
94
|
});
|
|
71
95
|
};
|
|
72
96
|
export default ColumnHeader;
|
|
@@ -9,7 +9,9 @@ const ColumnsHeader = _ref => {
|
|
|
9
9
|
let {
|
|
10
10
|
table,
|
|
11
11
|
selectRange,
|
|
12
|
-
tableSize
|
|
12
|
+
tableSize,
|
|
13
|
+
handleDragStart,
|
|
14
|
+
handleDragEnd
|
|
13
15
|
} = _ref;
|
|
14
16
|
const editor = useSlateStatic();
|
|
15
17
|
const [insertColumnIndex, setInsertColumnIndex] = useState(0);
|
|
@@ -55,7 +57,9 @@ const ColumnsHeader = _ref => {
|
|
|
55
57
|
tableSize: tableSize,
|
|
56
58
|
setAddIconPosition: setAddIconPosition,
|
|
57
59
|
setInsertColumnIndex: setInsertColumnIndex,
|
|
58
|
-
selectRange: selectRange
|
|
60
|
+
selectRange: selectRange,
|
|
61
|
+
handleDragStart: handleDragStart,
|
|
62
|
+
handleDragEnd: handleDragEnd
|
|
59
63
|
});
|
|
60
64
|
}))), addIconPosition && /*#__PURE__*/React.createElement("div", {
|
|
61
65
|
className: classnames('position-fixed sdoc-table-add-element-icon-content', {
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
flex-shrink: 0;
|
|
11
11
|
border-right: 1px solid rgba(0, 0, 0, .08);
|
|
12
12
|
background-color: rgb(243, 245, 247);
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.sdoc-table-wrapper .sdoc-table-columns-header .sdoc-table-column-header.drag {
|
|
17
|
+
cursor: move;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
/* row-header */
|
|
@@ -28,6 +33,11 @@
|
|
|
28
33
|
width: 100%;
|
|
29
34
|
background-color: rgb(243, 245, 247);
|
|
30
35
|
border-bottom: 1px solid rgba(0, 0, 0, .08);
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.sdoc-table-wrapper .sdoc-table-rows-header .sdoc-table-row-header.drag {
|
|
40
|
+
cursor: move;
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
.sdoc-table-wrapper .sdoc-table-rows-columns-header {
|
|
@@ -71,3 +81,4 @@
|
|
|
71
81
|
.sdoc-table-wrapper .sdoc-table-add-element-icon-content:hover {
|
|
72
82
|
cursor: pointer;
|
|
73
83
|
}
|
|
84
|
+
|
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
2
3
|
import ColumnsHeader from './columns-header';
|
|
3
4
|
import RowsHeader from './rows-header';
|
|
4
|
-
import { useResizeHandlersContext } from '../hooks';
|
|
5
|
+
import { useResizeHandlersContext, useTableSelectedRangeContext } from '../hooks';
|
|
5
6
|
import RowsColumnsHeader from './rows-columns-header';
|
|
7
|
+
import { generateDragMoveElement, getTableDragType, getTableRowSelectedRange, getTableColumnSelectedRange } from '../../helpers';
|
|
8
|
+
import { DRAG_HANDLER_COLUMN, DRAG_HANDLER_ROW, EMPTY_SELECTED_RANGE } from '../../constants';
|
|
9
|
+
import { TABLE_DRAG_KEY } from '../../../../constants';
|
|
6
10
|
import './index.css';
|
|
7
11
|
const TableHeader = _ref => {
|
|
8
12
|
let {
|
|
13
|
+
editor,
|
|
9
14
|
table,
|
|
10
|
-
setSelectedRange
|
|
15
|
+
setSelectedRange,
|
|
16
|
+
setIsDragMove
|
|
11
17
|
} = _ref;
|
|
18
|
+
const {
|
|
19
|
+
t
|
|
20
|
+
} = useTranslation();
|
|
12
21
|
const columns = useResizeHandlersContext();
|
|
22
|
+
const selectedRange = useTableSelectedRangeContext() || EMPTY_SELECTED_RANGE;
|
|
13
23
|
const selectColumn = useCallback(columnIndex => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
minRowIndex: 0,
|
|
17
|
-
maxRowIndex: rowsCount - 1,
|
|
18
|
-
minColIndex: columnIndex,
|
|
19
|
-
maxColIndex: columnIndex
|
|
20
|
-
};
|
|
21
|
-
setSelectedRange(range);
|
|
24
|
+
const selectedRange = getTableColumnSelectedRange(table, columnIndex);
|
|
25
|
+
setSelectedRange(selectedRange);
|
|
22
26
|
|
|
23
27
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
28
|
}, [table, columns]);
|
|
25
29
|
const selectRow = useCallback(rowIndex => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
minRowIndex: rowIndex,
|
|
29
|
-
maxRowIndex: rowIndex,
|
|
30
|
-
minColIndex: 0,
|
|
31
|
-
maxColIndex: columnsCount - 1
|
|
32
|
-
};
|
|
33
|
-
setSelectedRange(range);
|
|
30
|
+
const selectedRange = getTableRowSelectedRange(table, rowIndex);
|
|
31
|
+
setSelectedRange(selectedRange);
|
|
34
32
|
|
|
35
33
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
36
34
|
}, [table, columns]);
|
|
@@ -48,17 +46,62 @@ const TableHeader = _ref => {
|
|
|
48
46
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
47
|
}, [table, columns]);
|
|
50
48
|
const tableSize = [table.children.length, columns.length];
|
|
49
|
+
const handleDragStart = event => {
|
|
50
|
+
event.stopPropagation();
|
|
51
|
+
const {
|
|
52
|
+
tableSelectedRange
|
|
53
|
+
} = editor;
|
|
54
|
+
const tableId = table.id;
|
|
55
|
+
const {
|
|
56
|
+
minColIndex,
|
|
57
|
+
maxColIndex,
|
|
58
|
+
minRowIndex,
|
|
59
|
+
maxRowIndex
|
|
60
|
+
} = tableSelectedRange;
|
|
61
|
+
const dragType = getTableDragType(table, selectedRange);
|
|
62
|
+
const startIndex = dragType === DRAG_HANDLER_COLUMN ? minColIndex : minRowIndex;
|
|
63
|
+
const endIndex = dragType === DRAG_HANDLER_ROW ? maxRowIndex : maxColIndex;
|
|
64
|
+
const data = {
|
|
65
|
+
tableId,
|
|
66
|
+
dragType,
|
|
67
|
+
startIndex,
|
|
68
|
+
endIndex
|
|
69
|
+
};
|
|
70
|
+
const dragData = JSON.stringify(data);
|
|
71
|
+
event.dataTransfer.setData(TABLE_DRAG_KEY, dragData);
|
|
72
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
73
|
+
const moveCount = endIndex - startIndex + 1;
|
|
74
|
+
const tipText = dragType === DRAG_HANDLER_COLUMN ? t('Move_column_count', {
|
|
75
|
+
count: moveCount
|
|
76
|
+
}) : t('Move_row_count', {
|
|
77
|
+
count: moveCount
|
|
78
|
+
});
|
|
79
|
+
const dragImage = generateDragMoveElement(tipText);
|
|
80
|
+
event.dataTransfer.setDragImage(dragImage, 0, 0);
|
|
81
|
+
setIsDragMove(true);
|
|
82
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const handleDragEnd = event => {
|
|
86
|
+
setIsDragMove(false);
|
|
87
|
+
const indicator = document.getElementById('sdoc-drag-image');
|
|
88
|
+
indicator.style.display = 'none';
|
|
89
|
+
};
|
|
51
90
|
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(ColumnsHeader, {
|
|
52
91
|
table: table,
|
|
53
92
|
selectRange: selectColumn,
|
|
54
|
-
tableSize: tableSize
|
|
93
|
+
tableSize: tableSize,
|
|
94
|
+
handleDragStart: handleDragStart,
|
|
95
|
+
handleDragEnd: handleDragEnd
|
|
55
96
|
}), /*#__PURE__*/React.createElement(RowsColumnsHeader, {
|
|
56
97
|
selectRange: selectTable,
|
|
57
98
|
tableSize: tableSize
|
|
58
99
|
}), /*#__PURE__*/React.createElement(RowsHeader, {
|
|
59
100
|
table: table,
|
|
60
101
|
selectRange: selectRow,
|
|
61
|
-
tableSize: tableSize
|
|
102
|
+
tableSize: tableSize,
|
|
103
|
+
handleDragStart: handleDragStart,
|
|
104
|
+
handleDragEnd: handleDragEnd
|
|
62
105
|
}));
|
|
63
106
|
};
|
|
64
107
|
export default TableHeader;
|
|
@@ -9,7 +9,9 @@ const RowsHeader = _ref => {
|
|
|
9
9
|
let {
|
|
10
10
|
table,
|
|
11
11
|
selectRange,
|
|
12
|
-
tableSize
|
|
12
|
+
tableSize,
|
|
13
|
+
handleDragStart,
|
|
14
|
+
handleDragEnd
|
|
13
15
|
} = _ref;
|
|
14
16
|
const editor = useSlateStatic();
|
|
15
17
|
const {
|
|
@@ -54,7 +56,9 @@ const RowsHeader = _ref => {
|
|
|
54
56
|
tableSize: tableSize,
|
|
55
57
|
setAddIconPosition: setAddIconPosition,
|
|
56
58
|
setInsertRowIndex: setInsertRowIndex,
|
|
57
|
-
selectRange: selectRange
|
|
59
|
+
selectRange: selectRange,
|
|
60
|
+
handleDragStart: handleDragStart,
|
|
61
|
+
handleDragEnd: handleDragEnd
|
|
58
62
|
});
|
|
59
63
|
})), addIconPosition && /*#__PURE__*/React.createElement("div", {
|
|
60
64
|
className: classnames('position-fixed sdoc-table-add-element-icon-content', {
|
package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useCallback, useState, useEffect } from 'react';
|
|
1
|
+
import React, { useRef, useCallback, useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { useSlateStatic } from '@seafile/slate-react';
|
|
3
3
|
import classnames from 'classnames';
|
|
4
4
|
import ObjectUtils from '../../../../../../utils/object-utils';
|
|
@@ -15,9 +15,14 @@ const RowHeader = _ref => {
|
|
|
15
15
|
setAddIconPosition,
|
|
16
16
|
setInsertRowIndex,
|
|
17
17
|
selectRange,
|
|
18
|
-
tableSize
|
|
18
|
+
tableSize,
|
|
19
|
+
handleDragStart,
|
|
20
|
+
handleDragEnd
|
|
19
21
|
} = _ref;
|
|
20
22
|
const editor = useSlateStatic();
|
|
23
|
+
const {
|
|
24
|
+
tableSelectedRange
|
|
25
|
+
} = editor;
|
|
21
26
|
useEffect(() => {
|
|
22
27
|
setRowHeight(getRowDomHeight(editor, row));
|
|
23
28
|
}, [editor, row, tableSize]);
|
|
@@ -30,6 +35,21 @@ const RowHeader = _ref => {
|
|
|
30
35
|
const currentCell = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
|
|
31
36
|
const currentCellPath = currentCell ? findPath(editor, currentCell, [-1, -1]) : [-1, -1];
|
|
32
37
|
const pathLength = currentCellPath.length;
|
|
38
|
+
const canDrag = useMemo(() => {
|
|
39
|
+
const {
|
|
40
|
+
minRowIndex,
|
|
41
|
+
maxRowIndex,
|
|
42
|
+
minColIndex,
|
|
43
|
+
maxColIndex
|
|
44
|
+
} = tableSelectedRange;
|
|
45
|
+
const [, colNum] = tableSize;
|
|
46
|
+
const isSelectRow = minColIndex === 0 && maxColIndex === colNum - 1;
|
|
47
|
+
const isSelectRangeRow = minRowIndex <= index && index <= maxRowIndex;
|
|
48
|
+
const isSelectAllRows = minRowIndex === 0 && maxRowIndex === tableSize[0] - 1;
|
|
49
|
+
if (tableSize[0] === 1 || isSelectAllRows) return false;
|
|
50
|
+
if (isSelectRow && isSelectRangeRow) return true;
|
|
51
|
+
return false;
|
|
52
|
+
}, [index, tableSelectedRange, tableSize]);
|
|
33
53
|
useEffect(() => {
|
|
34
54
|
if (elementHasImage(row)) {
|
|
35
55
|
// There is a delay in image loading
|
|
@@ -80,7 +100,8 @@ const RowHeader = _ref => {
|
|
|
80
100
|
return /*#__PURE__*/React.createElement("div", {
|
|
81
101
|
className: classnames('sdoc-table-row-header', {
|
|
82
102
|
'range-selected': isSelectedARow && isSelectedSomeRow,
|
|
83
|
-
'range-selected-tip': !isSelectedARow && isSelectedSomeRow || currentCellPath[pathLength - 2] === index
|
|
103
|
+
'range-selected-tip': !isSelectedARow && isSelectedSomeRow || currentCellPath[pathLength - 2] === index,
|
|
104
|
+
'drag': canDrag
|
|
84
105
|
}),
|
|
85
106
|
style: {
|
|
86
107
|
height: rowHeight
|
|
@@ -88,7 +109,10 @@ const RowHeader = _ref => {
|
|
|
88
109
|
ref: rowHeaderRef,
|
|
89
110
|
onClick: () => selectRange(index),
|
|
90
111
|
onMouseMove: onMouseMove,
|
|
91
|
-
onMouseLeave: onMouseLeave
|
|
112
|
+
onMouseLeave: onMouseLeave,
|
|
113
|
+
onDragStart: handleDragStart,
|
|
114
|
+
onDragEnd: handleDragEnd,
|
|
115
|
+
draggable: canDrag
|
|
92
116
|
});
|
|
93
117
|
};
|
|
94
118
|
export default RowHeader;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import EventBus from '../../../utils/event-bus';
|
|
2
2
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
3
|
+
import { TABLE_DRAG_KEY } from '../../constants';
|
|
3
4
|
export const onMouseEnter = (event, element) => {
|
|
4
5
|
event.stopPropagation();
|
|
5
6
|
const eventBus = EventBus.getInstance();
|
|
@@ -8,6 +9,8 @@ export const onMouseEnter = (event, element) => {
|
|
|
8
9
|
export const onDragOver = event => {
|
|
9
10
|
event.stopPropagation();
|
|
10
11
|
event.preventDefault();
|
|
12
|
+
const dragTypes = event.dataTransfer.types;
|
|
13
|
+
if (dragTypes.includes(TABLE_DRAG_KEY)) return;
|
|
11
14
|
const eventBus = EventBus.getInstance();
|
|
12
15
|
eventBus.dispatch(INTERNAL_EVENT.ON_DRAG_OVER_BLOCK, event);
|
|
13
16
|
};
|
|
@@ -9,7 +9,7 @@ import { focusEditor } from '../../core';
|
|
|
9
9
|
import { getDomTopHeight, setSelection, isVoidNode, getNodeEntry, isBlockquote, isList, onWrapListItem } from './helpers';
|
|
10
10
|
import { insertImageFiles } from '../../plugins/image/helpers';
|
|
11
11
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
12
|
-
import { CODE_BLOCK, TABLE, BLOCKQUOTE, CHECK_LIST_ITEM, CALL_OUT } from '../../constants';
|
|
12
|
+
import { CODE_BLOCK, TABLE, BLOCKQUOTE, CHECK_LIST_ITEM, CALL_OUT, TABLE_DRAG_KEY } from '../../constants';
|
|
13
13
|
import { getCalloutEntry } from '../../plugins/callout/helper';
|
|
14
14
|
import './index.css';
|
|
15
15
|
let sourceElement = null;
|
|
@@ -105,9 +105,11 @@ const SideToolbar = () => {
|
|
|
105
105
|
leaveElement.classList.remove('sdoc-draging');
|
|
106
106
|
}, []);
|
|
107
107
|
const drop = useCallback(event => {
|
|
108
|
+
const dragTypes = event.dataTransfer.types;
|
|
108
109
|
targetElement = event.currentTarget;
|
|
109
110
|
targetElement.classList.remove('sdoc-draging');
|
|
110
|
-
|
|
111
|
+
// Prevent dragging table data to the editor
|
|
112
|
+
if (dragTypes.includes(TABLE_DRAG_KEY)) return;
|
|
111
113
|
// Drag local image files to sdoc
|
|
112
114
|
if (event.dataTransfer.files.length > 0) {
|
|
113
115
|
const [, targetPath] = getNodeEntry(editor, targetElement);
|
package/package.json
CHANGED
|
@@ -14,15 +14,12 @@
|
|
|
14
14
|
/>
|
|
15
15
|
<missing-glyph />
|
|
16
16
|
|
|
17
|
-
<<<<<<< HEAD
|
|
18
17
|
<glyph glyph-name="sdoc-center-alignment" unicode="" d="M560 896v-128H832v-320h-272v-128H928v-320H560v-128h-96v128H96V320h368v128H192V768h272V896h96zM832 224H192v-128h640v128zM736 672H288v-128h448V672z" horiz-adv-x="1024" />
|
|
19
18
|
|
|
20
19
|
<glyph glyph-name="sdoc-bottom-alignment" unicode="" d="M0-64v96h1024v-96H0z m448 192V832H128v-704h320z m-96 96H224V736h128v-512z m544-96V640H576v-512h320z m-96 96h-128V544h128v-320z" horiz-adv-x="1024" />
|
|
21
20
|
|
|
22
21
|
<glyph glyph-name="sdoc-top-alignment" unicode="" d="M0 832v-96h1024V832H0z m448-192v-704H128V640h320z m-96-96H224v-512h128V544z m544 96v-512H576V640h320z m-96-96h-128v-320h128V544z" horiz-adv-x="1024" />
|
|
23
22
|
|
|
24
|
-
=======
|
|
25
|
-
>>>>>>> 6ce93a64 (feat: read all)
|
|
26
23
|
<glyph glyph-name="sdoc-all-read" unicode="" d="M883.2 768h121.6c9.6 0 19.2-9.6 19.2-19.2v-60.8c0-6.4-9.6-16-19.2-16h-121.6c-9.6 0-19.2 9.6-19.2 19.2V748.8c0 9.6 9.6 19.2 19.2 19.2z m-284.8-704h406.4c12.8 0 22.4-9.6 22.4-19.2v-60.8c0-9.6-9.6-19.2-22.4-19.2H598.4c-12.8 0-22.4 9.6-22.4 19.2v60.8c0 9.6 9.6 19.2 22.4 19.2z m403.2 352c12.8 0 22.4-9.6 22.4-19.2v-60.8c0-9.6-9.6-19.2-22.4-19.2h-246.4c-12.8 0-22.4 9.6-22.4 19.2v60.8c0 9.6 9.6 19.2 22.4 19.2h246.4zM761.6 860.8c-3.2 3.2-9.6 3.2-12.8 3.2-6.4 0-9.6-3.2-12.8-9.6L304 70.4 67.2 256c-9.6 6.4-22.4 3.2-28.8-6.4L0 188.8c-3.2-9.6 0-22.4 9.6-28.8l336-256L819.2 803.2c6.4 9.6 3.2 22.4-6.4 28.8l-51.2 28.8z" horiz-adv-x="1027" />
|
|
27
24
|
|
|
28
25
|
<glyph glyph-name="sdoc-freezed" unicode="" d="M512 384m-512 0a512 512 0 1 1 1024 0 512 512 0 1 1-1024 0ZM316.8 716.8c118.4 70.4 265.6 70.4 384 3.2s192-195.2 192-332.8c0-137.6-73.6-265.6-195.2-332.8-182.4-105.6-416-41.6-521.6 140.8S134.4 608 316.8 716.8z m348.8-604.8c137.6 80 195.2 249.6 131.2 396.8L259.2 195.20000000000005c92.8-124.8 268.8-163.2 406.4-83.2zM352 652.8c-137.6-80-192-249.6-128-393.6l537.6 310.4c-96 128-272 163.2-409.6 83.2z" horiz-adv-x="1024" />
|