UNPKG

@opensig/opendesign

Version:

213 lines (212 loc) 8.05 kB
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 };