feat(editor): table block supports drag-and-drop sorting (#10065)

close: BS-2477
This commit is contained in:
zzj3720
2025-02-10 14:14:53 +00:00
parent 964f2e1bfd
commit c78d6b81c6
15 changed files with 496 additions and 49 deletions
@@ -0,0 +1,83 @@
import type { OffsetList } from './types';
type CellOffsets = {
rows: OffsetList;
columns: OffsetList;
};
export const domToOffsets = (
element: HTMLElement,
rowSelector: string,
cellSelector: string
): CellOffsets | undefined => {
const rowDoms = Array.from(element.querySelectorAll(rowSelector));
const firstRowDom = rowDoms[0];
if (!firstRowDom) return;
const columnDoms = Array.from(firstRowDom.querySelectorAll(cellSelector));
const rows: OffsetList = [];
const columns: OffsetList = [];
for (let i = 0; i < rowDoms.length; i++) {
const rect = rowDoms[i].getBoundingClientRect();
if (!rect) continue;
if (i === 0) {
rows.push(rect.top);
}
rows.push(rect.bottom);
}
for (let i = 0; i < columnDoms.length; i++) {
const rect = columnDoms[i].getBoundingClientRect();
if (!rect) continue;
if (i === 0) {
columns.push(rect.left);
}
columns.push(rect.right);
}
return {
rows,
columns,
};
};
export const getIndexByPosition = (
positions: OffsetList,
offset: number,
reverse = false
) => {
if (reverse) {
return positions.slice(1).findIndex(p => offset <= p);
}
return positions.slice(0, -1).findLastIndex(p => offset >= p);
};
export const getRangeByPositions = (
positions: OffsetList,
start: number,
end: number
) => {
const startIndex = getIndexByPosition(positions, start, true);
const endIndex = getIndexByPosition(positions, end);
return {
start: startIndex,
end: endIndex,
};
};
export const getAreaByOffsets = (
offsets: CellOffsets,
top: number,
bottom: number,
left: number,
right: number
) => {
const { rows, columns } = offsets;
const startRow = getIndexByPosition(rows, top, true);
const endRow = getIndexByPosition(rows, bottom);
const startColumn = getIndexByPosition(columns, left, true);
const endColumn = getIndexByPosition(columns, right);
return {
top: startRow,
bottom: endRow,
left: startColumn,
right: endColumn,
};
};
@@ -0,0 +1,3 @@
export * from './cell-select';
export * from './linear-move';
export * from './types';
@@ -0,0 +1,38 @@
import type { OffsetList } from './types';
export const getTargetIndexByDraggingOffset = (
offsets: OffsetList,
draggingIndex: number,
indicatorLeft: number
) => {
const originalStart = offsets[draggingIndex];
const originalWidth = offsets[draggingIndex + 1] - originalStart;
const indicatorRight = indicatorLeft + originalWidth;
const isForward = indicatorLeft > originalStart;
const startIndex = isForward ? draggingIndex + 1 : 0;
const endIndex = isForward ? offsets.length - 1 : draggingIndex - 1;
if (isForward) {
for (let i = endIndex; i >= startIndex; i--) {
const blockCenter = (offsets[i] + offsets[i + 1]) / 2;
if (indicatorRight > blockCenter) {
return {
targetIndex: i,
isForward,
};
}
}
} else {
for (let i = startIndex; i <= endIndex; i++) {
const blockCenter = (offsets[i] + offsets[i + 1]) / 2;
if (indicatorLeft < blockCenter) {
return {
targetIndex: i,
isForward,
};
}
}
}
return {
targetIndex: undefined,
isForward,
};
};
@@ -0,0 +1 @@
export type OffsetList = number[];