UNPKG

vue-gantt-3

Version:

A gantt component for Vue 3

302 lines (301 loc) 11.8 kB
import { inject, shallowRef, ref } from "vue"; import dayjs from "dayjs"; import { treeForEach, arrangementArr } from "../../../../utils/common.mjs"; const useTimeLine = ({ rowHeight, rowBuffer, perHourSpacing, scrollViewScrollTop, scrollViewScrollLeft, rowNodeMap, currentVisibleRowIds, startInfo, movingTimeLineRowId, movingTimeLine, createTimePointNodes }) => { const wrapRef = inject("wrapRef"); const visibleRows = shallowRef([]); const visibleTimeLineMap = shallowRef(/* @__PURE__ */ new Map()); const bufferWidth = 200; const wrapWidth = ref(0); const wrapHeight = ref(0); const freshTimeLineView = () => { var _a, _b; wrapWidth.value = ((_a = wrapRef.value) == null ? void 0 : _a.offsetWidth) || 0; wrapHeight.value = ((_b = wrapRef.value) == null ? void 0 : _b.offsetHeight) || 0; freshVisibleRows(); freshVisibleTimeLines(); }; const freshTimeLineViewAfterScrollTop = () => { freshVisibleRows(); freshVisibleTimeLines(false); }; const freshVisibleRows = () => { if (!wrapRef.value) return; const bufferHeight = rowHeight.value * rowBuffer; const startNumInView = Math.floor((scrollViewScrollTop.value - bufferHeight) / rowHeight.value); const endNumInView = Math.ceil((scrollViewScrollTop.value + wrapHeight.value + bufferHeight) / rowHeight.value); const newVisibleRows = []; const start = Math.max(0, startNumInView); const end = Math.min(currentVisibleRowIds.value.length - 1, endNumInView); for (let i = start; i <= end; i++) { const currentRowId = currentVisibleRowIds.value[i]; const currentRowNode = rowNodeMap.value.get(currentRowId); if (currentRowNode) { newVisibleRows.push({ id: currentRowId, rowNode: currentRowNode, translateY: i * rowHeight.value }); const timeLineNodes = sortTimeLinesInRowNode(currentRowNode); if (timeLineNodes) { const timeLineNodesAfterCombine = mergeOverlapTimeLine(timeLineNodes); currentRowNode.timeLineNodes = timeLineNodesAfterCombine; } } } visibleRows.value = arrangementArr(newVisibleRows, visibleRows.value); }; const sortTimeLinesInRowNode = (rowNode) => { if (!rowNode.timeLineNodes && rowNode.data.timeLines) { const timeLineNodes = []; if (rowNode.hasChildren) { const timeLineNode = createTimeLineNodeFromRowNode(rowNode); timeLineNode && timeLineNodes.push(timeLineNode); } else { for (let timeLine of rowNode.data.timeLines) { const timeLineNode = createTimeLineNode(timeLine); timeLineNodes.push(timeLineNode); } } sortTimeLineNodes(timeLineNodes); return timeLineNodes; } }; const createTimeLineNodeFromRowNode = (rowNode) => { const startDate = rowNode.startDate; const endDate = rowNode.endDate; const styleOption = { backgroundColor: "#000" }; if (startDate && endDate) { const isSameDate = startDate.isSame(endDate); const baseNode = { id: rowNode.id, startDate, endDate, isSameDate, hasChildren: rowNode.hasChildren, styleOption }; return baseNode; } }; const sortTimeLineNodes = (timeLineNodes) => { timeLineNodes.sort((timeLine1, timeLine2) => { if (timeLine1.startDate.isSame(timeLine2.startDate)) return 0; if (timeLine1.startDate.isBefore(timeLine2.startDate)) { return -1; } else { return 1; } }); }; const mergeOverlapTimeLine = (timeLineNodes) => { const newTimeLineNodes = []; for (let timeLineNode of timeLineNodes) { const lastTimeLineNode = newTimeLineNodes[newTimeLineNodes.length - 1]; if (lastTimeLineNode && !timeLineNode.startDate.isAfter(lastTimeLineNode.endDate)) { lastTimeLineNode.isMerge = true; const maxEndDate = dayjs.max([lastTimeLineNode.endDate, timeLineNode.endDate]); maxEndDate && (lastTimeLineNode.endDate = maxEndDate); if (!lastTimeLineNode.mergedTimeLineNodes) { lastTimeLineNode.mergedTimeLineNodes = [lastTimeLineNode]; } if (timeLineNode.isMerge) { timeLineNode.isMerge = false; lastTimeLineNode.mergedTimeLineNodes = lastTimeLineNode.mergedTimeLineNodes.concat(timeLineNode.mergedTimeLineNodes); timeLineNode.mergedTimeLineNodes = void 0; } else { lastTimeLineNode.mergedTimeLineNodes.push(timeLineNode); } } else { newTimeLineNodes.push(timeLineNode); } } return newTimeLineNodes; }; const createTimeLineNode = (timeLine) => { const startDate = dayjs(timeLine.startDate); const endDate = dayjs(timeLine.endDate); const isSameDate = startDate.isSame(endDate); const styleOption = { ...timeLine.styleOption }; if (isSameDate) { styleOption.backgroundColor = "#000"; } const timePointNodes = createTimePointNodes(timeLine); const baseNode = { id: timeLine.id, timePointNodes, data: timeLine, startDate, endDate, isSameDate, styleOption, icon: timeLine.icon, label: timeLine.label, disableStretch: timeLine.disableStretch, disableMove: timeLine.disableMove }; return baseNode; }; const freshVisibleTimeLines = (freshAll = true) => { var _a; if (!wrapRef.value) return; const { startDate } = startInfo.value; const startLeftInView = scrollViewScrollLeft.value - bufferWidth; const endLeftInView = scrollViewScrollLeft.value + wrapWidth.value + bufferWidth; const startDateInView = startDate.add(Math.max(0, startLeftInView) / perHourSpacing.value, "hour"); const endDateInView = startDate.add(endLeftInView / perHourSpacing.value, "hour"); const newVisibleTimeLineMap = /* @__PURE__ */ new Map(); let needFreshRows = []; if (freshAll) { needFreshRows = visibleRows.value; } else { needFreshRows = visibleRows.value.filter((row) => { const oldTimeLineCache = visibleTimeLineMap.value.get(row.id); if (oldTimeLineCache) { newVisibleTimeLineMap.set(row.id, oldTimeLineCache); } return !oldTimeLineCache; }); } for (let visibleRow of needFreshRows) { const rowId = visibleRow.id; const timeLineNodes = visibleRow.rowNode.timeLineNodes; if (timeLineNodes) { const visibleTimeLines = []; const startIndex = getTimeLineIndexInView(timeLineNodes, startDateInView, "min"); const endIndex = getTimeLineIndexInView(timeLineNodes, endDateInView, "max"); const hasMovingTimeLine = movingTimeLineRowId.value === rowId; for (let i = startIndex; i < endIndex; i++) { const currentTimeNode = timeLineNodes[i]; if (hasMovingTimeLine && currentTimeNode.id === ((_a = movingTimeLine.value) == null ? void 0 : _a.id)) continue; const currentStartDate = currentTimeNode.startDate; const currentEndDate = currentTimeNode.endDate; const translateX = currentStartDate.diff(startDate, "hour", true) * perHourSpacing.value; const width = currentTimeNode.isSameDate ? 0 : currentEndDate.diff(currentStartDate, "hour", true) * perHourSpacing.value; let type = "normal"; if (currentTimeNode.hasChildren) { type = "parentTimeLineNode"; } else if (currentTimeNode.isSameDate) { type = "sameDateTimeLineNode"; } const originalTimePoints = currentTimeNode.timePointNodes || []; const timePointNodes = []; for (let timePointNode of originalTimePoints) { if (timePointNode.date.isBetween(currentStartDate, currentEndDate, void 0, "[]")) { const timePointNodeTranslateX = timePointNode.date.diff(currentStartDate, "hour", true) * perHourSpacing.value; timePointNode.translateX = timePointNodeTranslateX; timePointNodes.push(timePointNode); } } visibleTimeLines.push({ id: currentTimeNode.id, startDate: currentTimeNode.startDate, endDate: currentTimeNode.endDate, timeLineNode: currentTimeNode, width, translateX, styleOption: currentTimeNode.styleOption, type, timePointNodes, icon: currentTimeNode.icon, label: currentTimeNode.label, disableStretch: currentTimeNode.disableStretch, disableMove: currentTimeNode.disableMove }); } if (hasMovingTimeLine) { visibleTimeLines.push(movingTimeLine.value); } newVisibleTimeLineMap.set(rowId, visibleTimeLines); } } visibleTimeLineMap.value = newVisibleTimeLineMap; }; const getTimeLineIndexInView = (timeLineNodes, targetDate, type) => { let minIndex = 0; let maxIndex = timeLineNodes.length - 1; while (maxIndex >= minIndex) { const midIndex = Math.floor((minIndex + maxIndex) / 2); const startDate = timeLineNodes[midIndex].startDate; const endDate = timeLineNodes[midIndex].endDate; const currentDate = type === "min" ? endDate : startDate; if (currentDate.isBefore(targetDate)) { minIndex = midIndex + 1; } else { maxIndex = midIndex - 1; } } return minIndex; }; const freshTimeLines = (rowNodes) => { if (rowNodes.length === 0) return; treeForEach(rowNodes, (rowNode) => { const currentRowId = rowNode.id; const currentRowNode = rowNodeMap.value.get(currentRowId); currentRowNode && (currentRowNode.timeLineNodes = void 0); visibleTimeLineMap.value.delete(currentRowId); }); freshTimeLineViewAfterScrollTop(); }; const updateParentTimeLine = (rowId) => { var _a, _b; const parentRowNode = rowNodeMap.value.get(rowId); const { startDate } = startInfo.value; if (parentRowNode) { const parentTimeLineNode = (_a = parentRowNode.timeLineNodes) == null ? void 0 : _a[0]; const parentVisibleTimeLine = (_b = visibleTimeLineMap.value.get(rowId)) == null ? void 0 : _b[0]; if (parentTimeLineNode) { const childrenRowNodes = parentRowNode.children || []; const startDateArr = []; const endDateArr = []; for (let childRowNode of childrenRowNodes) { const childTimeLineNodes = childRowNode.timeLineNodes || []; for (let childTimeLineNode of childTimeLineNodes) { startDateArr.push(childTimeLineNode.startDate); endDateArr.push(childTimeLineNode.endDate); } const minStartDate = dayjs.min(startDateArr); const maxEndDate = dayjs.max(endDateArr); if (minStartDate && maxEndDate) { parentTimeLineNode.startDate = minStartDate; parentTimeLineNode.endDate = maxEndDate; if (parentVisibleTimeLine) { const translateX = parentTimeLineNode.startDate.diff(startDate, "hour", true) * perHourSpacing.value; const width = parentTimeLineNode.endDate.diff(parentTimeLineNode.startDate, "hour", true) * perHourSpacing.value; parentVisibleTimeLine.translateX = translateX; parentVisibleTimeLine.width = width; } } } parentRowNode.parentId && updateParentTimeLine(parentRowNode.parentId); } } }; return { freshTimeLineView, freshTimeLineViewAfterScrollTop, freshTimeLines, freshVisibleTimeLines, sortTimeLineNodes, mergeOverlapTimeLine, visibleTimeLineMap, visibleRows, updateParentTimeLine }; }; export { useTimeLine }; //# sourceMappingURL=useTimeLine.mjs.map