@opensig/opendesign
Version:
213 lines (212 loc) • 8.05 kB
JavaScript
import { ref, watch, computed } from "vue";
import { useMounted, until } from "@vueuse/core";
import { isClient, isNil, isNumber } from "../_utils/is.mjs";
import { getElementRectByRAF } from "../_utils/dom.mjs";
import { getCellValue, getGroupColumns, isEmptyCell } from "./utils.mjs";
const getStaticWidth = (width, containerWidth) => {
if (isNil(width)) {
return width;
}
if (isNumber(width)) {
return width;
}
if (width.endsWith("%")) {
return Number.parseFloat(width) * containerWidth / 100;
}
return Number.parseFloat(width);
};
const useDataColumn = (options) => {
const { tableEl, containerWidth, defaultEmptyCellText, columns, data, spanMethod } = options;
const isMounted = useMounted();
const dataColumnMap = /* @__PURE__ */ new Map();
const dataColumns = ref([]);
const groupColumns = ref([]);
const fixColumnAfterMounted = () => {
if (!isClient || dataColumns.value.every(({ fixed, width, minWidth, maxWidth }) => [fixed, width, minWidth, maxWidth].every((v) => isNil(v)))) {
return;
}
until(() => dataColumns.value.every((column) => !!column.colRef) && data.value.length && tableEl.value && !!containerWidth.value).toBeTruthy().then(() => {
return Promise.all(
dataColumns.value.map(async (column) => {
var _a;
let width = (_a = column.colRef) == null ? void 0 : _a.style.width;
if (!width) {
width = getStaticWidth(column.width, containerWidth.value);
}
if (!width) {
width = await getElementRectByRAF(column.colRef).then((rect) => rect.width);
}
if (column.minWidth) {
column._minWidth = getStaticWidth(column.minWidth, containerWidth.value);
width = Math.max(width, column._minWidth);
}
if (column.maxWidth) {
column._maxWidth = getStaticWidth(column.maxWidth, containerWidth.value);
width = Math.min(width, column._maxWidth);
}
column.colRef.style.width = `${width}px`;
column.resizeWidth = await getElementRectByRAF(column.colRef).then((rect) => rect.width);
})
);
}).then(() => {
tableEl.value.style.tableLayout = "fixed";
const totalWidth = dataColumns.value.reduce((_width, column) => _width + column.resizeWidth, 0);
if (totalWidth < containerWidth.value) {
const lastCol = dataColumns.value[dataColumns.value.length - 1];
lastCol.resizeWidth += containerWidth.value - totalWidth;
lastCol.colRef.style.width = `${lastCol.resizeWidth}px`;
}
});
};
const parseColumns = () => {
const res = getGroupColumns({
isMounted: isMounted.value,
...options,
columnMap: dataColumnMap,
defaultFormatter: (_options) => {
if (isEmptyCell(_options.cellValue)) {
return defaultEmptyCellText.value;
}
return _options.cellValue.toString();
}
});
dataColumns.value = res.dataColumns;
groupColumns.value = res.groupColumns;
fixColumnAfterMounted();
};
watch(
() => [columns.value, isMounted.value, data.value],
() => parseColumns(),
{ immediate: true, deep: true }
);
watch(containerWidth, () => {
fixColumnAfterMounted();
});
const removedBodyCellsBySpan = computed(() => {
const toRemove = [];
data.value.forEach((row, rowIndex) => {
dataColumns.value.forEach((column, colIndex) => {
if (toRemove.some((v) => v.index === `${rowIndex}_${colIndex}`)) {
return;
}
const res = spanMethod.value({
row,
column,
// @ts-ignore
cellValue: getCellValue({ row, column }),
rowIndex,
colIndex
});
if ((res == null ? void 0 : res.colSpan) && res.colSpan > 1) {
for (let i = 0; i < res.colSpan - 1; i++) {
const targetColIndex = colIndex + i + 1;
if ((res == null ? void 0 : res.rowSpan) && res.rowSpan > 1) {
for (let j = 0; j < res.rowSpan - 1; j++) {
toRemove.push({ index: `${rowIndex + j + 1}_${targetColIndex}`, removedMethod: "rowspan", removedBy: column.key });
}
}
toRemove.push({ index: `${rowIndex}_${targetColIndex}`, removedMethod: "colspan", removedBy: column.key });
}
}
if ((res == null ? void 0 : res.rowSpan) && res.rowSpan > 1) {
for (let i = 0; i < res.rowSpan - 1; i++) {
toRemove.push({ index: `${rowIndex + i + 1}_${colIndex}`, removedMethod: "rowspan", removedBy: column.key });
}
}
});
});
return toRemove;
});
const isBodyCellRemoved = (rowIndex, colIndex) => {
return removedBodyCellsBySpan.value.some((v) => v.index === `${rowIndex}_${colIndex}`);
};
const isLastLeftFixedCell = (rowIndex, colIndex) => {
const column = dataColumns.value[colIndex];
if (column.fixed !== "left") {
return false;
}
let nextIndex = colIndex + 1;
while (nextIndex < dataColumns.value.length && dataColumns.value[nextIndex].fixed === "left") {
const nextCellRemoveInfo = removedBodyCellsBySpan.value.filter((v) => v.index === `${rowIndex}_${nextIndex}`);
if (!nextCellRemoveInfo.length) {
return false;
}
if (nextCellRemoveInfo.some((v) => v.removedMethod === "rowspan")) {
return false;
}
nextIndex++;
}
return true;
};
const isFirstRightFixedCell = (rowIndex, colIndex) => {
const column = dataColumns.value[colIndex];
if (column.fixed !== "right") {
return false;
}
let prevIndex = colIndex - 1;
while (prevIndex >= 0 && dataColumns.value[prevIndex].fixed === "right") {
const prevCellRemoveInfo = removedBodyCellsBySpan.value.filter((v) => v.index === `${rowIndex}_${prevIndex}`);
if (!prevCellRemoveInfo.length) {
return false;
}
if (prevCellRemoveInfo.some((v) => v.removedMethod === "rowspan")) {
return false;
}
prevIndex--;
}
return true;
};
const hasLeftFixedColumn = computed(() => dataColumns.value.some((v) => v.fixed === "left" || v.fixed === "right"));
const hasRightFixedColumn = computed(() => dataColumns.value.some((v) => v.fixed === "right"));
const resizingColumnKey = ref("");
let resizeStartX = 0;
let resizeStartWidth = 0;
const handleColumnResizerMouseMoving = (event) => {
const column = dataColumnMap.get(resizingColumnKey.value);
if (!(column == null ? void 0 : column.colRef)) {
return;
}
const deltaX = event.clientX - resizeStartX;
let width = Math.floor(resizeStartWidth + deltaX);
if (column._minWidth) {
width = Math.max(width, column._minWidth);
}
if (column._maxWidth) {
width = Math.min(width, column._maxWidth);
}
column.colRef.style.width = `${width}px`;
};
const handleColumnResizerMouseup = () => {
resizingColumnKey.value = "";
window.removeEventListener("mousemove", handleColumnResizerMouseMoving);
window.removeEventListener("mouseup", handleColumnResizerMouseup);
window.removeEventListener("contextmenu", handleColumnResizerMouseup);
};
const handleColumnResizerMousedown = ({ event, column }) => {
var _a;
event.preventDefault();
event.stopPropagation();
resizingColumnKey.value = column.key;
resizeStartX = event.clientX;
resizeStartWidth = ((_a = column.thRef) == null ? void 0 : _a.getBoundingClientRect().width) ?? 0;
window.addEventListener("mousemove", handleColumnResizerMouseMoving);
window.addEventListener("mouseup", handleColumnResizerMouseup);
window.addEventListener("contextmenu", handleColumnResizerMouseup);
};
return {
dataColumnMap,
dataColumns,
groupColumns,
removedBodyCellsBySpan,
isBodyCellRemoved,
isLastLeftFixedCell,
isFirstRightFixedCell,
hasLeftFixedColumn,
hasRightFixedColumn,
handleColumnResizerMousedown,
resizingColumnKey
};
};
export {
useDataColumn
};