dishui 0.0.67 → 0.0.68

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.
Files changed (32) hide show
  1. package/dist/calendar.js +5 -0
  2. package/dist/components/Demo/index.js +76 -80
  3. package/dist/components/Demo/index.js.map +1 -1
  4. package/dist/components/pro/Calendar/Calendar.js +576 -0
  5. package/dist/components/pro/Calendar/Calendar.js.map +1 -0
  6. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js +104 -0
  7. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -0
  8. package/dist/components/pro/Calendar/hooks/useCalendarState.js +187 -0
  9. package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -0
  10. package/dist/components/pro/Calendar/utils.js +193 -0
  11. package/dist/components/pro/Calendar/utils.js.map +1 -0
  12. package/dist/components/pro/Gantt/Gantt.js +868 -0
  13. package/dist/components/pro/Gantt/Gantt.js.map +1 -0
  14. package/dist/components/pro/Gantt/hooks/useGanttDrag.js +99 -0
  15. package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -0
  16. package/dist/components/pro/Gantt/hooks/useGanttState.js +95 -0
  17. package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -0
  18. package/dist/components/pro/Gantt/utils.js +236 -0
  19. package/dist/components/pro/Gantt/utils.js.map +1 -0
  20. package/dist/dishui.css +1 -1
  21. package/dist/gantt.js +5 -0
  22. package/dist/hooks/useCopyToClipboard.d.ts +2 -1
  23. package/dist/hooks/useCopyToClipboard.js +17 -9
  24. package/dist/hooks/useCopyToClipboard.js.map +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +9 -1
  27. package/dist/utils/i18n.js +40 -0
  28. package/dist/utils/i18n.js.map +1 -1
  29. package/package.json +12 -1
  30. package/dist/pages/components/Gantt/index.d.ts +0 -3
  31. package/dist/pages/components/Gantt/index.en.d.ts +0 -3
  32. package/dist/pages/components/Gantt/index.zh.d.ts +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Gantt.js","names":[],"sources":["../../../../src/components/pro/Gantt/Gantt.tsx"],"sourcesContent":["/**\n * DishUI Gantt Chart Component\n */\n\nimport React, {\n forwardRef,\n useImperativeHandle,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n GanttProps,\n GanttHandle,\n GanttNode,\n GanttNodeId,\n GanttScaleLevel,\n FlatGanttNode,\n GanttDependencyLink,\n GanttGridConfig,\n} from \"./types\";\nimport { useGanttState } from \"./hooks/useGanttState\";\nimport { useGanttDrag } from \"./hooks/useGanttDrag\";\nimport {\n isNonWorkingDay,\n isWeekend,\n isSameDay,\n formatDate,\n DEFAULT_SCALE_CONFIGS,\n} from \"./utils\";\nimport \"./styles.css\";\n\n// ─── Helpers ──────────────────────────────────────────────────────\n\n/**\n * Check if a date is a declared holiday entry.\n * Returns true for any date that has an explicit non-working holiday entry,\n * INCLUDING weekends that happen to fall within a holiday period (e.g. Spring Festival).\n * 调休 (compensatory workday entries with isWorkday=true) are NOT holidays.\n */\nfunction isHolidayOnly(date: Date, holidays?: GanttProps[\"holidays\"]): boolean {\n if (!holidays) return false;\n if (holidays.isNonWorkingDay) {\n return holidays.isNonWorkingDay(date);\n }\n const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, \"0\")}-${String(date.getDate()).padStart(2, \"0\")}`;\n const entry = holidays.entries?.find((e) => e.date === dateStr);\n if (!entry) return false;\n // 调休 (compensatory workday) is NOT a holiday\n if (entry.isWorkday) return false;\n return true;\n}\n\nconst DEFAULT_GRID: Required<GanttGridConfig> = {\n showCellBorders: true,\n cellBorderColor: \"\",\n weekendColor: \"\",\n holidayColor: \"#fff0f3\",\n todayColor: \"\",\n showRowLines: false,\n};\n\nconst DEFAULT_LABELS = {\n treePanelTitle: \"Tasks\",\n searchPlaceholder: \"Search...\",\n expandAll: \"Expand All\",\n collapseAll: \"Collapse All\",\n today: \"Today\",\n zoomIn: \"Zoom In\",\n zoomOut: \"Zoom Out\",\n noData: \"No data\",\n workingDays: \"Working days\",\n calendarDays: \"Calendar days\",\n weekDays: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"] as [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n ],\n monthNames: [\n \"Jan\",\n \"Feb\",\n \"Mar\",\n \"Apr\",\n \"May\",\n \"Jun\",\n \"Jul\",\n \"Aug\",\n \"Sep\",\n \"Oct\",\n \"Nov\",\n \"Dec\",\n ] as [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n ],\n add: \"Add\",\n delete: \"Delete\",\n edit: \"Edit\",\n link: \"Open link\",\n};\n\n// ─── Main Component ───────────────────────────────────────────────\n\nconst Gantt = forwardRef<GanttHandle, GanttProps>(function Gantt(props, ref) {\n const {\n data,\n categories = {},\n holidays,\n timeWindow,\n columns,\n defaultScale = \"day\",\n availableScales,\n scaleConfigs,\n treePanelWidth: initialTreeWidth = 300,\n treePanelMinWidth = 200,\n treePanelMaxWidth = 600,\n treePanelResizable = true,\n rowHeight = 36,\n draggable = false,\n resizable = false,\n readOnly = false,\n defaultExpandedIds,\n defaultExpandAll = true,\n todayMarker = { visible: true, autoScroll: true },\n tooltip: tooltipConfig = { enabled: true },\n labels: userLabels,\n showSearch = false,\n highlightNonWorkingDays = true,\n grid: userGrid,\n dependencyLinks = [],\n className,\n width = \"100%\",\n height = \"100%\",\n onBarChange,\n onNodeClick,\n onNodeDoubleClick,\n onContextMenu,\n onNodeToggle,\n onViewChange,\n onScaleChange,\n onNodeLabelEdit,\n onNodeAdd,\n onNodeAddChild,\n onNodeDelete,\n onNodeLinkClick,\n onDependencyCreate,\n onDependencyClick,\n onDependencyDelete,\n renderTreeNode,\n renderToolbar,\n renderTimelineHeader,\n } = props;\n\n const labels = useMemo(\n () => ({ ...DEFAULT_LABELS, ...userLabels }),\n [userLabels],\n );\n const gridCfg = useMemo(() => ({ ...DEFAULT_GRID, ...userGrid }), [userGrid]);\n\n // ─── Core state ─────────────────────────────────────────────\n const state = useGanttState({\n data,\n defaultScale,\n defaultExpandedIds,\n defaultExpandAll,\n scaleConfigs,\n categories,\n holidays,\n timeWindow,\n availableScales,\n onScaleChange,\n onNodeToggle,\n onViewChange,\n });\n const {\n scale,\n setScale,\n scales,\n currentScaleConfig,\n flatNodes,\n dates,\n headerGroups,\n dateRange,\n today,\n todayX,\n totalTimelineWidth,\n selectedNodeId,\n setSelectedNodeId,\n toggleNode,\n expandAll,\n collapseAll,\n scrollToDate,\n scrollToToday,\n scrollToNode,\n treeBodyRef,\n timelineBodyRef,\n timelineHeaderRef,\n syncScrollVertical,\n syncScrollHorizontal,\n } = state;\n\n const drag = useGanttDrag({\n scaleConfig: currentScaleConfig,\n timelineStart: dateRange.start,\n onBarChange: readOnly ? undefined : onBarChange,\n calendar: holidays,\n });\n\n // ─── Tree panel resize ──────────────────────────────────────\n const [treePanelW, setTreePanelW] = useState(initialTreeWidth);\n const resizingRef = useRef(false);\n const resizeStartRef = useRef({ x: 0, width: 0 });\n const handleResizeStart = useCallback(\n (e: React.MouseEvent) => {\n if (!treePanelResizable) return;\n e.preventDefault();\n resizingRef.current = true;\n resizeStartRef.current = { x: e.clientX, width: treePanelW };\n const hm = (ev: MouseEvent) => {\n if (!resizingRef.current) return;\n setTreePanelW(\n Math.max(\n treePanelMinWidth,\n Math.min(\n treePanelMaxWidth,\n resizeStartRef.current.width +\n ev.clientX -\n resizeStartRef.current.x,\n ),\n ),\n );\n };\n const hu = () => {\n resizingRef.current = false;\n window.removeEventListener(\"mousemove\", hm);\n window.removeEventListener(\"mouseup\", hu);\n };\n window.addEventListener(\"mousemove\", hm);\n window.addEventListener(\"mouseup\", hu);\n },\n [treePanelResizable, treePanelW, treePanelMinWidth, treePanelMaxWidth],\n );\n\n // ─── Search ─────────────────────────────────────────────────\n const [searchQuery, setSearchQuery] = useState(\"\");\n const filteredFlatNodes = useMemo(() => {\n if (!searchQuery.trim()) return flatNodes;\n const q = searchQuery.toLowerCase();\n return flatNodes.filter((fn) => fn.node.label.toLowerCase().includes(q));\n }, [flatNodes, searchQuery]);\n\n // ─── Edit dialog ─────────────────────────────────────────\n const [editingLabel, setEditingLabel] = useState(\"\");\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const [editDialogNode, setEditDialogNode] = useState<GanttNode | null>(null);\n const editInputRef = useRef<HTMLInputElement>(null);\n const startEditing = useCallback(\n (node: GanttNode) => {\n if (readOnly || !onNodeLabelEdit) return;\n setEditDialogNode(node);\n setEditingLabel(node.label);\n setEditDialogOpen(true);\n },\n [readOnly, onNodeLabelEdit],\n );\n const commitEdit = useCallback(() => {\n if (!editDialogNode) return;\n const trimmed = editingLabel.trim();\n if (trimmed && onNodeLabelEdit && trimmed !== editDialogNode.label) {\n onNodeLabelEdit(editDialogNode, trimmed);\n }\n setEditDialogOpen(false);\n setEditDialogNode(null);\n setEditingLabel(\"\");\n }, [editDialogNode, editingLabel, onNodeLabelEdit]);\n const cancelEdit = useCallback(() => {\n setEditDialogOpen(false);\n setEditDialogNode(null);\n setEditingLabel(\"\");\n }, []);\n\n // ─── Dependency connector drag ──────────────────────────────\n const [connDrag, setConnDrag] = useState<{\n fromId: GanttNodeId;\n startX: number;\n startY: number;\n curX: number;\n curY: number;\n } | null>(null);\n const connDragRef = useRef(connDrag);\n connDragRef.current = connDrag;\n const timelinePanelRef = useRef<HTMLDivElement>(null);\n\n const handleConnectorMouseDown = useCallback(\n (e: React.MouseEvent, nodeId: GanttNodeId) => {\n if (readOnly || !onDependencyCreate) return;\n e.preventDefault();\n e.stopPropagation();\n const body = timelineBodyRef.current;\n if (!body) return;\n const rect = body.getBoundingClientRect();\n // Snap start point to the bar's connector edge rather than exact mouse position\n const displayN = showSearch ? filteredFlatNodes : flatNodes;\n const fn = displayN.find((f) => f.node.id === nodeId);\n let x: number;\n let y: number;\n if (fn) {\n // Determine if clicked on left or right connector\n const mouseX = e.clientX - rect.left + body.scrollLeft;\n const barCenter = fn.barLeft + fn.barWidth / 2;\n if (mouseX < barCenter) {\n x = fn.barLeft; // left edge\n } else {\n x = fn.barLeft + fn.barWidth; // right edge\n }\n y = fn.visibleIndex * rowHeight + rowHeight / 2;\n } else {\n x = e.clientX - rect.left + body.scrollLeft;\n y = e.clientY - rect.top + body.scrollTop;\n }\n setConnDrag({ fromId: nodeId, startX: x, startY: y, curX: x, curY: y });\n },\n [\n readOnly,\n onDependencyCreate,\n timelineBodyRef,\n flatNodes,\n filteredFlatNodes,\n showSearch,\n rowHeight,\n ],\n );\n\n useEffect(() => {\n if (!connDrag) return;\n const body = timelineBodyRef.current;\n if (!body) return;\n\n const hm = (e: MouseEvent) => {\n const rect = body.getBoundingClientRect();\n const curX = e.clientX - rect.left + body.scrollLeft;\n const curY = e.clientY - rect.top + body.scrollTop;\n setConnDrag((prev) => (prev ? { ...prev, curX, curY } : null));\n };\n const hu = (e: MouseEvent) => {\n const cur = connDragRef.current;\n if (cur && onDependencyCreate) {\n const rect = body.getBoundingClientRect();\n const y = e.clientY - rect.top + body.scrollTop;\n const rowIdx = Math.floor(y / rowHeight);\n const displayN = showSearch ? filteredFlatNodes : flatNodes;\n const dn = displayN[rowIdx];\n if (dn && dn.node.id !== cur.fromId) {\n onDependencyCreate(cur.fromId, dn.node.id);\n }\n }\n setConnDrag(null);\n };\n window.addEventListener(\"mousemove\", hm);\n window.addEventListener(\"mouseup\", hu);\n return () => {\n window.removeEventListener(\"mousemove\", hm);\n window.removeEventListener(\"mouseup\", hu);\n };\n // Only re-attach listeners when drag starts (fromId changes), not on every cursor move\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [connDrag?.fromId]);\n\n // ─── Auto-scroll ────────────────────────────────────────────\n useEffect(() => {\n if (todayMarker.autoScroll !== false) {\n const t = setTimeout(scrollToToday, 100);\n return () => clearTimeout(t);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n useImperativeHandle(ref, () => ({\n scrollToDate,\n scrollToToday,\n scrollToNode,\n getVisibleRange: () => ({ start: dateRange.start, end: dateRange.end }),\n setScale,\n expandAll,\n collapseAll,\n toggleNode,\n }));\n\n // ─── Row click → smooth scroll to data start ───────────────\n const handleRowClick = useCallback(\n (node: GanttNode) => {\n setSelectedNodeId(node.id);\n onNodeClick?.(node);\n const flat = flatNodes.find((fn) => fn.node.id === node.id);\n if (flat?.resolvedStartDate && timelineBodyRef.current) {\n const targetX = flat.barLeft - timelineBodyRef.current.clientWidth / 3;\n timelineBodyRef.current.scrollTo({\n left: Math.max(0, targetX),\n behavior: \"smooth\",\n });\n }\n },\n [flatNodes, setSelectedNodeId, onNodeClick, timelineBodyRef],\n );\n\n // ─── Context menu ───────────────────────────────────────────\n const handleTimelineContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (!onContextMenu) return;\n e.preventDefault();\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const x =\n e.clientX - rect.left + (timelineBodyRef.current?.scrollLeft || 0);\n const date = new Date(dateRange.start);\n date.setDate(\n date.getDate() +\n Math.floor(\n x / (currentScaleConfig.cellWidth * currentScaleConfig.slotsPerDay),\n ),\n );\n onContextMenu({\n node: null,\n position: { x: e.clientX, y: e.clientY },\n date,\n });\n },\n [onContextMenu, dateRange, currentScaleConfig, timelineBodyRef],\n );\n\n const findParent = useCallback(\n (\n targetId: GanttNodeId,\n nodes: GanttNode[],\n parent: GanttNode | null,\n ): GanttNode | null => {\n for (const n of nodes) {\n if (n.id === targetId) return parent;\n if (n.children) {\n const f = findParent(targetId, n.children, n);\n if (f !== undefined) return f;\n }\n }\n return null;\n },\n [],\n );\n\n // ─── Toolbar ────────────────────────────────────────────────\n const defaultToolbar = (\n <div className=\"gantt-toolbar\">\n <div className=\"gantt-toolbar-group\">\n {scales.map((s) => (\n <button\n key={s}\n className={`gantt-scale-btn ${s === scale ? \"gantt-scale-btn--active\" : \"\"}`}\n onClick={() => setScale(s)}\n title={DEFAULT_SCALE_CONFIGS[s].label}\n >\n {DEFAULT_SCALE_CONFIGS[s].label}\n </button>\n ))}\n </div>\n <div className=\"gantt-toolbar-divider\" />\n <button\n className=\"gantt-icon-btn\"\n onClick={scrollToToday}\n title={labels.today}\n >\n ◉\n </button>\n <button\n className=\"gantt-icon-btn\"\n onClick={expandAll}\n title={labels.expandAll}\n >\n ⊞\n </button>\n <button\n className=\"gantt-icon-btn\"\n onClick={collapseAll}\n title={labels.collapseAll}\n >\n ⊟\n </button>\n <div className=\"gantt-toolbar-spacer\" />\n <span style={{ fontSize: 11, color: \"oklch(var(--bc) / 0.4)\" }}>\n {flatNodes.length} items\n </span>\n </div>\n );\n const toolbar = renderToolbar\n ? renderToolbar(defaultToolbar)\n : defaultToolbar;\n\n // ─── Tree Row ───────────────────────────────────────────────\n const renderTreeRow = (flatNode: FlatGanttNode) => {\n const { node, depth, expanded, hasChildren } = flatNode;\n const isSelected = selectedNodeId === node.id;\n\n if (renderTreeNode) {\n return (\n <div\n key={node.id}\n className={`gantt-tree-row ${isSelected ? \"gantt-tree-row--selected\" : \"\"}`}\n style={{ height: rowHeight }}\n onClick={() => handleRowClick(node)}\n onDoubleClick={() => {\n onNodeDoubleClick?.(node);\n startEditing(node);\n }}\n >\n {renderTreeNode(node, depth, expanded, () => toggleNode(node.id))}\n </div>\n );\n }\n\n return (\n <div\n key={node.id}\n className={`gantt-tree-row ${isSelected ? \"gantt-tree-row--selected\" : \"\"}`}\n style={{ height: rowHeight }}\n onClick={() => handleRowClick(node)}\n onDoubleClick={() => {\n onNodeDoubleClick?.(node);\n startEditing(node);\n }}\n >\n <div className=\"gantt-tree-indent\" style={{ width: depth * 20 }} />\n <div\n className={`gantt-tree-toggle ${hasChildren ? (expanded ? \"gantt-tree-toggle--expanded\" : \"\") : \"gantt-tree-toggle--placeholder\"}`}\n onClick={(e) => {\n e.stopPropagation();\n if (hasChildren) toggleNode(node.id);\n }}\n >\n {hasChildren && \"\\u25B6\"}\n </div>\n <div className=\"gantt-tree-label\" title={node.label}>\n {node.label}\n </div>\n {node.link && (\n <button\n className=\"gantt-tree-action-btn\"\n title={labels.link}\n onClick={(e) => {\n e.stopPropagation();\n if (onNodeLinkClick) {\n onNodeLinkClick(node, node.link!);\n } else {\n window.open(node.link!, \"_blank\");\n }\n }}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\" />\n </svg>\n </button>\n )}\n {columns?.map((col) => (\n <div\n key={col.key}\n className=\"gantt-tree-cell\"\n style={{ width: col.width || 80, textAlign: col.align || \"left\" }}\n >\n {col.render ? col.render(node, col) : (node.meta?.[col.key] ?? \"\")}\n </div>\n ))}\n {!readOnly && (onNodeAdd || onNodeAddChild || onNodeDelete) && (\n <div className=\"gantt-tree-actions gantt-tree-actions--pinned\">\n {onNodeAdd && (\n <button\n className=\"gantt-tree-action-btn\"\n title={labels.add}\n onClick={(e) => {\n e.stopPropagation();\n onNodeAdd(findParent(node.id, data, null), node);\n }}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n {onNodeAddChild && (\n <button\n className=\"gantt-tree-action-btn\"\n title=\"Add child\"\n onClick={(e) => {\n e.stopPropagation();\n onNodeAddChild(node);\n }}\n >\n {\"\\u229E\"}\n </button>\n )}\n {onNodeDelete && (\n <button\n className=\"gantt-tree-action-btn gantt-tree-action-btn--danger\"\n title={labels.delete}\n onClick={(e) => {\n e.stopPropagation();\n onNodeDelete(node);\n }}\n >\n {\"\\u00D7\"}\n </button>\n )}\n </div>\n )}\n </div>\n );\n };\n\n // ─── Timeline Header ───────────────────────────────────────\n const renderDefaultTimelineHeader = () => (\n <div className=\"gantt-timeline-header\" ref={timelineHeaderRef}>\n <div\n className=\"gantt-timeline-header-row\"\n style={{ width: totalTimelineWidth }}\n >\n {headerGroups.map((group, i) => (\n <div\n key={i}\n className=\"gantt-timeline-header-group\"\n style={{\n width:\n group.span *\n currentScaleConfig.cellWidth *\n currentScaleConfig.slotsPerDay,\n }}\n >\n {group.label}\n </div>\n ))}\n </div>\n <div\n className=\"gantt-timeline-header-row\"\n style={{ width: totalTimelineWidth }}\n >\n {scale === \"halfday\"\n ? dates.map((date, i) => {\n const isToday2 = isSameDay(date, today);\n const isWknd = isNonWorkingDay(date, holidays);\n const baseCls = `gantt-timeline-header-cell ${isToday2 ? \"gantt-timeline-header-cell--today\" : \"\"} ${isWknd ? \"gantt-timeline-header-cell--weekend\" : \"\"}`;\n return (\n <React.Fragment key={i}>\n <div\n className={baseCls}\n style={{ width: currentScaleConfig.cellWidth }}\n >\n 上午\n </div>\n <div\n className={baseCls}\n style={{ width: currentScaleConfig.cellWidth }}\n >\n 下午\n </div>\n </React.Fragment>\n );\n })\n : scale === \"hour\"\n ? dates.map((date, i) => {\n const isToday2 = isSameDay(date, today);\n const isWknd = isNonWorkingDay(date, holidays);\n const baseCls = `gantt-timeline-header-cell ${isToday2 ? \"gantt-timeline-header-cell--today\" : \"\"} ${isWknd ? \"gantt-timeline-header-cell--weekend\" : \"\"}`;\n return (\n <React.Fragment key={i}>\n {Array.from({ length: 24 }, (_, h) => (\n <div\n key={h}\n className={baseCls}\n style={{ width: currentScaleConfig.cellWidth }}\n >\n {h}\n </div>\n ))}\n </React.Fragment>\n );\n })\n : dates.map((date, i) => {\n const isToday2 = isSameDay(date, today);\n const isWknd = isNonWorkingDay(date, holidays);\n const cls = `gantt-timeline-header-cell ${isToday2 ? \"gantt-timeline-header-cell--today\" : \"\"} ${isWknd ? \"gantt-timeline-header-cell--weekend\" : \"\"}`;\n return (\n <div\n key={i}\n className={cls}\n style={{\n width:\n currentScaleConfig.cellWidth *\n currentScaleConfig.slotsPerDay,\n }}\n >\n {date.getDate()}\n </div>\n );\n })}\n </div>\n </div>\n );\n\n // ─── Grid Columns ──────────────────────────────────────────\n const renderGridColumns = () => {\n if (scale === \"halfday\" || scale === \"hour\") {\n // Render individual sub-cells for halfday/hour\n const slots = currentScaleConfig.slotsPerDay;\n const cellW = currentScaleConfig.cellWidth;\n const elements: React.ReactNode[] = [];\n dates.forEach((date, dayIdx) => {\n const isToday2 = isSameDay(date, today);\n const isHol = isHolidayOnly(date, holidays);\n const isWknd = isWeekend(date) && holidays?.weekendsOff !== false;\n const showBorder = gridCfg.showCellBorders;\n\n for (let s = 0; s < slots; s++) {\n const globalIdx = dayIdx * slots + s;\n const classes = [\"gantt-timeline-col\"];\n if (showBorder) classes.push(\"gantt-timeline-col--border\");\n if (highlightNonWorkingDays && isWknd)\n classes.push(\"gantt-timeline-col--weekend\");\n if (highlightNonWorkingDays && isHol)\n classes.push(\"gantt-timeline-col--holiday\");\n if (isToday2) classes.push(\"gantt-timeline-col--today\");\n\n const style: React.CSSProperties = {\n left: globalIdx * cellW,\n width: cellW,\n };\n if (gridCfg.cellBorderColor && showBorder)\n style.borderRightColor = gridCfg.cellBorderColor;\n if (isWknd && gridCfg.weekendColor)\n style.background = gridCfg.weekendColor;\n if (isHol && gridCfg.holidayColor)\n style.background = gridCfg.holidayColor;\n if (isToday2 && gridCfg.todayColor)\n style.background = gridCfg.todayColor;\n\n elements.push(\n <div\n key={`${dayIdx}-${s}`}\n className={classes.join(\" \")}\n style={style}\n />,\n );\n }\n });\n return elements;\n }\n\n return dates.map((date, i) => {\n const isToday2 = isSameDay(date, today);\n const isHol = isHolidayOnly(date, holidays);\n const isWknd = isWeekend(date) && holidays?.weekendsOff !== false;\n const showBorder = gridCfg.showCellBorders;\n\n const classes = [\"gantt-timeline-col\"];\n if (showBorder) classes.push(\"gantt-timeline-col--border\");\n if (highlightNonWorkingDays && isWknd)\n classes.push(\"gantt-timeline-col--weekend\");\n if (highlightNonWorkingDays && isHol)\n classes.push(\"gantt-timeline-col--holiday\");\n if (isToday2) classes.push(\"gantt-timeline-col--today\");\n\n // Custom inline colors from gridCfg\n const style: React.CSSProperties = {\n left: i * currentScaleConfig.cellWidth * currentScaleConfig.slotsPerDay,\n width: currentScaleConfig.cellWidth * currentScaleConfig.slotsPerDay,\n };\n if (gridCfg.cellBorderColor && showBorder)\n style.borderRightColor = gridCfg.cellBorderColor;\n if (isWknd && gridCfg.weekendColor)\n style.background = gridCfg.weekendColor;\n if (isHol && gridCfg.holidayColor)\n style.background = gridCfg.holidayColor;\n if (isToday2 && gridCfg.todayColor) style.background = gridCfg.todayColor;\n\n return <div key={i} className={classes.join(\" \")} style={style} />;\n });\n };\n\n // ─── Bar ────────────────────────────────────────────────────\n const renderBar = (flatNode: FlatGanttNode) => {\n const { node, barLeft, barWidth, isRenderable, categoryConfig } = flatNode;\n if (!isRenderable || barWidth <= 0) return null;\n\n const isDraggableBar = !readOnly && (categoryConfig.draggable ?? draggable);\n const isResizableBar = !readOnly && (categoryConfig.resizable ?? resizable);\n const isCurrentlyDragging = drag.draggingNodeId === node.id;\n const isSelected = selectedNodeId === node.id;\n const { left, width: adjustedWidth } = drag.getAdjustedBar(\n node.id,\n barLeft,\n barWidth,\n );\n\n // Per-node color > category color > default\n const barColor = node.barColor || categoryConfig.color || \"#3b82f6\";\n const barBg = node.barColor || categoryConfig.backgroundColor || barColor;\n const barH = rowHeight * (categoryConfig.barHeight || 0.6);\n const barTop = (rowHeight - barH) / 2;\n const borderRadius = categoryConfig.borderRadius ?? 4;\n const renderStyle = categoryConfig.renderStyle || \"bar\";\n const showConnectors = !readOnly && !!onDependencyCreate;\n\n // Connector handles for dependency linking\n const connectorHandles = showConnectors && (\n <>\n <div\n className={`gantt-bar-connector gantt-bar-connector--left ${connDrag?.fromId === node.id ? \"gantt-bar-connector--active\" : \"\"}`}\n onMouseDown={(e) => handleConnectorMouseDown(e, node.id)}\n />\n <div\n className={`gantt-bar-connector gantt-bar-connector--right ${connDrag?.fromId === node.id ? \"gantt-bar-connector--active\" : \"\"}`}\n onMouseDown={(e) => handleConnectorMouseDown(e, node.id)}\n />\n </>\n );\n\n if (renderStyle === \"line\") {\n return (\n <div\n key={node.id}\n className={`gantt-bar gantt-bar--line ${isSelected ? \"gantt-bar--selected\" : \"\"} ${isCurrentlyDragging ? \"gantt-bar--dragging\" : \"\"}`}\n style={{\n left,\n width: adjustedWidth,\n background: barColor,\n top: rowHeight / 2 - 1.5,\n height: 3,\n borderRadius: 1,\n }}\n >\n {connectorHandles}\n </div>\n );\n }\n\n if (node.milestone) {\n return (\n <React.Fragment key={node.id}>\n <div\n className={`gantt-milestone ${isCurrentlyDragging ? \"gantt-bar--dragging\" : \"\"}`}\n style={{\n left: left + adjustedWidth / 2 - 7,\n top: rowHeight / 2 - 7,\n background: barColor,\n transition: isCurrentlyDragging\n ? \"none\"\n : \"left 0.25s cubic-bezier(0.4,0,0.2,1)\",\n }}\n />\n {showConnectors && (\n <div\n style={{\n position: \"absolute\",\n left: left + adjustedWidth / 2 - 7,\n top: rowHeight / 2 - 7,\n width: 14,\n height: 14,\n }}\n >\n <div\n className={`gantt-bar-connector gantt-bar-connector--left ${connDrag?.fromId === node.id ? \"gantt-bar-connector--active\" : \"\"}`}\n style={{ left: -5, top: 2 }}\n onMouseDown={(e) => handleConnectorMouseDown(e, node.id)}\n />\n <div\n className={`gantt-bar-connector gantt-bar-connector--right ${connDrag?.fromId === node.id ? \"gantt-bar-connector--active\" : \"\"}`}\n style={{ right: -5, top: 2 }}\n onMouseDown={(e) => handleConnectorMouseDown(e, node.id)}\n />\n </div>\n )}\n </React.Fragment>\n );\n }\n\n return (\n <div\n key={node.id}\n className={`gantt-bar ${isDraggableBar ? \"gantt-bar--draggable\" : \"\"} ${isCurrentlyDragging ? \"gantt-bar--dragging\" : \"\"} ${isSelected ? \"gantt-bar--selected\" : \"\"}`}\n style={{\n left,\n top: barTop,\n width: adjustedWidth,\n height: barH,\n background: barBg,\n borderRadius,\n }}\n onMouseDown={\n isDraggableBar\n ? (e) => {\n if (\n (e.target as HTMLElement).classList.contains(\n \"gantt-bar-connector\",\n )\n )\n return;\n drag.startDrag(e, node, \"move\", barLeft, barWidth);\n }\n : undefined\n }\n onClick={(e) => {\n e.stopPropagation();\n setSelectedNodeId(node.id);\n onNodeClick?.(node);\n }}\n onContextMenu={(e) => {\n if (onContextMenu) {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu({\n node,\n position: { x: e.clientX, y: e.clientY },\n date: new Date(),\n });\n }\n }}\n >\n {categoryConfig.showProgress && node.progress != null && (\n <div\n className=\"gantt-bar-fill\"\n style={{ width: `${node.progress}%`, background: barColor }}\n />\n )}\n {categoryConfig.renderBar ? (\n categoryConfig.renderBar(node, {\n node,\n width: adjustedWidth,\n height: barH,\n isDragging: isCurrentlyDragging,\n isSelected,\n startDateFormatted: flatNode.resolvedStartDate\n ? formatDate(flatNode.resolvedStartDate)\n : \"\",\n endDateFormatted: flatNode.resolvedEndDate\n ? formatDate(flatNode.resolvedEndDate)\n : \"\",\n durationText: node.workingDays ? `${node.workingDays}d` : \"\",\n })\n ) : (\n <span className=\"gantt-bar-label\">\n {adjustedWidth > 60\n ? node.label\n : node.workingDays\n ? `${node.workingDays}d`\n : \"\"}\n </span>\n )}\n {isResizableBar && (\n <>\n <div\n className=\"gantt-bar-resize-handle gantt-bar-resize-handle--left\"\n onMouseDown={(e) =>\n drag.startDrag(e, node, \"resize-start\", barLeft, barWidth)\n }\n />\n <div\n className=\"gantt-bar-resize-handle gantt-bar-resize-handle--right\"\n onMouseDown={(e) =>\n drag.startDrag(e, node, \"resize-end\", barLeft, barWidth)\n }\n />\n </>\n )}\n {connectorHandles}\n </div>\n );\n };\n\n // ─── Dependency Links SVG ───────────────────────────\n const renderDependencyLinks = () => {\n if (dependencyLinks.length === 0 && !connDrag) return null;\n const displayN = showSearch ? filteredFlatNodes : flatNodes;\n const nodeMap = new Map(displayN.map((fn) => [fn.node.id, fn]));\n const totalH = displayN.length * rowHeight;\n\n return (\n <svg\n className=\"gantt-dependency-svg\"\n style={{ width: totalTimelineWidth, height: totalH }}\n >\n {dependencyLinks.map((link, i) => {\n const from = nodeMap.get(link.fromId);\n const to = nodeMap.get(link.toId);\n if (!from || !to) return null;\n\n const x1 = from.barLeft + from.barWidth;\n const y1 = from.visibleIndex * rowHeight + rowHeight / 2;\n const x2 = to.barLeft;\n const y2 = to.visibleIndex * rowHeight + rowHeight / 2;\n\n const midX = x1 + 12;\n const path = `M${x1},${y1} H${midX} V${y2} H${x2}`;\n const dashClass =\n link.lineStyle === \"dashed\"\n ? \"gantt-dependency-path--dashed\"\n : link.lineStyle === \"dotted\"\n ? \"gantt-dependency-path--dotted\"\n : \"gantt-dependency-path--solid\";\n\n const strokeColor = link.color || undefined;\n const strokeW = link.lineWidth || 1.5;\n const showArr = link.showArrow !== false;\n const showDelete = !readOnly && !!onDependencyDelete;\n\n // Position the delete button at the midpoint of the link\n const delX = midX;\n const delY = (y1 + y2) / 2;\n\n return (\n <g\n key={i}\n className=\"gantt-dependency-group\"\n onClick={() => onDependencyClick?.(link)}\n >\n <path\n className={`gantt-dependency-path ${dashClass}`}\n d={path}\n style={{ stroke: strokeColor, strokeWidth: strokeW }}\n />\n {showArr && (\n <polygon\n className=\"gantt-dependency-arrow\"\n points={`${x2},${y2} ${x2 - 6},${y2 - 4} ${x2 - 6},${y2 + 4}`}\n style={{ fill: strokeColor }}\n />\n )}\n {showDelete && (\n <foreignObject\n x={delX - 8}\n y={delY - 8}\n width={16}\n height={16}\n className=\"gantt-dependency-delete-fo\"\n >\n <button\n className=\"gantt-dependency-delete-btn\"\n onClick={(e) => {\n e.stopPropagation();\n onDependencyDelete(link);\n }}\n title=\"删除连线\"\n >\n ×\n </button>\n </foreignObject>\n )}\n </g>\n );\n })}\n {connDrag &&\n (() => {\n const { startX, startY, curX, curY } = connDrag;\n const dx = curX - startX;\n const cpOffset = Math.min(Math.abs(dx) * 0.5, 60);\n const cp1x = startX + cpOffset;\n const cp2x = curX - cpOffset;\n const d = `M${startX},${startY} C${cp1x},${startY} ${cp2x},${curY} ${curX},${curY}`;\n return <path className=\"gantt-dep-drag-line\" d={d} />;\n })()}\n </svg>\n );\n };\n\n // ─── Today Marker ───────────────────────────────────────────\n const renderTodayMarker = () => {\n if (!todayMarker.visible) return null;\n return (\n <div\n className=\"gantt-today-marker\"\n style={{\n left: todayX,\n ...(todayMarker.color ? { background: todayMarker.color } : {}),\n }}\n />\n );\n };\n\n // ─── Tooltip ────────────────────────────────────────────────\n const [tooltipState, setTooltipState] = useState<{\n node: GanttNode;\n x: number;\n y: number;\n } | null>(null);\n const handleBarMouseEnter = useCallback(\n (e: React.MouseEvent, node: GanttNode) => {\n if (!tooltipConfig.enabled || drag.isDragging) return;\n setTooltipState({ node, x: e.clientX + 12, y: e.clientY + 12 });\n },\n [tooltipConfig.enabled, drag.isDragging],\n );\n const handleBarMouseLeave = useCallback(() => setTooltipState(null), []);\n\n const renderTooltip = () => {\n if (!tooltipState) return null;\n if (tooltipConfig.render)\n return (\n <div\n className=\"gantt-tooltip\"\n style={{ left: tooltipState.x, top: tooltipState.y }}\n >\n {tooltipConfig.render(tooltipState.node)}\n </div>\n );\n const n = tooltipState.node;\n return (\n <div\n className=\"gantt-tooltip\"\n style={{ left: tooltipState.x, top: tooltipState.y }}\n >\n <div className=\"gantt-tooltip-title\">{n.label}</div>\n {n.startDate && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">Start:</span>\n {typeof n.startDate === \"string\"\n ? n.startDate\n : formatDate(n.startDate)}\n </div>\n )}\n {n.endDate && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">End:</span>\n {typeof n.endDate === \"string\" ? n.endDate : formatDate(n.endDate)}\n </div>\n )}\n {n.workingDays != null && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">{labels.workingDays}:</span>\n {n.workingDays}\n </div>\n )}\n {n.assignee && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">Assignee:</span>\n {n.assignee}\n </div>\n )}\n {n.progress != null && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">Progress:</span>\n {n.progress}%\n </div>\n )}\n {n.link && (\n <div className=\"gantt-tooltip-row\">\n <span className=\"gantt-tooltip-label\">Link:</span>\n <span className=\"gantt-tooltip-link\">{n.link}</span>\n </div>\n )}\n </div>\n );\n };\n\n // ─── Main Render ────────────────────────────────────────────\n if (!data || data.length === 0) {\n return (\n <div\n className={`gantt-container ${className || \"\"}`}\n style={{ width, height }}\n >\n {toolbar}\n <div className=\"gantt-empty\">{labels.noData}</div>\n </div>\n );\n }\n\n const displayNodes = showSearch ? filteredFlatNodes : flatNodes;\n const totalRowsHeight = displayNodes.length * rowHeight;\n\n return (\n <div\n className={`gantt-container ${className || \"\"}`}\n style={{ width, height }}\n >\n {toolbar}\n <div className=\"gantt-body\">\n <div className=\"gantt-tree-panel\" style={{ width: treePanelW }}>\n {showSearch && (\n <div className=\"gantt-search\">\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n <input\n className=\"gantt-search-input\"\n placeholder={labels.searchPlaceholder}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n />\n </div>\n )}\n <div className=\"gantt-tree-header\">\n <div className=\"gantt-tree-header-cell\" style={{ flex: 1 }}>\n {labels.treePanelTitle}\n </div>\n {columns?.map((col) => (\n <div\n key={col.key}\n className=\"gantt-tree-header-cell\"\n style={{\n width: col.width || 80,\n textAlign: col.align || \"left\",\n }}\n >\n {col.title}\n </div>\n ))}\n </div>\n <div\n className=\"gantt-tree-body\"\n ref={treeBodyRef}\n onScroll={() => syncScrollVertical(\"tree\")}\n >\n {displayNodes.map(renderTreeRow)}\n </div>\n </div>\n {treePanelResizable && (\n <div\n className={`gantt-resize-handle ${resizingRef.current ? \"gantt-resize-handle--active\" : \"\"}`}\n onMouseDown={handleResizeStart}\n />\n )}\n <div className=\"gantt-timeline-panel\" ref={timelinePanelRef}>\n {renderTimelineHeader\n ? renderTimelineHeader(dates, scale)\n : renderDefaultTimelineHeader()}\n <div\n className=\"gantt-timeline-body\"\n ref={timelineBodyRef}\n onScroll={() => {\n syncScrollVertical(\"timeline\");\n syncScrollHorizontal();\n }}\n onContextMenu={handleTimelineContextMenu}\n >\n <div\n className=\"gantt-timeline-grid\"\n style={{ width: totalTimelineWidth, height: totalRowsHeight }}\n >\n {renderGridColumns()}\n {renderTodayMarker()}\n </div>\n <div\n className=\"gantt-timeline-rows\"\n style={{ width: totalTimelineWidth, height: totalRowsHeight }}\n >\n {displayNodes.map((fn) => (\n <div\n key={fn.node.id}\n className={`gantt-bar-row ${gridCfg.showRowLines ? \"gantt-bar-row--lined\" : \"\"}`}\n style={{ height: rowHeight }}\n onMouseEnter={(e) => handleBarMouseEnter(e, fn.node)}\n onMouseLeave={handleBarMouseLeave}\n >\n {renderBar(fn)}\n </div>\n ))}\n </div>\n {renderDependencyLinks()}\n </div>\n </div>\n </div>\n {renderTooltip()}\n {/* Edit Dialog */}\n {editDialogOpen && editDialogNode && (\n <div className=\"gantt-edit-dialog-overlay\" onClick={cancelEdit}>\n <div\n className=\"gantt-edit-dialog\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"gantt-edit-dialog__header\">\n <span className=\"gantt-edit-dialog__title\">{labels.edit}</span>\n <button\n type=\"button\"\n className=\"gantt-edit-dialog__close\"\n onClick={cancelEdit}\n >\n \\u00D7\n </button>\n </div>\n <div className=\"gantt-edit-dialog__body\">\n <input\n ref={editInputRef}\n className=\"gantt-edit-dialog__input\"\n value={editingLabel}\n onChange={(e) => setEditingLabel(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") commitEdit();\n if (e.key === \"Escape\") cancelEdit();\n }}\n autoFocus\n />\n </div>\n <div className=\"gantt-edit-dialog__footer\">\n <button\n type=\"button\"\n className=\"gantt-edit-dialog__btn gantt-edit-dialog__btn--cancel\"\n onClick={cancelEdit}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"gantt-edit-dialog__btn gantt-edit-dialog__btn--submit\"\n onClick={commitEdit}\n disabled={!editingLabel.trim()}\n >\n OK\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n});\n\nexport default Gantt;\n"],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { calculateWorkingDays as e, startOfDay as t, xToDate as n } from "../utils.js";
2
+ import { useCallback as r, useEffect as i, useRef as a, useState as o } from "react";
3
+ //#region src/components/pro/Gantt/hooks/useGanttDrag.ts
4
+ function s(s) {
5
+ let { scaleConfig: c, timelineStart: l, onBarChange: u, calendar: d, minBarWidth: f = 10 } = s, [p, m] = o(null), [h, g] = o({ dx: 0 }), _ = a(null), v = r((e, t, n, r, i) => {
6
+ if (!n) return;
7
+ e.preventDefault(), e.stopPropagation();
8
+ let a = {
9
+ nodeId: t.id,
10
+ mode: n,
11
+ startX: e.clientX,
12
+ startBarLeft: r,
13
+ startBarWidth: i,
14
+ originalNode: t
15
+ };
16
+ m(a), g({ dx: 0 }), _.current = a;
17
+ }, []), y = r((e) => {
18
+ if (!_.current) return;
19
+ let t = e.clientX - _.current.startX;
20
+ g({ dx: t });
21
+ }, []), b = r((r) => {
22
+ let i = _.current;
23
+ if (!i) return;
24
+ let a = r.clientX - i.startX, o = i.startBarLeft, s = i.startBarWidth;
25
+ switch (i.mode) {
26
+ case "move":
27
+ o = i.startBarLeft + a;
28
+ break;
29
+ case "resize-start":
30
+ o = i.startBarLeft + a, s = Math.max(f, i.startBarWidth - a);
31
+ break;
32
+ case "resize-end": s = Math.max(f, i.startBarWidth + a);
33
+ }
34
+ let p = n(o, l, c), h = n(o + s, l, c), v = e(p, h, d);
35
+ u && a !== 0 && u({
36
+ node: i.originalNode,
37
+ newStartDate: t(p),
38
+ newEndDate: t(h),
39
+ newWorkingDays: v,
40
+ changeType: i.mode,
41
+ originalNode: i.originalNode
42
+ }), m(null), g({ dx: 0 }), _.current = null;
43
+ }, [
44
+ l,
45
+ c,
46
+ u,
47
+ d,
48
+ f
49
+ ]);
50
+ i(() => {
51
+ if (p) return window.addEventListener("mousemove", y), window.addEventListener("mouseup", b), () => {
52
+ window.removeEventListener("mousemove", y), window.removeEventListener("mouseup", b);
53
+ };
54
+ }, [
55
+ p,
56
+ y,
57
+ b
58
+ ]);
59
+ let x = r((e, t, n) => {
60
+ if (!p || p.nodeId !== e) return {
61
+ left: t,
62
+ width: n
63
+ };
64
+ let r = h.dx;
65
+ switch (p.mode) {
66
+ case "move": return {
67
+ left: t + r,
68
+ width: n
69
+ };
70
+ case "resize-start": return {
71
+ left: t + r,
72
+ width: Math.max(f, n - r)
73
+ };
74
+ case "resize-end": return {
75
+ left: t,
76
+ width: Math.max(f, n + r)
77
+ };
78
+ default: return {
79
+ left: t,
80
+ width: n
81
+ };
82
+ }
83
+ }, [
84
+ p,
85
+ h,
86
+ f
87
+ ]);
88
+ return {
89
+ isDragging: p !== null,
90
+ draggingNodeId: p?.nodeId ?? null,
91
+ dragMode: p?.mode ?? null,
92
+ startDrag: v,
93
+ getAdjustedBar: x
94
+ };
95
+ }
96
+ //#endregion
97
+ export { s as useGanttDrag };
98
+
99
+ //# sourceMappingURL=useGanttDrag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGanttDrag.js","names":[],"sources":["../../../../../src/components/pro/Gantt/hooks/useGanttDrag.ts"],"sourcesContent":["/**\n * Drag and resize interaction hook for Gantt bars.\n * Handles move (translate) and resize-start/resize-end operations.\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport type {\n GanttNode,\n GanttScaleConfig,\n GanttBarChangeEvent,\n HolidayCalendar,\n GanttCategoryConfig,\n} from '../types';\nimport {\n xToDate,\n dateToX,\n calculateWorkingDays,\n addWorkingDays,\n startOfDay,\n clamp,\n} from '../utils';\n\nexport type DragMode = 'move' | 'resize-start' | 'resize-end' | null;\n\nexport interface DragState {\n nodeId: string | number;\n mode: DragMode;\n startX: number;\n startBarLeft: number;\n startBarWidth: number;\n originalNode: GanttNode;\n}\n\nexport interface UseGanttDragOptions {\n scaleConfig: GanttScaleConfig;\n timelineStart: Date;\n onBarChange?: (event: GanttBarChangeEvent) => void;\n calendar?: HolidayCalendar;\n minBarWidth?: number;\n}\n\nexport function useGanttDrag(options: UseGanttDragOptions) {\n const { scaleConfig, timelineStart, onBarChange, calendar, minBarWidth = 10 } = options;\n\n const [dragState, setDragState] = useState<DragState | null>(null);\n const [dragDelta, setDragDelta] = useState<{ dx: number }>({ dx: 0 });\n const dragRef = useRef<DragState | null>(null);\n\n const startDrag = useCallback(\n (\n e: React.MouseEvent,\n node: GanttNode,\n mode: DragMode,\n barLeft: number,\n barWidth: number\n ) => {\n if (!mode) return;\n e.preventDefault();\n e.stopPropagation();\n\n const state: DragState = {\n nodeId: node.id,\n mode,\n startX: e.clientX,\n startBarLeft: barLeft,\n startBarWidth: barWidth,\n originalNode: node,\n };\n\n setDragState(state);\n setDragDelta({ dx: 0 });\n dragRef.current = state;\n },\n []\n );\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!dragRef.current) return;\n const dx = e.clientX - dragRef.current.startX;\n setDragDelta({ dx });\n },\n []\n );\n\n const handleMouseUp = useCallback(\n (e: MouseEvent) => {\n const state = dragRef.current;\n if (!state) return;\n\n const dx = e.clientX - state.startX;\n\n // Compute new position\n let newBarLeft = state.startBarLeft;\n let newBarWidth = state.startBarWidth;\n\n switch (state.mode) {\n case 'move':\n newBarLeft = state.startBarLeft + dx;\n break;\n case 'resize-start':\n newBarLeft = state.startBarLeft + dx;\n newBarWidth = Math.max(minBarWidth, state.startBarWidth - dx);\n break;\n case 'resize-end':\n newBarWidth = Math.max(minBarWidth, state.startBarWidth + dx);\n break;\n }\n\n // Convert pixel positions to dates\n const newStartDate = xToDate(newBarLeft, timelineStart, scaleConfig);\n const newEndDate = xToDate(newBarLeft + newBarWidth, timelineStart, scaleConfig);\n\n // Calculate working days if applicable\n const workingDays = calculateWorkingDays(newStartDate, newEndDate, calendar);\n\n if (onBarChange && (dx !== 0)) {\n onBarChange({\n node: state.originalNode,\n newStartDate: startOfDay(newStartDate),\n newEndDate: startOfDay(newEndDate),\n newWorkingDays: workingDays,\n changeType: state.mode as 'move' | 'resize-start' | 'resize-end',\n originalNode: state.originalNode,\n });\n }\n\n setDragState(null);\n setDragDelta({ dx: 0 });\n dragRef.current = null;\n },\n [timelineStart, scaleConfig, onBarChange, calendar, minBarWidth]\n );\n\n // Attach global mouse listeners during drag\n useEffect(() => {\n if (dragState) {\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }\n }, [dragState, handleMouseMove, handleMouseUp]);\n\n /**\n * Get the adjusted bar position for a given node during drag\n */\n const getAdjustedBar = useCallback(\n (nodeId: string | number, barLeft: number, barWidth: number) => {\n if (!dragState || dragState.nodeId !== nodeId) {\n return { left: barLeft, width: barWidth };\n }\n\n const dx = dragDelta.dx;\n\n switch (dragState.mode) {\n case 'move':\n return { left: barLeft + dx, width: barWidth };\n case 'resize-start':\n return {\n left: barLeft + dx,\n width: Math.max(minBarWidth, barWidth - dx),\n };\n case 'resize-end':\n return {\n left: barLeft,\n width: Math.max(minBarWidth, barWidth + dx),\n };\n default:\n return { left: barLeft, width: barWidth };\n }\n },\n [dragState, dragDelta, minBarWidth]\n );\n\n const isDragging = dragState !== null;\n const draggingNodeId = dragState?.nodeId ?? null;\n\n return {\n isDragging,\n draggingNodeId,\n dragMode: dragState?.mode ?? null,\n startDrag,\n getAdjustedBar,\n };\n}\n"],"mappings":";;;AAyCA,SAAgB,EAAa,GAA8B;CACzD,IAAM,EAAE,gBAAa,kBAAe,gBAAa,aAAU,iBAAc,OAAO,GAE1E,CAAC,GAAW,KAAgB,EAA2B,IAAI,GAC3D,CAAC,GAAW,KAAgB,EAAyB,EAAE,IAAI,EAAE,CAAC,GAC9D,IAAU,EAAyB,IAAI,GAEvC,IAAY,GAEd,GACA,GACA,GACA,GACA,MACG;EACH,IAAI,CAAC,GAAM;EAEX,AADA,EAAE,eAAe,GACjB,EAAE,gBAAgB;EAElB,IAAM,IAAmB;GACvB,QAAQ,EAAK;GACb;GACA,QAAQ,EAAE;GACV,cAAc;GACd,eAAe;GACf,cAAc;EAChB;EAIA,AAFA,EAAa,CAAK,GAClB,EAAa,EAAE,IAAI,EAAE,CAAC,GACtB,EAAQ,UAAU;CACpB,GACA,CAAC,CACH,GAEM,IAAkB,GACrB,MAAkB;EACjB,IAAI,CAAC,EAAQ,SAAS;EACtB,IAAM,IAAK,EAAE,UAAU,EAAQ,QAAQ;EACvC,EAAa,EAAE,MAAG,CAAC;CACrB,GACA,CAAC,CACH,GAEM,IAAgB,GACnB,MAAkB;EACjB,IAAM,IAAQ,EAAQ;EACtB,IAAI,CAAC,GAAO;EAEZ,IAAM,IAAK,EAAE,UAAU,EAAM,QAGzB,IAAa,EAAM,cACnB,IAAc,EAAM;EAExB,QAAQ,EAAM,MAAd;GACE,KAAK;IACH,IAAa,EAAM,eAAe;IAClC;GACF,KAAK;IAEH,AADA,IAAa,EAAM,eAAe,GAClC,IAAc,KAAK,IAAI,GAAa,EAAM,gBAAgB,CAAE;IAC5D;GACF,KAAK,cACH,IAAc,KAAK,IAAI,GAAa,EAAM,gBAAgB,CAAE;EAEhE;EAGA,IAAM,IAAe,EAAQ,GAAY,GAAe,CAAW,GAC7D,IAAa,EAAQ,IAAa,GAAa,GAAe,CAAW,GAGzE,IAAc,EAAqB,GAAc,GAAY,CAAQ;EAe3E,AAbI,KAAgB,MAAO,KACzB,EAAY;GACV,MAAM,EAAM;GACZ,cAAc,EAAW,CAAY;GACrC,YAAY,EAAW,CAAU;GACjC,gBAAgB;GAChB,YAAY,EAAM;GAClB,cAAc,EAAM;EACtB,CAAC,GAGH,EAAa,IAAI,GACjB,EAAa,EAAE,IAAI,EAAE,CAAC,GACtB,EAAQ,UAAU;CACpB,GACA;EAAC;EAAe;EAAa;EAAa;EAAU;CAAW,CACjE;CAGA,QAAgB;EACd,IAAI,GAGF,OAFA,OAAO,iBAAiB,aAAa,CAAe,GACpD,OAAO,iBAAiB,WAAW,CAAa,SACnC;GAEX,AADA,OAAO,oBAAoB,aAAa,CAAe,GACvD,OAAO,oBAAoB,WAAW,CAAa;EACrD;CAEJ,GAAG;EAAC;EAAW;EAAiB;CAAa,CAAC;CAK9C,IAAM,IAAiB,GACpB,GAAyB,GAAiB,MAAqB;EAC9D,IAAI,CAAC,KAAa,EAAU,WAAW,GACrC,OAAO;GAAE,MAAM;GAAS,OAAO;EAAS;EAG1C,IAAM,IAAK,EAAU;EAErB,QAAQ,EAAU,MAAlB;GACE,KAAK,QACH,OAAO;IAAE,MAAM,IAAU;IAAI,OAAO;GAAS;GAC/C,KAAK,gBACH,OAAO;IACL,MAAM,IAAU;IAChB,OAAO,KAAK,IAAI,GAAa,IAAW,CAAE;GAC5C;GACF,KAAK,cACH,OAAO;IACL,MAAM;IACN,OAAO,KAAK,IAAI,GAAa,IAAW,CAAE;GAC5C;GACF,SACE,OAAO;IAAE,MAAM;IAAS,OAAO;GAAS;EAC5C;CACF,GACA;EAAC;EAAW;EAAW;CAAW,CACpC;CAKA,OAAO;EACL,YAJiB,MAAc;EAK/B,gBAJqB,GAAW,UAAU;EAK1C,UAAU,GAAW,QAAQ;EAC7B;EACA;CACF;AACF"}
@@ -0,0 +1,95 @@
1
+ import { DEFAULT_SCALE_CONFIGS as e, computeDateRange as t, dateToX as n, flattenTree as r, generateDateRange as i, generateHeaderGroups as a, startOfDay as o } from "../utils.js";
2
+ import { useCallback as s, useMemo as c, useRef as l, useState as u } from "react";
3
+ //#region src/components/pro/Gantt/hooks/useGanttState.ts
4
+ function d(d) {
5
+ let { data: f, defaultScale: p = "day", defaultExpandedIds: m, defaultExpandAll: h = !0, scaleConfigs: g, categories: _ = {}, holidays: v, timeWindow: y, availableScales: b, onScaleChange: x, onNodeToggle: S, onViewChange: C } = d, [w, T] = u(p), E = s((e) => {
6
+ T(e), x?.(e);
7
+ }, [x]), D = c(() => ({
8
+ ...e,
9
+ ...g
10
+ }), [g]), O = D[w], k = c(() => b || [
11
+ "year",
12
+ "quarter",
13
+ "month",
14
+ "week",
15
+ "day",
16
+ "halfday",
17
+ "hour"
18
+ ], [b]), [A, j] = u(() => m ? new Set(m) : /* @__PURE__ */ new Set()), M = s((e, t) => {
19
+ j((n) => {
20
+ let r = new Set(n), i = h ? !n.has(e) : n.has(e), a = t ?? !i;
21
+ return h ? a ? r.delete(e) : r.add(e) : a ? r.add(e) : r.delete(e), S?.(e, a), r;
22
+ });
23
+ }, [h, S]), N = s(() => {
24
+ j(/* @__PURE__ */ new Set());
25
+ }, []), P = s(() => {
26
+ let e = /* @__PURE__ */ new Set();
27
+ function t(n) {
28
+ for (let r of n) r.children && r.children.length > 0 && (e.add(r.id), t(r.children));
29
+ }
30
+ t(f), j(h ? e : /* @__PURE__ */ new Set());
31
+ }, [f, h]), [F, I] = u(null), L = c(() => t(f, v), [f, v]), R = c(() => i(L.start, L.end), [L]), z = c(() => a(R, w), [R, w]), B = c(() => r(f, A, h, L, O, _, v, y), [
32
+ f,
33
+ A,
34
+ h,
35
+ L,
36
+ O,
37
+ _,
38
+ v,
39
+ y
40
+ ]), V = R.length * O.cellWidth * O.slotsPerDay, H = o(/* @__PURE__ */ new Date()), U = n(H, L.start, O), W = l(null), G = l(null), K = l(null), q = l(!1), J = s((e) => {
41
+ if (q.current) return;
42
+ q.current = !0;
43
+ let t = e === "tree" ? W.current : G.current, n = e === "tree" ? G.current : W.current;
44
+ t && n && (n.scrollTop = t.scrollTop), requestAnimationFrame(() => {
45
+ q.current = !1;
46
+ });
47
+ }, []), Y = s(() => {
48
+ G.current && K.current && (K.current.scrollLeft = G.current.scrollLeft);
49
+ }, []), X = s((e) => {
50
+ let t = n(e, L.start, O);
51
+ if (G.current) {
52
+ let e = G.current.clientWidth;
53
+ G.current.scrollLeft = Math.max(0, t - e / 3);
54
+ }
55
+ }, [L.start, O]);
56
+ return {
57
+ scale: w,
58
+ setScale: E,
59
+ scales: k,
60
+ currentScaleConfig: O,
61
+ mergedScaleConfigs: D,
62
+ expandedIds: A,
63
+ toggleNode: M,
64
+ expandAll: N,
65
+ collapseAll: P,
66
+ selectedNodeId: F,
67
+ setSelectedNodeId: I,
68
+ dateRange: L,
69
+ dates: R,
70
+ headerGroups: z,
71
+ today: H,
72
+ todayX: U,
73
+ totalTimelineWidth: V,
74
+ flatNodes: B,
75
+ treeBodyRef: W,
76
+ timelineBodyRef: G,
77
+ timelineHeaderRef: K,
78
+ syncScrollVertical: J,
79
+ syncScrollHorizontal: Y,
80
+ scrollToDate: X,
81
+ scrollToToday: s(() => {
82
+ X(H);
83
+ }, [X, H]),
84
+ scrollToNode: s((e) => {
85
+ let t = B.findIndex((t) => t.node.id === e);
86
+ t >= 0 && W.current && (W.current.scrollTop = t * 36);
87
+ let n = B.find((t) => t.node.id === e);
88
+ n?.resolvedStartDate && X(n.resolvedStartDate);
89
+ }, [B, X])
90
+ };
91
+ }
92
+ //#endregion
93
+ export { d as useGanttState };
94
+
95
+ //# sourceMappingURL=useGanttState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGanttState.js","names":[],"sources":["../../../../../src/components/pro/Gantt/hooks/useGanttState.ts"],"sourcesContent":["/**\n * Core state management hook for the Gantt component.\n * Manages expansion, selection, scale, date range, and scroll synchronization.\n */\n\nimport { useState, useCallback, useMemo, useRef, useEffect } from 'react';\nimport type {\n GanttNode,\n GanttNodeId,\n GanttScaleLevel,\n GanttScaleConfig,\n GanttCategoryConfig,\n HolidayCalendar,\n TimeWindow,\n FlatGanttNode,\n} from '../types';\nimport {\n DEFAULT_SCALE_CONFIGS,\n computeDateRange,\n generateDateRange,\n generateHeaderGroups,\n flattenTree,\n startOfDay,\n dateToX,\n isSameDay,\n} from '../utils';\n\nexport interface UseGanttStateOptions {\n data: GanttNode[];\n defaultScale?: GanttScaleLevel;\n defaultExpandedIds?: GanttNodeId[];\n defaultExpandAll?: boolean;\n scaleConfigs?: Partial<Record<GanttScaleLevel, GanttScaleConfig>>;\n categories?: Record<string, GanttCategoryConfig>;\n holidays?: HolidayCalendar;\n timeWindow?: TimeWindow;\n availableScales?: GanttScaleLevel[];\n onScaleChange?: (scale: GanttScaleLevel) => void;\n onNodeToggle?: (nodeId: GanttNodeId, expanded: boolean) => void;\n onViewChange?: (start: Date, end: Date, scale: GanttScaleLevel) => void;\n}\n\nexport function useGanttState(options: UseGanttStateOptions) {\n const {\n data,\n defaultScale = 'day',\n defaultExpandedIds,\n defaultExpandAll = true,\n scaleConfigs: customScaleConfigs,\n categories = {},\n holidays,\n timeWindow,\n availableScales,\n onScaleChange,\n onNodeToggle,\n onViewChange,\n } = options;\n\n // ─── Scale state ────────────────────────────────────────────\n const [scale, setScaleRaw] = useState<GanttScaleLevel>(defaultScale);\n const setScale = useCallback(\n (newScale: GanttScaleLevel) => {\n setScaleRaw(newScale);\n onScaleChange?.(newScale);\n },\n [onScaleChange]\n );\n\n const mergedScaleConfigs = useMemo(\n () => ({ ...DEFAULT_SCALE_CONFIGS, ...customScaleConfigs }),\n [customScaleConfigs]\n );\n\n const currentScaleConfig = mergedScaleConfigs[scale];\n\n const scales = useMemo(\n () => availableScales || (['year', 'quarter', 'month', 'week', 'day', 'halfday', 'hour'] as GanttScaleLevel[]),\n [availableScales]\n );\n\n // ─── Expansion state ────────────────────────────────────────\n // In defaultExpandAll mode, this set tracks COLLAPSED node IDs.\n // Otherwise, it tracks EXPANDED node IDs.\n const [expandedIds, setExpandedIds] = useState<Set<GanttNodeId>>(() => {\n if (defaultExpandedIds) {\n return new Set(defaultExpandedIds);\n }\n return new Set<GanttNodeId>();\n });\n\n const toggleNode = useCallback(\n (nodeId: GanttNodeId, expanded?: boolean) => {\n setExpandedIds((prev) => {\n const next = new Set(prev);\n const isCurrentlyExpanded = defaultExpandAll ? !prev.has(nodeId) : prev.has(nodeId);\n const shouldExpand = expanded ?? !isCurrentlyExpanded;\n\n if (defaultExpandAll) {\n // In expandAll mode, the set tracks collapsed IDs\n if (shouldExpand) {\n next.delete(nodeId);\n } else {\n next.add(nodeId);\n }\n } else {\n if (shouldExpand) {\n next.add(nodeId);\n } else {\n next.delete(nodeId);\n }\n }\n\n onNodeToggle?.(nodeId, shouldExpand);\n return next;\n });\n },\n [defaultExpandAll, onNodeToggle]\n );\n\n const expandAll = useCallback(() => {\n setExpandedIds(new Set());\n }, []);\n\n const collapseAll = useCallback(() => {\n // Collect all node IDs that have children\n const allParentIds = new Set<GanttNodeId>();\n function collect(nodes: GanttNode[]) {\n for (const n of nodes) {\n if (n.children && n.children.length > 0) {\n allParentIds.add(n.id);\n collect(n.children);\n }\n }\n }\n collect(data);\n\n if (defaultExpandAll) {\n // In expandAll mode, collapsed set = all parent IDs\n setExpandedIds(allParentIds);\n } else {\n setExpandedIds(new Set());\n }\n }, [data, defaultExpandAll]);\n\n // ─── Selection state ────────────────────────────────────────\n const [selectedNodeId, setSelectedNodeId] = useState<GanttNodeId | null>(null);\n\n // ─── Date range ─────────────────────────────────────────────\n const dateRange = useMemo(() => computeDateRange(data, holidays), [data, holidays]);\n\n const dates = useMemo(() => generateDateRange(dateRange.start, dateRange.end), [dateRange]);\n\n const headerGroups = useMemo(\n () => generateHeaderGroups(dates, scale),\n [dates, scale]\n );\n\n // ─── Flattened tree ─────────────────────────────────────────\n const flatNodes = useMemo(\n () =>\n flattenTree(\n data,\n expandedIds,\n defaultExpandAll,\n dateRange,\n currentScaleConfig,\n categories,\n holidays,\n timeWindow\n ),\n [data, expandedIds, defaultExpandAll, dateRange, currentScaleConfig, categories, holidays, timeWindow]\n );\n\n // ─── Total timeline width ───────────────────────────────────\n const totalTimelineWidth = dates.length * currentScaleConfig.cellWidth * currentScaleConfig.slotsPerDay;\n\n // ─── Today position ─────────────────────────────────────────\n const today = startOfDay(new Date());\n const todayX = dateToX(today, dateRange.start, currentScaleConfig);\n\n // ─── Scroll refs ────────────────────────────────────────────\n const treeBodyRef = useRef<HTMLDivElement>(null);\n const timelineBodyRef = useRef<HTMLDivElement>(null);\n const timelineHeaderRef = useRef<HTMLDivElement>(null);\n const isSyncingScroll = useRef(false);\n\n const syncScrollVertical = useCallback((source: 'tree' | 'timeline') => {\n if (isSyncingScroll.current) return;\n isSyncingScroll.current = true;\n\n const sourceEl = source === 'tree' ? treeBodyRef.current : timelineBodyRef.current;\n const targetEl = source === 'tree' ? timelineBodyRef.current : treeBodyRef.current;\n\n if (sourceEl && targetEl) {\n targetEl.scrollTop = sourceEl.scrollTop;\n }\n\n requestAnimationFrame(() => {\n isSyncingScroll.current = false;\n });\n }, []);\n\n const syncScrollHorizontal = useCallback(() => {\n if (timelineBodyRef.current && timelineHeaderRef.current) {\n timelineHeaderRef.current.scrollLeft = timelineBodyRef.current.scrollLeft;\n }\n }, []);\n\n // ─── Scroll to date ─────────────────────────────────────────\n const scrollToDate = useCallback(\n (date: Date) => {\n const x = dateToX(date, dateRange.start, currentScaleConfig);\n if (timelineBodyRef.current) {\n const viewportWidth = timelineBodyRef.current.clientWidth;\n timelineBodyRef.current.scrollLeft = Math.max(0, x - viewportWidth / 3);\n }\n },\n [dateRange.start, currentScaleConfig]\n );\n\n const scrollToToday = useCallback(() => {\n scrollToDate(today);\n }, [scrollToDate, today]);\n\n const scrollToNode = useCallback(\n (nodeId: GanttNodeId) => {\n const idx = flatNodes.findIndex((fn) => fn.node.id === nodeId);\n if (idx >= 0 && treeBodyRef.current) {\n const rowHeight = 36; // will be from props\n treeBodyRef.current.scrollTop = idx * rowHeight;\n }\n // Also scroll timeline to node's start date\n const node = flatNodes.find((fn) => fn.node.id === nodeId);\n if (node?.resolvedStartDate) {\n scrollToDate(node.resolvedStartDate);\n }\n },\n [flatNodes, scrollToDate]\n );\n\n return {\n // Scale\n scale,\n setScale,\n scales,\n currentScaleConfig,\n mergedScaleConfigs,\n\n // Expansion\n expandedIds,\n toggleNode,\n expandAll,\n collapseAll,\n\n // Selection\n selectedNodeId,\n setSelectedNodeId,\n\n // Date data\n dateRange,\n dates,\n headerGroups,\n today,\n todayX,\n totalTimelineWidth,\n\n // Flattened tree\n flatNodes,\n\n // Scroll\n treeBodyRef,\n timelineBodyRef,\n timelineHeaderRef,\n syncScrollVertical,\n syncScrollHorizontal,\n scrollToDate,\n scrollToToday,\n scrollToNode,\n };\n}\n"],"mappings":";;;AA0CA,SAAgB,EAAc,GAA+B;CAC3D,IAAM,EACJ,SACA,kBAAe,OACf,uBACA,sBAAmB,IACnB,cAAc,GACd,gBAAa,CAAC,GACd,aACA,eACA,oBACA,kBACA,iBACA,oBACE,GAGE,CAAC,GAAO,KAAe,EAA0B,CAAY,GAC7D,IAAW,GACd,MAA8B;EAE7B,AADA,EAAY,CAAQ,GACpB,IAAgB,CAAQ;CAC1B,GACA,CAAC,CAAa,CAChB,GAEM,IAAqB,SAClB;EAAE,GAAG;EAAuB,GAAG;CAAmB,IACzD,CAAC,CAAkB,CACrB,GAEM,IAAqB,EAAmB,IAExC,IAAS,QACP,KAAoB;EAAC;EAAQ;EAAW;EAAS;EAAQ;EAAO;EAAW;CAAM,GACvF,CAAC,CAAe,CAClB,GAKM,CAAC,GAAa,KAAkB,QAChC,IACK,IAAI,IAAI,CAAkB,oBAE5B,IAAI,IAAiB,CAC7B,GAEK,IAAa,GAChB,GAAqB,MAAuB;EAC3C,GAAgB,MAAS;GACvB,IAAM,IAAO,IAAI,IAAI,CAAI,GACnB,IAAsB,IAAmB,CAAC,EAAK,IAAI,CAAM,IAAI,EAAK,IAAI,CAAM,GAC5E,IAAe,KAAY,CAAC;GAkBlC,OAhBI,IAEE,IACF,EAAK,OAAO,CAAM,IAElB,EAAK,IAAI,CAAM,IAGb,IACF,EAAK,IAAI,CAAM,IAEf,EAAK,OAAO,CAAM,GAItB,IAAe,GAAQ,CAAY,GAC5B;EACT,CAAC;CACH,GACA,CAAC,GAAkB,CAAY,CACjC,GAEM,IAAY,QAAkB;EAClC,kBAAe,IAAI,IAAI,CAAC;CAC1B,GAAG,CAAC,CAAC,GAEC,IAAc,QAAkB;EAEpC,IAAM,oBAAe,IAAI,IAAiB;EAC1C,SAAS,EAAQ,GAAoB;GACnC,KAAK,IAAM,KAAK,GACd,AAAI,EAAE,YAAY,EAAE,SAAS,SAAS,MACpC,EAAa,IAAI,EAAE,EAAE,GACrB,EAAQ,EAAE,QAAQ;EAGxB;EAGA,AAFA,EAAQ,CAAI,GAIV,EAFE,IAEa,oBAEA,IAAI,IAAI,CAAC;CAE5B,GAAG,CAAC,GAAM,CAAgB,CAAC,GAGrB,CAAC,GAAgB,KAAqB,EAA6B,IAAI,GAGvE,IAAY,QAAc,EAAiB,GAAM,CAAQ,GAAG,CAAC,GAAM,CAAQ,CAAC,GAE5E,IAAQ,QAAc,EAAkB,EAAU,OAAO,EAAU,GAAG,GAAG,CAAC,CAAS,CAAC,GAEpF,IAAe,QACb,EAAqB,GAAO,CAAK,GACvC,CAAC,GAAO,CAAK,CACf,GAGM,IAAY,QAEd,EACE,GACA,GACA,GACA,GACA,GACA,GACA,GACA,CACF,GACF;EAAC;EAAM;EAAa;EAAkB;EAAW;EAAoB;EAAY;EAAU;CAAU,CACvG,GAGM,IAAqB,EAAM,SAAS,EAAmB,YAAY,EAAmB,aAGtF,IAAQ,kBAAW,IAAI,KAAK,CAAC,GAC7B,IAAS,EAAQ,GAAO,EAAU,OAAO,CAAkB,GAG3D,IAAc,EAAuB,IAAI,GACzC,IAAkB,EAAuB,IAAI,GAC7C,IAAoB,EAAuB,IAAI,GAC/C,IAAkB,EAAO,EAAK,GAE9B,IAAqB,GAAa,MAAgC;EACtE,IAAI,EAAgB,SAAS;EAC7B,EAAgB,UAAU;EAE1B,IAAM,IAAW,MAAW,SAAS,EAAY,UAAU,EAAgB,SACrE,IAAW,MAAW,SAAS,EAAgB,UAAU,EAAY;EAM3E,AAJI,KAAY,MACd,EAAS,YAAY,EAAS,YAGhC,4BAA4B;GAC1B,EAAgB,UAAU;EAC5B,CAAC;CACH,GAAG,CAAC,CAAC,GAEC,IAAuB,QAAkB;EAC7C,AAAI,EAAgB,WAAW,EAAkB,YAC/C,EAAkB,QAAQ,aAAa,EAAgB,QAAQ;CAEnE,GAAG,CAAC,CAAC,GAGC,IAAe,GAClB,MAAe;EACd,IAAM,IAAI,EAAQ,GAAM,EAAU,OAAO,CAAkB;EAC3D,IAAI,EAAgB,SAAS;GAC3B,IAAM,IAAgB,EAAgB,QAAQ;GAC9C,EAAgB,QAAQ,aAAa,KAAK,IAAI,GAAG,IAAI,IAAgB,CAAC;EACxE;CACF,GACA,CAAC,EAAU,OAAO,CAAkB,CACtC;CAsBA,OAAO;EAEL;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EAGA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA,eAxDoB,QAAkB;GACtC,EAAa,CAAK;EACpB,GAAG,CAAC,GAAc,CAAK,CAsDrB;EACA,cArDmB,GAClB,MAAwB;GACvB,IAAM,IAAM,EAAU,WAAW,MAAO,EAAG,KAAK,OAAO,CAAM;GAC7D,AAAI,KAAO,KAAK,EAAY,YAE1B,EAAY,QAAQ,YAAY,IAAM;GAGxC,IAAM,IAAO,EAAU,MAAM,MAAO,EAAG,KAAK,OAAO,CAAM;GACzD,AAAI,GAAM,qBACR,EAAa,EAAK,iBAAiB;EAEvC,GACA,CAAC,GAAW,CAAY,CAwCxB;CACF;AACF"}
@@ -0,0 +1,236 @@
1
+ //#region src/components/pro/Gantt/utils.ts
2
+ var e = {
3
+ year: {
4
+ label: "Year",
5
+ cellWidth: 4,
6
+ slotsPerDay: 1
7
+ },
8
+ quarter: {
9
+ label: "Quarter",
10
+ cellWidth: 8,
11
+ slotsPerDay: 1
12
+ },
13
+ month: {
14
+ label: "Month",
15
+ cellWidth: 16,
16
+ slotsPerDay: 1
17
+ },
18
+ week: {
19
+ label: "Week",
20
+ cellWidth: 24,
21
+ slotsPerDay: 1
22
+ },
23
+ day: {
24
+ label: "Day",
25
+ cellWidth: 40,
26
+ slotsPerDay: 1
27
+ },
28
+ halfday: {
29
+ label: "Half Day",
30
+ cellWidth: 40,
31
+ slotsPerDay: 2
32
+ },
33
+ hour: {
34
+ label: "Hour",
35
+ cellWidth: 30,
36
+ slotsPerDay: 24
37
+ }
38
+ }, t = {
39
+ color: "#3b82f6",
40
+ backgroundColor: "#3b82f6",
41
+ barHeight: .6,
42
+ borderRadius: 4,
43
+ showProgress: !1,
44
+ skipNonWorkingDays: !1,
45
+ draggable: void 0,
46
+ resizable: void 0,
47
+ renderStyle: "bar"
48
+ }, n = {
49
+ startHour: 0,
50
+ endHour: 24
51
+ };
52
+ function r(e) {
53
+ if (!e) return null;
54
+ if (e instanceof Date) return isNaN(e.getTime()) ? null : e;
55
+ let t = String(e);
56
+ if (t.includes("T") || t.includes("+") || t.includes("Z")) {
57
+ let e = new Date(t);
58
+ return isNaN(e.getTime()) ? null : e;
59
+ }
60
+ if (/^\d{4}-\d{2}-\d{2}$/.test(t)) {
61
+ let [e, n, r] = t.split("-").map(Number);
62
+ return new Date(e, n - 1, r);
63
+ }
64
+ let n = new Date(t);
65
+ return isNaN(n.getTime()) ? null : n;
66
+ }
67
+ function i(e) {
68
+ return `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
69
+ }
70
+ function a(e) {
71
+ let t = e.getDay();
72
+ return t === 0 || t === 6;
73
+ }
74
+ function o(e, t) {
75
+ if (!t) return a(e);
76
+ if (t.isNonWorkingDay) return t.isNonWorkingDay(e);
77
+ let n = i(e);
78
+ if (t.entries && t.entries.length > 0) {
79
+ let e = t.entries.find((e) => e.date === n);
80
+ if (e) return !e.isWorkday;
81
+ }
82
+ return t.weekendsOff !== !1 && a(e);
83
+ }
84
+ function s(e, t, n) {
85
+ let r = 0, i = new Date(e);
86
+ i.setHours(0, 0, 0, 0);
87
+ let a = new Date(t);
88
+ for (a.setHours(0, 0, 0, 0); i <= a;) o(i, n) || r++, i.setDate(i.getDate() + 1);
89
+ return r;
90
+ }
91
+ function c(e, t, n) {
92
+ if (t <= 0) return new Date(e);
93
+ let r = new Date(e);
94
+ r.setHours(0, 0, 0, 0);
95
+ let i = t;
96
+ for (; i > 0;) {
97
+ let e = o(r, n);
98
+ r.setDate(r.getDate() + 1), e || i--;
99
+ }
100
+ return r;
101
+ }
102
+ function l(e, t) {
103
+ let n = new Date(e);
104
+ n.setHours(0, 0, 0, 0);
105
+ let r = new Date(t);
106
+ return r.setHours(0, 0, 0, 0), Math.round((r.getTime() - n.getTime()) / 864e5);
107
+ }
108
+ function u(e, t) {
109
+ let n = new Date(e);
110
+ return n.setDate(n.getDate() + t), n;
111
+ }
112
+ function d(e) {
113
+ let t = new Date(e);
114
+ return t.setHours(0, 0, 0, 0), t;
115
+ }
116
+ function f(e, t) {
117
+ return e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate();
118
+ }
119
+ function p(e) {
120
+ let t = new Date(Date.UTC(e.getFullYear(), e.getMonth(), e.getDate())), n = t.getUTCDay() || 7;
121
+ t.setUTCDate(t.getUTCDate() + 4 - n);
122
+ let r = new Date(Date.UTC(t.getUTCFullYear(), 0, 1));
123
+ return Math.ceil(((t.getTime() - r.getTime()) / 864e5 + 1) / 7);
124
+ }
125
+ function m(e) {
126
+ let t = new Date(Date.UTC(e.getFullYear(), e.getMonth(), e.getDate())), n = t.getUTCDay() || 7;
127
+ return t.setUTCDate(t.getUTCDate() + 4 - n), t.getUTCFullYear();
128
+ }
129
+ function h(e, t, n = 14) {
130
+ let i = null, a = null;
131
+ function o(e) {
132
+ for (let n of e) {
133
+ let e = r(n.startDate), s = r(n.endDate);
134
+ if (e && ((!i || e < i) && (i = new Date(e)), (!a || e > a) && (a = new Date(e))), s && ((!i || s < i) && (i = new Date(s)), (!a || s > a) && (a = new Date(s))), e && n.workingDays && !s) {
135
+ let r = c(e, n.workingDays, t);
136
+ (!a || r > a) && (a = new Date(r));
137
+ }
138
+ n.children && o(n.children);
139
+ }
140
+ }
141
+ o(e);
142
+ let s = d(/* @__PURE__ */ new Date());
143
+ return i ||= u(s, -30), a ||= u(s, 30), i && s < i && (i = new Date(s)), a && s > a && (a = new Date(s)), {
144
+ start: u(i, -n),
145
+ end: u(a, n)
146
+ };
147
+ }
148
+ function g(e, t) {
149
+ let n = [], r = d(new Date(e)), i = d(new Date(t));
150
+ for (; r <= i;) n.push(new Date(r)), r.setDate(r.getDate() + 1);
151
+ return n;
152
+ }
153
+ function _(e, t) {
154
+ let n = [];
155
+ if (e.length === 0) return n;
156
+ let r = "", i = 0, a = e[0];
157
+ for (let o of e) {
158
+ let e;
159
+ switch (t) {
160
+ case "year":
161
+ e = `${o.getFullYear()}`;
162
+ break;
163
+ case "quarter":
164
+ e = `Q${Math.floor(o.getMonth() / 3) + 1} ${o.getFullYear()}`;
165
+ break;
166
+ case "week": {
167
+ let t = p(o), n = m(o), r = o.getMonth() + 1;
168
+ e = `${n}-W${String(t).padStart(2, "0")} (${r}月)`;
169
+ break;
170
+ }
171
+ case "month":
172
+ case "day":
173
+ e = `${o.getFullYear()}-${String(o.getMonth() + 1).padStart(2, "0")}`;
174
+ break;
175
+ case "halfday":
176
+ case "hour":
177
+ e = `${o.getFullYear()}-${String(o.getMonth() + 1).padStart(2, "0")}-${String(o.getDate()).padStart(2, "0")}`;
178
+ break;
179
+ default: e = "";
180
+ }
181
+ e === r ? i++ : (r && n.push({
182
+ label: r,
183
+ span: i,
184
+ date: a
185
+ }), r = e, i = 1, a = o);
186
+ }
187
+ return r && n.push({
188
+ label: r,
189
+ span: i,
190
+ date: a
191
+ }), n;
192
+ }
193
+ function v(e, n, i, a, o, s, f, p) {
194
+ let m = [], h = d(a.start), g = 0;
195
+ function _(e, a) {
196
+ for (let d of e) {
197
+ let e = !!(d.children && d.children.length > 0), p = i ? !n.has(d.id) : n.has(d.id), v = {
198
+ ...t,
199
+ ...s.default,
200
+ ...d.category && s[d.category] ? s[d.category] : {}
201
+ }, y = r(d.startDate), b = r(d.endDate);
202
+ y && d.workingDays && !b && (b = v.skipNonWorkingDays ? c(y, d.workingDays, f) : u(y, d.workingDays));
203
+ let x = 0, S = 0, C = d.renderable !== !1 && !!y;
204
+ if (C && y) {
205
+ let e = b || u(y, 1), t = l(h, y), n = Math.max(l(y, e), 1);
206
+ x = t * o.cellWidth * o.slotsPerDay, S = n * o.cellWidth * o.slotsPerDay;
207
+ }
208
+ let w = {
209
+ node: d,
210
+ depth: a,
211
+ expanded: p,
212
+ hasChildren: e,
213
+ barLeft: x,
214
+ barWidth: S,
215
+ resolvedStartDate: y,
216
+ resolvedEndDate: b,
217
+ isRenderable: C,
218
+ categoryConfig: v,
219
+ visibleIndex: g++
220
+ };
221
+ m.push(w), e && p && _(d.children, a + 1);
222
+ }
223
+ }
224
+ return _(e, 0), m;
225
+ }
226
+ function y(e, t, n) {
227
+ let r = e / (n.cellWidth * n.slotsPerDay);
228
+ return u(t, Math.floor(r));
229
+ }
230
+ function b(e, t, n) {
231
+ return l(t, e) * n.cellWidth * n.slotsPerDay;
232
+ }
233
+ //#endregion
234
+ export { t as DEFAULT_CATEGORY_CONFIG, e as DEFAULT_SCALE_CONFIGS, n as DEFAULT_TIME_WINDOW, u as addDays, c as addWorkingDays, s as calculateWorkingDays, h as computeDateRange, b as dateToX, l as daysBetween, v as flattenTree, i as formatDate, g as generateDateRange, _ as generateHeaderGroups, p as getISOWeekNumber, m as getISOWeekYear, o as isNonWorkingDay, f as isSameDay, a as isWeekend, r as parseDate, d as startOfDay, y as xToDate };
235
+
236
+ //# sourceMappingURL=utils.js.map