gantt-lib 0.6.0 → 0.6.2

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/GanttChart/GanttChart.tsx","../src/utils/dateUtils.ts","../src/utils/dependencyUtils.ts","../src/components/TimeScaleHeader/TimeScaleHeader.tsx","../src/components/TaskRow/TaskRow.tsx","../src/utils/geometry.ts","../src/hooks/useTaskDrag.ts","../src/components/TodayIndicator/TodayIndicator.tsx","../src/components/GridBackground/GridBackground.tsx","../src/components/DragGuideLines/DragGuideLines.tsx","../src/components/DependencyLines/DependencyLines.tsx","../src/components/TaskList/TaskList.tsx","../src/components/ui/Popover.tsx","../src/components/TaskList/TaskListRow.tsx","../src/components/ui/Input.tsx","../src/components/ui/DatePicker.tsx","../src/components/ui/Calendar.tsx","../src/components/TaskList/DepIcons.tsx","../src/components/TaskList/NewTaskRow.tsx","../src/components/ui/Button.tsx"],"sourcesContent":["'use client';\n\n// CSS import triggers tsup to emit dist/index.css (renamed to dist/styles.css by onSuccess)\nimport './styles.css';\n\n// Components\nexport { GanttChart, type Task, type TaskDependency, type GanttChartProps, type GanttChartHandle } from './components/GanttChart';\nexport { default as TaskRow } from './components/TaskRow';\nexport { default as TimeScaleHeader } from './components/TimeScaleHeader';\nexport { default as GridBackground } from './components/GridBackground';\nexport { default as TodayIndicator } from './components/TodayIndicator';\nexport { default as DragGuideLines } from './components/DragGuideLines/DragGuideLines';\nexport { TaskList, type TaskListProps } from './components/TaskList';\n\n// UI Components\nexport { Input, type InputProps } from './components/ui/Input';\nexport { Button, type ButtonProps } from './components/ui/Button';\nexport { Popover, PopoverTrigger, PopoverContent, type PopoverProps, type PopoverContentProps } from './components/ui/Popover';\nexport { Calendar, type CalendarProps } from './components/ui/Calendar';\nexport { DatePicker, type DatePickerProps } from './components/ui/DatePicker';\n\n// Hooks\nexport { useTaskDrag } from './hooks';\n\n// Utils\nexport * from './utils';\n\n// Types\nexport type {\n GanttDateRange,\n TaskBarGeometry,\n GridConfig,\n MonthSpan,\n GridLine,\n WeekendBlock,\n} from './types';\n","'use client';\n\nimport React, { useMemo, useCallback, useRef, useState, useEffect, useImperativeHandle, forwardRef } from 'react';\nimport { getMultiMonthDays } from '../../utils/dateUtils';\nimport { calculateGridWidth } from '../../utils/geometry';\nimport { validateDependencies, cascadeByLinks, computeParentDates, computeParentProgress, getChildren, removeDependenciesBetweenTasks } from '../../utils/dependencyUtils';\nimport type { ValidationResult } from '../../types';\nimport TimeScaleHeader from '../TimeScaleHeader';\nimport TaskRow from '../TaskRow';\nimport TodayIndicator from '../TodayIndicator';\nimport GridBackground from '../GridBackground';\nimport DragGuideLines from '../DragGuideLines/DragGuideLines';\nimport { DependencyLines } from '../DependencyLines';\nimport { TaskList } from '../TaskList';\nimport './GanttChart.css';\n\n/**\n * Task data structure for Gantt chart\n */\nexport interface Task {\n /** Unique identifier for the task */\n id: string;\n /** Display name of the task */\n name: string;\n /** Task start date (ISO string or Date object) */\n startDate: string | Date;\n /** Task end date (ISO string or Date object) */\n endDate: string | Date;\n /** Optional color for task bar visualization */\n color?: string;\n /** Optional parent task ID for hierarchy relationship */\n parentId?: string;\n /**\n * Optional progress value from 0-100\n * - Decimal values are allowed and rounded to nearest integer for display\n * - Values are clamped to 0-100 range\n * - Undefined or 0 means no progress is displayed\n * - Progress is visual-only, no user interaction\n */\n progress?: number;\n /**\n * Optional flag indicating if task is accepted\n * - Only meaningful when progress is 100%\n * - Affects the color of the progress bar (green for accepted, yellow for completed)\n */\n accepted?: boolean;\n /**\n * Optional array of task dependencies\n * - Each dependency references a predecessor task by ID\n * - Supports 4 link types: FS (finish-to-start), SS (start-to-start), FF (finish-to-finish), SF (start-to-finish)\n * - Lag is optional and defaults to 0 (positive = delay, negative = overlap)\n */\n dependencies?: TaskDependency[];\n /**\n * Optional flag to prevent drag and resize interactions.\n * When true, the task bar cannot be moved or resized.\n * Independent of accepted/progress — consumer controls both separately.\n */\n locked?: boolean;\n /**\n * Optional horizontal divider line for visual grouping.\n * - 'top' renders a bold line above the task row\n * - 'bottom' renders a bold line below the task row\n * The line spans the full grid width.\n */\n divider?: 'top' | 'bottom';\n}\n\n/**\n * Task dependency definition\n */\nexport interface TaskDependency {\n /** ID of the predecessor task */\n taskId: string;\n /** Link type: FS, SS, FF, or SF */\n type: 'FS' | 'SS' | 'FF' | 'SF';\n /** Optional lag in days (default: 0) */\n lag?: number;\n}\n\nexport interface GanttChartProps {\n /** Array of tasks to display */\n tasks: Task[];\n /** Width of each day column in pixels (default: 40) */\n dayWidth?: number;\n /** Height of each task row in pixels (default: 40) */\n rowHeight?: number;\n /** Height of the header row in pixels (default: 40) */\n headerHeight?: number;\n /** Container height. Can be pixels (600), string (\"90vh\", \"100%\", \"500px\"), or undefined for auto height */\n containerHeight?: number | string;\n /** Callback when tasks are modified via drag/resize. Can receive either the new tasks array or a functional updater. */\n onChange?: (tasks: Task[] | ((currentTasks: Task[]) => Task[])) => void;\n /** Optional callback for dependency validation results */\n onValidateDependencies?: (result: ValidationResult) => void;\n /** Enable automatic shifting of dependent tasks when predecessor moves (default: false) */\n enableAutoSchedule?: boolean;\n /** Disable dependency constraint checking during drag (default: false) */\n disableConstraints?: boolean;\n /** Called when a cascade drag completes; receives all shifted tasks (including dragged task) in hard mode */\n onCascade?: (tasks: Task[]) => void;\n /** Show task list overlay on the left side of the chart (default: false) */\n showTaskList?: boolean;\n /** Width of the task list overlay in pixels (default: 300) */\n taskListWidth?: number;\n /** Disable task name editing in the task list (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing in the task list (default: false) */\n disableDependencyEditing?: boolean;\n /** Highlight expired/overdue tasks with red background (default: false) */\n highlightExpiredTasks?: boolean;\n /** Callback when a new task is added via the task list */\n onAdd?: (task: Task) => void;\n /** Callback when a task is deleted via the task list */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted after a specific task via the task list */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n}\n\n/**\n * Ref handle type for GanttChart — exposes imperative scroll methods.\n */\nexport interface GanttChartHandle {\n scrollToToday: () => void;\n scrollToTask: (taskId: string) => void;\n}\n\n/**\n * GanttChart component - displays tasks on a monthly timeline with Excel-like styling\n *\n * The calendar automatically shows full months based on task date ranges.\n * For example, if tasks span from March 25 to May 5, the calendar shows\n * the complete months of March, April, and May (March 1 - May 31).\n *\n * @example\n * ```tsx\n * <GanttChart\n * tasks={[\n * { id: '1', name: 'Task 1', startDate: '2026-02-01', endDate: '2026-02-05' }\n * ]}\n * />\n * ```\n * @example\n * ```tsx\n * // Hide add task button\n * <GanttChart\n * tasks={tasks}\n * enableAddTask={false}\n * />\n * ```\n */\nexport const GanttChart = forwardRef<GanttChartHandle, GanttChartProps>(({\n tasks,\n dayWidth = 40,\n rowHeight = 40,\n headerHeight = 40,\n containerHeight,\n onChange,\n onValidateDependencies,\n enableAutoSchedule,\n disableConstraints,\n onCascade,\n showTaskList = false,\n taskListWidth = 520,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n highlightExpiredTasks = false,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n enableAddTask = true,\n}, ref) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n // Track selected task ID for highlighting in both TaskList and TaskRow\n const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null);\n\n // Track selected dep chip for arrow highlighting in DependencyLines\n const [selectedChip, setSelectedChip] = useState<{ successorId: string; predecessorId: string; linkType: string } | null>(null);\n\n // Hierarchy state: collapsed parent IDs\n const [collapsedParentIds, setCollapsedParentIds] = useState<Set<string>>(new Set());\n\n // Track editing task ID for auto-edit mode after insert\n const [editingTaskId, setEditingTaskId] = useState<string | null>(null);\n\n // Calculate multi-month date range from tasks\n const dateRange = useMemo(() => getMultiMonthDays(tasks), [tasks]);\n\n // Track dependency validation results\n const [validationResult, setValidationResult] = useState<ValidationResult | null>(null);\n\n // Cascade override positions for non-dragged chain members\n const [cascadeOverrides, setCascadeOverrides] = useState<Map<string, { left: number; width: number }>>(new Map());\n\n // Calculate grid width\n const gridWidth = useMemo(\n () => Math.round(dateRange.length * dayWidth),\n [dateRange.length, dayWidth]\n );\n\n // Filter tasks to hide children of collapsed parents (for chart rendering)\n const filteredTasks = useMemo(() => {\n return tasks.filter(task => {\n // Root-level tasks (no parentId) are always visible\n if (!task.parentId) return true;\n // Child tasks are visible only if their parent is not collapsed\n const parentCollapsed = collapsedParentIds.has(task.parentId);\n return !parentCollapsed;\n });\n }, [tasks, collapsedParentIds]);\n\n // Calculate total grid height (based on filtered tasks)\n const totalGridHeight = useMemo(\n () => filteredTasks.length * rowHeight,\n [filteredTasks.length, rowHeight]\n );\n\n // Get month start for calculations (first day of date range)\n const monthStart = useMemo(() => {\n if (dateRange.length === 0) {\n return new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 1));\n }\n const firstDay = dateRange[0];\n return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));\n }, [dateRange]);\n\n // Only render TodayIndicator if today is in the visible date range\n const todayInRange = useMemo(() => {\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n return dateRange.some(day => day.getTime() === today.getTime());\n }, [dateRange]);\n\n // Center chart on today's date on initial mount\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n const todayIndex = dateRange.findIndex(day => day.getTime() === today.getTime());\n\n if (todayIndex === -1) return;\n\n // Calculate scroll position to center today\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset - (containerWidth / 2) + (dayWidth / 2));\n\n container.scrollLeft = Math.max(0, scrollLeft);\n }, []); // Empty deps array - run only on mount\n\n /**\n * Scroll to today's date when the \"Today\" button is clicked\n */\n const scrollToToday = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n const todayIndex = dateRange.findIndex(day => day.getTime() === today.getTime());\n\n if (todayIndex === -1) return;\n\n // Calculate scroll position to center today\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset - (containerWidth / 2) + (dayWidth / 2));\n\n container.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });\n }, [dateRange, dayWidth]);\n\n /**\n * Scroll to a specific task by ID, centering its start date horizontally in the grid.\n */\n const scrollToTask = useCallback((taskId: string) => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n\n const taskStart = new Date(task.startDate as string);\n const taskStartUTC = new Date(Date.UTC(\n taskStart.getUTCFullYear(),\n taskStart.getUTCMonth(),\n taskStart.getUTCDate()\n ));\n const taskIndex = dateRange.findIndex(day => day.getTime() === taskStartUTC.getTime());\n if (taskIndex === -1) return;\n\n const taskOffset = taskIndex * dayWidth;\n const scrollLeft = Math.round(taskOffset - dayWidth * 2);\n container.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });\n }, [tasks, dateRange, dayWidth]);\n\n /**\n * Expose scrollToToday and scrollToTask methods to parent component via ref\n */\n useImperativeHandle(\n ref,\n () => ({\n scrollToToday,\n scrollToTask,\n }),\n [scrollToToday, scrollToTask]\n );\n\n // Track drag state for guide lines\n const [dragGuideLines, setDragGuideLines] = useState<{\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n } | null>(null);\n\n // Track currently-dragged task's pixel position for real-time dependency line updates\n const [draggedTaskOverride, setDraggedTaskOverride] = useState<{ taskId: string; left: number; width: number } | null>(null);\n\n // Validate dependencies when tasks change\n useEffect(() => {\n const result = validateDependencies(tasks);\n setValidationResult(result);\n onValidateDependencies?.(result);\n }, [tasks, onValidateDependencies]);\n\n /**\n * Stable callback for task updates\n *\n * FIXED: No longer depends on `tasks` to avoid stale closure bugs.\n * Uses functional state update pattern: the callback receives an updater function\n * that maps over the current tasks state, ensuring we always use the latest state.\n *\n * This prevents the \"reverting\" bug where dragging a second task causes the\n * first task to revert to its original position.\n *\n * To prevent re-render storms during drag:\n * 1. The onChange callback is only called AFTER drag completes (mouseUp)\n * 2. During drag, only the dragged TaskRow re-renders (due to its internal state)\n * 3. Other TaskRows don't re-render because their props haven't changed\n *\n * The React.memo comparison in TaskRow excludes onChange from comparison,\n * relying on the fact that onChange fires only after drag completes.\n */\n const handleTaskChange = useCallback((updatedTask: Task) => {\n // Find original task to detect date changes\n const originalTask = tasks.find(t => t.id === updatedTask.id);\n if (!originalTask) {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n // Clear editingTaskId after name edit completes\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n const origStart = new Date(originalTask.startDate as string);\n const origEnd = new Date(originalTask.endDate as string);\n const newStart = new Date(updatedTask.startDate as string);\n const newEnd = new Date(updatedTask.endDate as string);\n const datesChanged = origStart.getTime() !== newStart.getTime() || origEnd.getTime() !== newEnd.getTime();\n\n if (!datesChanged) {\n // Dates didn't change, but progress or other fields might have\n // Check if this task has a parent and update parent progress if needed\n const taskParentId = (updatedTask as any).parentId;\n if (taskParentId) {\n onChange?.((currentTasks) => {\n let finalTasks = currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t);\n // Update parent progress\n const newProgress = computeParentProgress(taskParentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === taskParentId\n ? { ...t, progress: newProgress }\n : t\n );\n return finalTasks;\n });\n } else {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n }\n // Clear editingTaskId after name edit completes\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n let cascadedTasksForCallback: Task[];\n\n if (disableConstraints) {\n cascadedTasksForCallback = [updatedTask];\n } else {\n const cascadedChain = cascadeByLinks(updatedTask.id, newStart, newEnd, tasks);\n cascadedTasksForCallback = [updatedTask, ...cascadedChain];\n }\n\n // Apply changes\n if (disableConstraints) {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n } else {\n onChange?.((currentTasks) => {\n const m = new Map(cascadedTasksForCallback.map(t => [t.id, t]));\n\n // Phase 19: Update parent dates when child task changes\n // For each updated task, check if it has a parent and update parent dates\n let finalTasks = currentTasks.map(t => m.get(t.id) ?? t);\n\n // Collect parent IDs that need updating\n const parentIdsToUpdate = new Set<string>();\n cascadedTasksForCallback.forEach(task => {\n if ((task as any).parentId) {\n parentIdsToUpdate.add((task as any).parentId);\n }\n });\n\n // Update each parent's dates and progress\n parentIdsToUpdate.forEach(parentId => {\n // Skip recomputing dates for the updated task itself if it's a parent\n // The user's manual drag/resize position should be preserved\n if (parentId === updatedTask.id) {\n // Still update progress from children, but not dates\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, progress: newProgress }\n : t\n );\n return;\n }\n\n const newDates = computeParentDates(parentId, finalTasks);\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, startDate: newDates.startDate.toISOString().split('T')[0], endDate: newDates.endDate.toISOString().split('T')[0], progress: newProgress }\n : t\n );\n });\n\n return finalTasks;\n });\n onCascade?.(cascadedTasksForCallback);\n }\n }, [tasks, onChange, disableConstraints, onCascade, editingTaskId]);\n\n /**\n * Handle task deletion: purge deleted taskId from all other tasks' dependency arrays,\n * emit onChange with cleaned tasks, then emit onDelete with the taskId.\n * For parent tasks, cascade delete to all children.\n */\n const handleDelete = useCallback((taskId: string) => {\n onChange?.((currentTasks) => {\n // Collect all tasks to delete (parent + descendants)\n const toDelete = new Set<string>([taskId]);\n\n function collectDescendants(parentId: string) {\n const children = getChildren(parentId, currentTasks);\n children.forEach(child => {\n toDelete.add(child.id);\n collectDescendants(child.id);\n });\n }\n\n collectDescendants(taskId);\n\n // Filter out deleted tasks\n const filteredTasks = currentTasks.filter(t => !toDelete.has(t.id));\n\n // Clean dependencies pointing to deleted tasks\n const cleanedTasks = filteredTasks.map(task => {\n if (!task.dependencies) return task;\n return {\n ...task,\n dependencies: task.dependencies.filter(dep => !toDelete.has(dep.taskId))\n };\n });\n\n return cleanedTasks;\n });\n onDelete?.(taskId);\n }, [onChange, onDelete]);\n\n /**\n * Handle task insertion: set editingTaskId to trigger auto-edit mode,\n * then notify external consumer via onInsertAfter callback.\n *\n * NOTE: The external onInsertAfter callback is responsible for adding\n * the task to the tasks array via onChange.\n */\n const handleInsertAfter = useCallback((taskId: string, newTask: Task) => {\n setEditingTaskId(newTask.id);\n onInsertAfter?.(taskId, newTask);\n }, [onInsertAfter]);\n\n /**\n * Handle task reordering: notify external consumer via onChange and onReorder callbacks.\n *\n * NOTE: onChange receives the full reordered array directly (not a functional updater).\n * Reordering is always a full replacement, never a diff.\n *\n * Extended signature: also accepts movedTaskId and inferredParentId for smart hierarchy.\n */\n const handleReorder = useCallback((reorderedTasks: Task[], movedTaskId?: string, inferredParentId?: string) => {\n console.log('=== GANTT CHART handleReorder START ===');\n console.log('[INPUTS]', {\n movedTaskId,\n inferredParentId,\n inferredParentIdType: typeof inferredParentId,\n reorderedTasksCount: reorderedTasks.length\n });\n\n // Find the moved task in reorderedTasks\n const movedTaskInReordered = reorderedTasks.find(t => t.id === movedTaskId);\n if (movedTaskInReordered) {\n console.log('[MOVED TASK IN REORDERED]', {\n id: movedTaskInReordered.id,\n name: movedTaskInReordered.name,\n currentParentId: movedTaskInReordered.parentId\n });\n } else {\n console.log('[MOVED TASK NOT FOUND IN REORDERED]');\n }\n\n onChange?.((currentTasks) => {\n console.log('[ONCHANGE START]', {\n currentTasksCount: currentTasks.length,\n movedTaskId,\n inferredParentId\n });\n\n // Find the moved task in currentTasks\n const movedTaskInCurrent = currentTasks.find(t => t.id === movedTaskId);\n if (movedTaskInCurrent) {\n console.log('[MOVED TASK IN CURRENT BEFORE UPDATE]', {\n id: movedTaskInCurrent.id,\n name: movedTaskInCurrent.name,\n currentParentId: movedTaskInCurrent.parentId\n });\n }\n\n let updated = reorderedTasks;\n // CRITICAL: Check movedTaskId only, NOT inferredParentId !== undefined\n // When inferredParentId is undefined, we want to CLEAR the parentId (exit group)\n // The old condition `inferredParentId !== undefined` prevented this!\n if (movedTaskId) {\n console.log('[CONDITION CHECK]', {\n condition: 'if (movedTaskId)',\n movedTaskId,\n isTrue: !!movedTaskId,\n willUpdateParentId: true\n });\n updated = updated.map(t => {\n if (t.id === movedTaskId) {\n const newParentId = inferredParentId || undefined;\n console.log('[UPDATING TASK]', {\n taskId: t.id,\n taskName: t.name,\n oldParentId: t.parentId,\n newParentId: newParentId,\n inferredParentId: inferredParentId,\n finalValue: newParentId\n });\n return { ...t, parentId: newParentId };\n }\n return t;\n });\n } else {\n console.log('[CONDITION CHECK]', {\n condition: 'if (movedTaskId)',\n movedTaskId,\n isTrue: false,\n willUpdateParentId: false\n });\n }\n\n // Verify the updated task\n const updatedTask = updated.find(t => t.id === movedTaskId);\n if (updatedTask) {\n console.log('[UPDATED TASK VERIFICATION]', {\n id: updatedTask.id,\n name: updatedTask.name,\n finalParentId: updatedTask.parentId\n });\n }\n\n console.log('[ONCHANGE END]', {\n updatedCount: updated.length\n });\n console.log('=== GANTT CHART handleReorder END ===\\n');\n\n return updated;\n });\n onReorder?.(reorderedTasks, movedTaskId, inferredParentId);\n }, [onChange, onReorder]);\n\n // Build merged pixel overrides for DependencyLines: dragged task + cascade chain members\n const dependencyOverrides = useMemo(() => {\n const map = new Map(cascadeOverrides);\n if (draggedTaskOverride) {\n map.set(draggedTaskOverride.taskId, {\n left: draggedTaskOverride.left,\n width: draggedTaskOverride.width,\n });\n }\n return map;\n }, [cascadeOverrides, draggedTaskOverride]);\n\n /**\n * Handle real-time cascade progress — updates cascadeOverrides state each RAF\n * so non-dragged chain members re-render with their preview positions.\n * new Map() forces React to detect the state change.\n */\n const handleCascadeProgress = useCallback((overrides: Map<string, { left: number; width: number }>) => {\n setCascadeOverrides(new Map(overrides));\n }, []);\n\n /**\n * Handle cascade completion — updates all shifted tasks via onChange (functional updater)\n * and notifies the external onCascade consumer.\n */\n const handleCascade = useCallback((cascadedTasks: Task[]) => {\n // Update state by merging cascaded tasks into current tasks\n onChange?.((currentTasks) => {\n const cascadeMap = new Map(cascadedTasks.map(t => [t.id, t]));\n let finalTasks = currentTasks.map(t => cascadeMap.get(t.id) ?? t);\n\n // The first task in cascadedTasks is always the dragged task (from useTaskDrag.ts)\n // If the dragged task is a parent, its dates should NOT be recomputed from children\n // because the user explicitly positioned it. Children should follow the parent.\n const draggedTaskId = cascadedTasks[0]?.id;\n\n // Update parent dates for any cascaded tasks that have parents\n // Collect parent IDs that need updating\n const parentIdsToUpdate = new Set<string>();\n cascadedTasks.forEach(task => {\n if ((task as any).parentId) {\n parentIdsToUpdate.add((task as any).parentId);\n }\n });\n\n // Update each parent's dates and progress\n parentIdsToUpdate.forEach(parentId => {\n // Skip recomputing dates for the dragged task itself\n // The user's manual drag position should be preserved\n if (parentId === draggedTaskId) {\n // Still update progress from children, but not dates\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, progress: newProgress }\n : t\n );\n return;\n }\n\n const newDates = computeParentDates(parentId, finalTasks);\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, startDate: newDates.startDate.toISOString().split('T')[0], endDate: newDates.endDate.toISOString().split('T')[0], progress: newProgress }\n : t\n );\n });\n\n return finalTasks;\n });\n // Notify external consumer\n onCascade?.(cascadedTasks);\n }, [onChange, onCascade]);\n\n /**\n * Handle task selection from TaskList or TaskRow\n */\n const handleTaskSelect = useCallback((taskId: string | null) => {\n setSelectedTaskId(taskId);\n }, []);\n\n // Hierarchy callbacks\n const handleToggleCollapse = useCallback((parentId: string) => {\n setCollapsedParentIds(prev => {\n const next = new Set(prev);\n if (next.has(parentId)) {\n next.delete(parentId);\n } else {\n next.add(parentId);\n }\n return next;\n });\n }, []);\n\n const handlePromoteTask = useCallback((taskId: string) => {\n onChange?.((currentTasks) => {\n // Find the task to promote\n const taskToPromote = currentTasks.find(t => t.id === taskId);\n if (!taskToPromote || !(taskToPromote as any).parentId) {\n return currentTasks; // No parent to remove from\n }\n\n const parentId = (taskToPromote as any).parentId;\n\n // Find all siblings (children of the same parent)\n const siblings = currentTasks.filter(t => (t as any).parentId === parentId);\n\n if (siblings.length <= 1) {\n // Only child, just remove parentId\n return currentTasks.map(t =>\n t.id === taskId ? { ...t, parentId: undefined } : t\n );\n }\n\n // Find the last sibling in array order\n const lastSiblingIndex = currentTasks\n .map((t, i) => ({ task: t, index: i }))\n .filter(({ task }) => (task as any).parentId === parentId)\n .sort((a, b) => b.index - a.index)[0];\n\n if (!lastSiblingIndex) {\n return currentTasks.map(t =>\n t.id === taskId ? { ...t, parentId: undefined } : t\n );\n }\n\n // Create new array with task moved after last sibling\n const withoutPromotedTask = currentTasks.filter(t => t.id !== taskId);\n const insertIndex = lastSiblingIndex.index + 1;\n\n const promotedTask = { ...taskToPromote, parentId: undefined };\n const newTasks = [\n ...withoutPromotedTask.slice(0, insertIndex),\n promotedTask,\n ...withoutPromotedTask.slice(insertIndex)\n ];\n\n return newTasks;\n });\n }, [onChange]);\n\n const handleDemoteTask = useCallback((taskId: string, newParentId: string) => {\n onChange?.((currentTasks) => {\n // Check for circular hierarchy\n const wouldCreateCircular = (targetId: string, parentId: string, tasks: Task[]): boolean => {\n if (targetId === parentId) return true; // Can't be own parent\n\n const descendants = new Set<string>();\n function collect(id: string) {\n const children = getChildren(id, tasks);\n children.forEach(child => {\n descendants.add(child.id);\n collect(child.id);\n });\n }\n collect(targetId);\n return descendants.has(parentId);\n };\n\n if (wouldCreateCircular(taskId, newParentId, currentTasks)) {\n // Circular hierarchy detected, return unchanged\n return currentTasks;\n }\n\n // Remove any existing dependencies between the two tasks\n let updatedTasks = removeDependenciesBetweenTasks(taskId, newParentId, currentTasks);\n\n // Apply parentId change\n updatedTasks = updatedTasks.map(t => {\n if (t.id === taskId) {\n // Set parentId to demote under new parent\n return { ...t, parentId: newParentId };\n }\n return t;\n });\n\n // Compute and apply parent dates from all children\n const parentDates = computeParentDates(newParentId, updatedTasks);\n const parentProgress = computeParentProgress(newParentId, updatedTasks);\n\n updatedTasks = updatedTasks.map(t =>\n t.id === newParentId\n ? { ...t, startDate: parentDates.startDate.toISOString().split('T')[0], endDate: parentDates.endDate.toISOString().split('T')[0], progress: parentProgress }\n : t\n );\n\n return updatedTasks;\n });\n }, [onChange]);\n\n // Pan (grab-scroll) on empty grid area\n const panStateRef = useRef<{ active: boolean; startX: number; startY: number; scrollX: number; scrollY: number } | null>(null);\n\n const handlePanStart = useCallback((e: React.MouseEvent) => {\n // Only pan on left click, skip if clicking on a task bar, input, or task list\n if (e.button !== 0) return;\n const target = e.target as HTMLElement;\n if (target.closest('[data-taskbar]')) return;\n if (target.closest('input, button, textarea, [contenteditable]')) return;\n if (target.closest('.gantt-tl-overlay')) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n panStateRef.current = {\n active: true,\n startX: e.clientX,\n startY: e.clientY,\n scrollX: container.scrollLeft,\n scrollY: container.scrollTop,\n };\n // Blur any focused input so onBlur save handlers fire before pan starts\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n container.style.cursor = 'grabbing';\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n const handlePanMove = (e: MouseEvent) => {\n const pan = panStateRef.current;\n if (!pan?.active) return;\n const container = scrollContainerRef.current;\n if (!container) return;\n\n container.scrollLeft = pan.scrollX - (e.clientX - pan.startX);\n container.scrollTop = pan.scrollY - (e.clientY - pan.startY);\n };\n\n const handlePanEnd = () => {\n if (!panStateRef.current?.active) return;\n panStateRef.current = null;\n const container = scrollContainerRef.current;\n if (container) container.style.cursor = '';\n };\n\n window.addEventListener('mousemove', handlePanMove);\n window.addEventListener('mouseup', handlePanEnd);\n return () => {\n window.removeEventListener('mousemove', handlePanMove);\n window.removeEventListener('mouseup', handlePanEnd);\n };\n }, []);\n\n return (\n <div className=\"gantt-container\">\n <div\n ref={scrollContainerRef}\n className=\"gantt-scrollContainer\"\n style={{ height: containerHeight ?? 'auto', cursor: 'grab' }}\n onMouseDown={handlePanStart}\n >\n {/* Content wrapper - enables TaskList to scroll with chart horizontally */}\n <div className=\"gantt-scrollContent\">\n {/* TaskList - sticky left, scrolls with content horizontally */}\n <TaskList\n tasks={tasks}\n rowHeight={rowHeight}\n headerHeight={headerHeight}\n taskListWidth={taskListWidth}\n onTaskChange={handleTaskChange}\n selectedTaskId={selectedTaskId ?? undefined}\n onTaskSelect={handleTaskSelect}\n show={showTaskList}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n onScrollToTask={scrollToTask}\n onSelectedChipChange={setSelectedChip}\n onAdd={onAdd}\n onDelete={handleDelete}\n onInsertAfter={handleInsertAfter}\n onReorder={handleReorder}\n editingTaskId={editingTaskId}\n enableAddTask={enableAddTask}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={handlePromoteTask}\n onDemoteTask={handleDemoteTask}\n />\n\n {/* Chart area */}\n <div style={{ minWidth: `${gridWidth}px`, flex: 1 }}>\n {/* Sticky header - stays at top during vertical scroll, scrolls with content horizontally */}\n <div className=\"gantt-stickyHeader\" style={{ width: `${gridWidth}px` }}>\n <TimeScaleHeader\n days={dateRange}\n dayWidth={dayWidth}\n headerHeight={headerHeight}\n />\n </div>\n\n {/* Task area */}\n <div\n className=\"gantt-taskArea\"\n style={{\n position: 'relative',\n width: `${gridWidth}px`,\n }}\n >\n <GridBackground\n dateRange={dateRange}\n dayWidth={dayWidth}\n totalHeight={totalGridHeight}\n />\n\n {todayInRange && <TodayIndicator monthStart={monthStart} dayWidth={dayWidth} />}\n\n {/* Dependency lines SVG overlay */}\n <DependencyLines\n tasks={filteredTasks}\n allTasks={tasks}\n collapsedParentIds={collapsedParentIds}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n gridWidth={gridWidth}\n dragOverrides={dependencyOverrides}\n selectedDep={selectedChip}\n />\n\n {dragGuideLines && (\n <DragGuideLines\n isDragging={dragGuideLines.isDragging}\n dragMode={dragGuideLines.dragMode}\n left={dragGuideLines.left}\n width={dragGuideLines.width}\n totalHeight={totalGridHeight}\n />\n )}\n\n {filteredTasks.map((task, index) => (\n <TaskRow\n key={task.id}\n task={task}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n onChange={handleTaskChange}\n onDragStateChange={(state) => {\n if (state.isDragging) {\n setDragGuideLines(state);\n setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });\n } else {\n setDragGuideLines(null);\n setDraggedTaskOverride(null);\n }\n }}\n rowIndex={index}\n allTasks={tasks}\n enableAutoSchedule={enableAutoSchedule ?? false}\n disableConstraints={disableConstraints ?? false}\n overridePosition={cascadeOverrides.get(task.id)}\n onCascadeProgress={handleCascadeProgress}\n onCascade={handleCascade}\n highlightExpiredTasks={highlightExpiredTasks}\n />\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\nGanttChart.displayName = 'GanttChart';\n\nexport default GanttChart;\n","import { parseISO, isValid } from 'date-fns';\n\n/**\n * Parse date string as UTC to prevent DST issues\n * @param date - Date string or Date object\n * @returns Date object representing UTC midnight\n * @throws Error if date string is invalid\n */\nexport const parseUTCDate = (date: string | Date): Date => {\n if (typeof date === 'string') {\n // If already an ISO string (contains 'T'), parse directly\n // Otherwise, append UTC time for simple date strings (YYYY-MM-DD)\n const dateStr = date.includes('T') ? date : `${date}T00:00:00Z`;\n const parsed = new Date(dateStr);\n if (isNaN(parsed.getTime())) {\n throw new Error(`Invalid date string: ${date}`);\n }\n return parsed;\n }\n return date;\n};\n\n/**\n * Get all days in the month of given date (UTC)\n * @param date - Reference date (any day in the target month)\n * @returns Array of Date objects for each day in the month\n */\nexport const getMonthDays = (date: Date | string): Date[] => {\n const utcDate = parseUTCDate(date);\n const year = utcDate.getUTCFullYear();\n const month = utcDate.getUTCMonth();\n\n // Get days in month (handles leap years)\n const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n\n const days: Date[] = [];\n for (let day = 1; day <= daysInMonth; day++) {\n days.push(new Date(Date.UTC(year, month, day)));\n }\n\n return days;\n};\n\n/**\n * Calculate day offset from month start (0-based)\n * @param date - The date to calculate offset for\n * @param monthStart - The start of the month as reference\n * @returns Number of days from month start (negative if date is before month start)\n */\nexport const getDayOffset = (date: Date, monthStart: Date): number => {\n const dateMs = Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n );\n const startMs = Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n );\n return Math.round((dateMs - startMs) / (1000 * 60 * 60 * 24));\n};\n\n/**\n * Check if date is today (local timezone comparison)\n * Uses local time to determine today's date boundary so the result matches\n * the user's timezone rather than UTC (prevents off-by-one errors at midnight).\n * @param date - Date to check\n * @returns True if date is today, false otherwise\n */\nexport const isToday = (date: Date): boolean => {\n const now = new Date();\n // Use local time methods so the \"today\" boundary reflects the user's timezone.\n // getUTCFullYear/Month/Date would shift the day for non-UTC users.\n const today = new Date(Date.UTC(\n now.getFullYear(),\n now.getMonth(),\n now.getDate()\n ));\n const compareDate = new Date(Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n ));\n return today.getTime() === compareDate.getTime();\n};\n\n/**\n * Check if date is a weekend day (Saturday or Sunday)\n * @param date - Date to check\n * @returns True if date is Saturday (6) or Sunday (0), false otherwise\n */\nexport const isWeekend = (date: Date): boolean => {\n const day = date.getUTCDay();\n return day === 0 || day === 6; // Sunday (0) or Saturday (6)\n};\n\n/**\n * Calculate multi-month date range from task dates\n * Expands range to include full months with padding on both ends for drag flexibility\n * Adds 1 month before and 2 months after the task range\n * @param tasks - Array of tasks with startDate and endDate\n * @returns Array of Date objects for all days in the expanded range\n */\nexport const getMultiMonthDays = (tasks: Array<{ startDate: string | Date; endDate: string | Date }>): Date[] => {\n // Handle empty task array by returning current month\n if (!tasks || tasks.length === 0) {\n return getMonthDays(new Date());\n }\n\n // Find min and max dates from all tasks\n let minDate: Date | null = null;\n let maxDate: Date | null = null;\n\n for (const task of tasks) {\n const start = parseUTCDate(task.startDate);\n const end = parseUTCDate(task.endDate);\n\n if (!minDate || start.getTime() < minDate.getTime()) {\n minDate = start;\n }\n if (!maxDate || end.getTime() > maxDate.getTime()) {\n maxDate = end;\n }\n }\n\n if (!minDate || !maxDate) {\n return getMonthDays(new Date());\n }\n\n // Extend to full months: 1st of first month to last day of last month\n // Add padding: 2 months after for drag flexibility\n const startOfMonth = new Date(Date.UTC(\n minDate.getUTCFullYear(),\n minDate.getUTCMonth(),\n 1\n ));\n\n const endOfMonth = new Date(Date.UTC(\n maxDate.getUTCFullYear(),\n maxDate.getUTCMonth() + 1 + 2, // Original + 2 months padding after\n 0\n ));\n\n // Generate all dates in range\n const days: Date[] = [];\n const current = new Date(startOfMonth);\n\n while (current.getTime() <= endOfMonth.getTime()) {\n days.push(new Date(Date.UTC(\n current.getUTCFullYear(),\n current.getUTCMonth(),\n current.getUTCDate()\n )));\n // Move to next day\n current.setUTCDate(current.getUTCDate() + 1);\n }\n\n return days;\n};\n\n/**\n * Calculate month spans within a date range\n * @param dateRange - Array of Date objects representing the full range\n * @returns Array of month span objects with month, days count, and start index\n */\nexport const getMonthSpans = (\n dateRange: Date[]\n): Array<{ month: Date; days: number; startIndex: number }> => {\n if (dateRange.length === 0) {\n return [];\n }\n\n const spans: Array<{ month: Date; days: number; startIndex: number }> = [];\n let currentMonthYear = `${dateRange[0].getUTCFullYear()}-${dateRange[0].getUTCMonth()}`;\n let startOfMonthIndex = 0;\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const monthYear = `${date.getUTCFullYear()}-${date.getUTCMonth()}`;\n\n // When month changes, finalize the previous span and start a new one\n if (monthYear !== currentMonthYear) {\n spans.push({\n month: new Date(Date.UTC(\n dateRange[startOfMonthIndex].getUTCFullYear(),\n dateRange[startOfMonthIndex].getUTCMonth(),\n 1\n )),\n days: i - startOfMonthIndex,\n startIndex: startOfMonthIndex\n });\n currentMonthYear = monthYear;\n startOfMonthIndex = i;\n }\n\n // Last date - finalize the last span\n if (i === dateRange.length - 1) {\n spans.push({\n month: new Date(Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n 1\n )),\n days: i - startOfMonthIndex + 1,\n startIndex: startOfMonthIndex\n });\n }\n }\n\n return spans;\n};\n\n/**\n * Format date as DD.MM (e.g., 25.03 for March 25th)\n * @param date - Date to format\n * @returns Formatted date string in DD.MM format\n */\nexport const formatDateLabel = (date: Date | string): string => {\n const parsed = parseUTCDate(date);\n const day = String(parsed.getUTCDate()).padStart(2, '0');\n const month = String(parsed.getUTCMonth() + 1).padStart(2, '0');\n return `${day}.${month}`;\n};\n","import { Task, TaskDependency, LinkType, ValidationResult, DependencyError } from '../types';\n\n/**\n * Build adjacency list for dependency graph (task -> successors)\n */\nexport function buildAdjacencyList(tasks: Task[]): Map<string, string[]> {\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n const graph = new Map<string, string[]>();\n\n for (const task of tasks) {\n const successors: string[] = [];\n\n // Find all tasks that depend on this task (this task is a predecessor)\n for (const otherTask of tasks) {\n if (otherTask.dependencies) {\n for (const dep of otherTask.dependencies) {\n if (dep.taskId === task.id) {\n successors.push(otherTask.id);\n break;\n }\n }\n }\n }\n\n graph.set(task.id, successors);\n }\n\n return graph;\n}\n\n/**\n * Detect circular dependencies using depth-first search\n */\nexport function detectCycles(tasks: Task[]): { hasCycle: boolean; cyclePath?: string[] } {\n const graph = buildAdjacencyList(tasks);\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const path: string[] = [];\n\n function dfs(taskId: string): boolean {\n if (visiting.has(taskId)) {\n // Found cycle - current task is already in recursion stack\n return true;\n }\n if (visited.has(taskId)) {\n return false;\n }\n\n visiting.add(taskId);\n path.push(taskId);\n\n const successors = graph.get(taskId) || [];\n for (const successor of successors) {\n if (dfs(successor)) {\n return true;\n }\n }\n\n visiting.delete(taskId);\n path.pop();\n visited.add(taskId);\n return false;\n }\n\n for (const task of tasks) {\n if (dfs(task.id)) {\n return { hasCycle: true, cyclePath: [...path] };\n }\n }\n\n return { hasCycle: false };\n}\n\n/**\n * Compute lag (in days) from actual predecessor/successor dates.\n * This is the single source of truth for lag semantics across chips, arrows, and drag.\n *\n * Semantics (lag=0 = natural, gap-free connection):\n * - FS: lag = succStart - predEnd - 1 (adjacent days = 0)\n * - SS: lag = succStart - predStart\n * - FF: lag = succEnd - predEnd\n * - SF: lag = succEnd - predStart + 1 (symmetric to FS)\n */\nexport function computeLagFromDates(\n linkType: LinkType,\n predStart: Date,\n predEnd: Date,\n succStart: Date,\n succEnd: Date\n): number {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const pS = Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate());\n const pE = Date.UTC(predEnd.getUTCFullYear(), predEnd.getUTCMonth(), predEnd.getUTCDate());\n const sS = Date.UTC(succStart.getUTCFullYear(), succStart.getUTCMonth(), succStart.getUTCDate());\n const sE = Date.UTC(succEnd.getUTCFullYear(), succEnd.getUTCMonth(), succEnd.getUTCDate());\n switch (linkType) {\n case 'FS': return Math.round((sS - pE) / DAY_MS) - 1;\n case 'SS': return Math.round((sS - pS) / DAY_MS);\n case 'FF': return Math.round((sE - pE) / DAY_MS);\n case 'SF': return Math.round((sE - pS) / DAY_MS) + 1;\n }\n}\n\n/**\n * Calculate successor date based on predecessor dates, link type, and lag\n *\n * Link type semantics:\n * - FS: Successor start = Predecessor end + lag + 1 day (lag=0 → next day)\n * - SS: Successor start = Predecessor start + lag\n * - FF: Successor end = Predecessor end + lag\n * - SF: Successor end = Predecessor start + lag - 1 day (lag=0 → day before)\n */\nexport function calculateSuccessorDate(\n predecessorStart: Date,\n predecessorEnd: Date,\n linkType: LinkType,\n lag: number = 0\n): Date {\n const DAY_MS = 24 * 60 * 60 * 1000;\n\n switch (linkType) {\n case 'FS':\n // lag=0 → successor starts the day after predecessor ends (inclusive dates)\n return new Date(predecessorEnd.getTime() + (lag + 1) * DAY_MS);\n case 'SS':\n return new Date(predecessorStart.getTime() + lag * DAY_MS);\n case 'FF':\n return new Date(predecessorEnd.getTime() + lag * DAY_MS);\n case 'SF':\n // lag=0 → successor ends the day before predecessor starts (inclusive dates)\n return new Date(predecessorStart.getTime() + (lag - 1) * DAY_MS);\n }\n}\n\n/**\n * Validate all dependencies in the task list\n */\nexport function validateDependencies(tasks: Task[]): ValidationResult {\n const errors: DependencyError[] = [];\n const taskIds = new Set(tasks.map(t => t.id));\n\n // Check for missing predecessor references\n for (const task of tasks) {\n if (task.dependencies) {\n for (const dep of task.dependencies) {\n if (!taskIds.has(dep.taskId)) {\n errors.push({\n type: 'missing-task',\n taskId: task.id,\n message: `Dependency references non-existent task: ${dep.taskId}`,\n relatedTaskIds: [dep.taskId],\n });\n }\n }\n }\n }\n\n // Check for cycles\n const cycleResult = detectCycles(tasks);\n if (cycleResult.hasCycle && cycleResult.cyclePath) {\n errors.push({\n type: 'cycle',\n taskId: cycleResult.cyclePath[0],\n message: 'Circular dependency detected',\n relatedTaskIds: cycleResult.cyclePath,\n });\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Get successor tasks of a dragged task using BFS, filtered by link type(s).\n *\n * Returns tasks in breadth-first order (direct successors first, then their successors).\n * The dragged task itself is NOT included in the returned array.\n *\n * The visited set prevents infinite loops in case of cycles (cycle detection already\n * prevents cycles in valid data, but the guard adds safety during cascade computation).\n *\n * @param draggedTaskId - ID of the task being dragged\n * @param allTasks - All tasks in the chart\n * @param linkTypes - Dependency types to follow (default: ['FS'] preserves Phase 7 behavior)\n */\nexport function getSuccessorChain(\n draggedTaskId: string,\n allTasks: Task[],\n linkTypes: LinkType[] = ['FS']\n): Task[] {\n // Build successor map filtered by requested link types: predecessor -> [successors]\n const successorMap = new Map<string, string[]>();\n for (const task of allTasks) {\n successorMap.set(task.id, []);\n }\n for (const task of allTasks) {\n if (!task.dependencies) continue;\n for (const dep of task.dependencies) {\n if (linkTypes.includes(dep.type)) {\n const list = successorMap.get(dep.taskId) ?? [];\n list.push(task.id);\n successorMap.set(dep.taskId, list);\n }\n }\n }\n\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n const visited = new Set<string>();\n const queue: string[] = [draggedTaskId];\n const chain: Task[] = [];\n visited.add(draggedTaskId); // seed — not added to chain\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const successors = successorMap.get(current) ?? [];\n for (const sid of successors) {\n if (!visited.has(sid)) {\n visited.add(sid);\n const t = taskById.get(sid);\n if (t) {\n chain.push(t);\n queue.push(sid);\n }\n }\n }\n }\n\n return chain; // excludes dragged task\n}\n\n/**\n * Cascade successors by actual link constraints (BFS, constraint-based).\n *\n * Each successor in the chain is positioned using calculateSuccessorDate\n * with the predecessor's NEW dates and the actual lag — not a flat delta.\n *\n * - FS/SS: constraintDate = new start of successor (duration preserved)\n * - FF/SF: constraintDate = new end of successor (duration preserved)\n *\n * Locked tasks break the chain.\n * Also cascades hierarchy children when a parent moves (when parent moves by\n * dependency link, children must move with it to maintain parent-child relationship).\n * Returns only the cascaded successors (not the moved task itself).\n */\nexport function cascadeByLinks(\n movedTaskId: string,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[]\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n // Track each task's updated dates\n const updatedDates = new Map<string, { start: Date; end: Date }>();\n updatedDates.set(movedTaskId, { start: newStart, end: newEnd });\n\n const result: Task[] = [];\n const queue: string[] = [movedTaskId];\n const visited = new Set<string>([movedTaskId]);\n\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n const { start: predStart, end: predEnd } = updatedDates.get(currentId)!;\n\n // First, cascade hierarchy children of the current task if it's a parent\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (visited.has(child.id) || child.locked) continue;\n\n // When a parent moves, its children move by the same delta\n const origStart = new Date(child.startDate as string);\n const origEnd = new Date(child.endDate as string);\n const durationMs = origEnd.getTime() - origStart.getTime();\n\n const parentOrig = taskById.get(currentId)!;\n const parentOrigStart = new Date(parentOrig.startDate as string);\n const parentOrigEnd = new Date(parentOrig.endDate as string);\n\n // Calculate delta from parent's original to new position\n const parentStartDelta = predStart.getTime() - parentOrigStart.getTime();\n const parentEndDelta = predEnd.getTime() - parentOrigEnd.getTime();\n\n const newChildStart = new Date(origStart.getTime() + parentStartDelta);\n const newChildEnd = new Date(origEnd.getTime() + parentEndDelta);\n\n visited.add(child.id);\n updatedDates.set(child.id, { start: newChildStart, end: newChildEnd });\n result.push({\n ...child,\n startDate: newChildStart.toISOString().split('T')[0],\n endDate: newChildEnd.toISOString().split('T')[0],\n });\n queue.push(child.id);\n }\n\n // Then, cascade dependency successors\n for (const task of allTasks) {\n if (visited.has(task.id) || !task.dependencies || task.locked) continue;\n\n for (const dep of task.dependencies) {\n if (dep.taskId !== currentId) continue;\n\n const orig = taskById.get(task.id)!;\n const origStart = new Date(orig.startDate as string);\n const origEnd = new Date(orig.endDate as string);\n const durationMs = origEnd.getTime() - origStart.getTime();\n\n const constraintDate = calculateSuccessorDate(predStart, predEnd, dep.type, dep.lag ?? 0);\n\n let newSuccStart: Date;\n let newSuccEnd: Date;\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n newSuccStart = constraintDate;\n newSuccEnd = new Date(constraintDate.getTime() + durationMs);\n } else {\n // FF or SF: constraintDate is the end date\n newSuccEnd = constraintDate;\n newSuccStart = new Date(constraintDate.getTime() - durationMs);\n }\n\n visited.add(task.id);\n updatedDates.set(task.id, { start: newSuccStart, end: newSuccEnd });\n result.push({\n ...task,\n startDate: newSuccStart.toISOString().split('T')[0],\n endDate: newSuccEnd.toISOString().split('T')[0],\n });\n queue.push(task.id);\n break; // one predecessor per cascade step\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get transitive closure of successors for cascading.\n *\n * Direct successors of the changed task are filtered by firstLevelLinkTypes.\n * Their successors (and so on) are included regardless of link type.\n *\n * Also includes hierarchy children of any parent task in the chain - when a parent\n * moves via dependency cascade, its children must move with it.\n */\nexport function getTransitiveCascadeChain(\n changedTaskId: string,\n allTasks: Task[],\n firstLevelLinkTypes: LinkType[]\n): Task[] {\n const allTypesSuccessorMap = new Map<string, Task[]>();\n for (const task of allTasks) {\n allTypesSuccessorMap.set(task.id, []);\n }\n for (const task of allTasks) {\n if (!task.dependencies) continue;\n for (const dep of task.dependencies) {\n const list = allTypesSuccessorMap.get(dep.taskId) ?? [];\n list.push(task);\n allTypesSuccessorMap.set(dep.taskId, list);\n }\n }\n\n const directChildren = getChildren(changedTaskId, allTasks);\n const directSuccessors = getSuccessorChain(changedTaskId, allTasks, firstLevelLinkTypes);\n const initialChain = [...directChildren, ...directSuccessors].filter((task, index, arr) =>\n arr.findIndex(candidate => candidate.id === task.id) === index\n );\n\n const chain = [...initialChain];\n const visited = new Set<string>([changedTaskId, ...initialChain.map(t => t.id)]);\n const queue = [...initialChain];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n // Add hierarchy children of the current task if it's a parent\n const children = getChildren(current.id, allTasks);\n for (const child of children) {\n if (!visited.has(child.id)) {\n visited.add(child.id);\n chain.push(child);\n queue.push(child);\n }\n }\n\n const successors = allTypesSuccessorMap.get(current.id) ?? [];\n for (const successor of successors) {\n if (!visited.has(successor.id)) {\n visited.add(successor.id);\n chain.push(successor);\n queue.push(successor);\n }\n }\n }\n\n return chain;\n}\n\n/**\n * Recalculate incoming dependency lags after a task's dates change.\n * Used when completing a drag or applying a manual date change.\n */\nexport function recalculateIncomingLags(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[]\n): NonNullable<Task['dependencies']> {\n if (!task.dependencies) return [];\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n return task.dependencies.map(dep => {\n const predecessor = taskById.get(dep.taskId);\n if (!predecessor) return dep;\n\n const predStart = new Date(predecessor.startDate as string);\n const predEnd = new Date(predecessor.endDate as string);\n const lagDays = computeLagFromDates(dep.type, predStart, predEnd, newStartDate, newEndDate);\n return { ...dep, lag: lagDays };\n });\n}\n\n/**\n * Get all dependency edges for rendering\n * Returns array of { predecessorId, successorId, type, lag }\n */\nexport function getAllDependencyEdges(tasks: Task[]): Array<{\n predecessorId: string;\n successorId: string;\n type: LinkType;\n lag: number;\n}> {\n const edges: Array<{ predecessorId: string; successorId: string; type: LinkType; lag: number }> = [];\n\n for (const task of tasks) {\n if (task.dependencies) {\n for (const dep of task.dependencies) {\n edges.push({\n predecessorId: dep.taskId,\n successorId: task.id,\n type: dep.type,\n lag: dep.lag ?? 0,\n });\n }\n }\n }\n\n return edges;\n}\n\n// ============================================================================\n// Hierarchy Utilities (Phase 19)\n// ============================================================================\n\n/**\n * Get all child tasks of a parent task.\n * Returns tasks where task.parentId === parentId.\n */\nexport function getChildren(parentId: string, tasks: Task[]): Task[] {\n return tasks.filter(t => (t as any).parentId === parentId);\n}\n\n/**\n * Check if a task is a parent (has children).\n * Returns true if any task has this task as parentId.\n */\nexport function isTaskParent(taskId: string, tasks: Task[]): boolean {\n return tasks.some(t => (t as any).parentId === taskId);\n}\n\n/**\n * Compute parent task dates from children.\n * Returns { startDate, endDate } where:\n * - startDate = min(children.startDate) or own startDate if no children\n * - endDate = max(children.endDate) or own endDate if no children\n */\nexport function computeParentDates(parentId: string, tasks: Task[]): { startDate: Date; endDate: Date } {\n const children = getChildren(parentId, tasks);\n\n if (children.length === 0) {\n // Empty parent - use own dates or default\n const parent = tasks.find(t => t.id === parentId);\n const start = parent ? new Date(parent.startDate) : new Date();\n const end = parent ? new Date(parent.endDate) : new Date();\n return { startDate: start, endDate: end };\n }\n\n const startDates = children.map(c => new Date(c.startDate));\n const endDates = children.map(c => new Date(c.endDate));\n\n const minTime = Math.min(...startDates.map(d => d.getTime()));\n const maxTime = Math.max(...endDates.map(d => d.getTime()));\n\n return {\n startDate: new Date(minTime),\n endDate: new Date(maxTime),\n };\n}\n\n/**\n * Compute parent task progress from children (weighted average by duration).\n * Returns 0 if no children.\n * Progress is rounded to 1 decimal place.\n */\nexport function computeParentProgress(parentId: string, tasks: Task[]): number {\n const children = getChildren(parentId, tasks);\n\n if (children.length === 0) {\n return 0;\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n let totalWeight = 0;\n let weightedSum = 0;\n\n for (const child of children) {\n const start = new Date(child.startDate).getTime();\n const end = new Date(child.endDate).getTime();\n // Inclusive duration: (end - start + 1 day) / DAY_MS\n const duration = (end - start + DAY_MS) / DAY_MS;\n const progress = (child.progress ?? 0);\n\n totalWeight += duration;\n weightedSum += duration * progress;\n }\n\n if (totalWeight === 0) {\n return 0;\n }\n\n // Round to 1 decimal place\n return Math.round((weightedSum / totalWeight) * 10) / 10;\n}\n\n/**\n * Remove dependencies between two tasks in both directions.\n * When tasks become parent-child, their dependency link becomes meaningless.\n *\n * @param taskId1 - First task ID\n * @param taskId2 - Second task ID\n * @param tasks - All tasks array\n * @returns New tasks array with dependencies between the two tasks removed\n */\nexport function removeDependenciesBetweenTasks(\n taskId1: string,\n taskId2: string,\n tasks: Task[]\n): Task[] {\n return tasks.map(task => {\n if (task.id === taskId1 || task.id === taskId2) {\n if (!task.dependencies) return task;\n const otherTaskId = task.id === taskId1 ? taskId2 : taskId1;\n const filteredDependencies = task.dependencies.filter(dep => dep.taskId !== otherTaskId);\n // Only create new object if dependencies actually changed\n if (filteredDependencies.length === task.dependencies.length) {\n return task;\n }\n return {\n ...task,\n dependencies: filteredDependencies.length > 0 ? filteredDependencies : undefined,\n };\n }\n return task;\n });\n}\n\n/**\n * Find the parent ID of a task.\n * Returns the parentId of the task if found, undefined otherwise.\n *\n * @param taskId - ID of the task to find parent for\n * @param tasks - All tasks array\n * @returns Parent task ID or undefined if task is root or not found\n */\nexport function findParentId(taskId: string, tasks: Task[]): string | undefined {\n const task = tasks.find(t => t.id === taskId);\n return task?.parentId;\n}\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { format } from 'date-fns';\nimport { ru } from 'date-fns/locale';\nimport { getMonthSpans } from '../../utils/dateUtils';\nimport type { MonthSpan } from '../../types';\nimport './TimeScaleHeader.css';\n\nexport interface TimeScaleHeaderProps {\n /** Array of dates to display (from getMultiMonthDays) */\n days: Date[];\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of the header row in pixels */\n headerHeight: number;\n}\n\n/**\n * TimeScaleHeader component - displays two-row date headers for the Gantt chart\n *\n * Top row: Month names (Russian, left-aligned) spanning multiple day columns\n * Bottom row: Day numbers (centered) in individual columns\n */\nconst TimeScaleHeader: React.FC<TimeScaleHeaderProps> = ({\n days,\n dayWidth,\n headerHeight,\n}) => {\n // Calculate month spans using the utility from dateUtils\n const monthSpans = useMemo(() => getMonthSpans(days), [days]);\n\n // Split header height evenly between two rows\n const rowHeight = headerHeight / 2;\n\n // Calculate grid template for day row\n const dayGridTemplate = useMemo(\n () => `repeat(${days.length}, ${dayWidth}px)`,\n [days.length, dayWidth]\n );\n\n return (\n <div\n className=\"gantt-tsh-header\"\n style={{ height: `${headerHeight}px` }}\n >\n {/* Month row - top */}\n <div\n className=\"gantt-tsh-monthRow\"\n style={{ height: `${rowHeight}px` }}\n >\n {monthSpans.map((span: MonthSpan, index: number) => (\n <div\n key={`month-${index}`}\n className=\"gantt-tsh-monthCell\"\n style={{ width: `${span.days * dayWidth}px` }}\n >\n {format(span.month, 'LLLL yyyy', { locale: ru }).replace(/^./, (c) => c.toUpperCase())}\n </div>\n ))}\n </div>\n\n {/* Day row - bottom */}\n <div\n className=\"gantt-tsh-dayRow\"\n style={{\n height: `${rowHeight}px`,\n gridTemplateColumns: dayGridTemplate,\n }}\n >\n {days.map((day, index) => {\n const isWeekend = day.getDay() === 0 || day.getDay() === 6;\n const prevDay = days[index - 1];\n const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();\n // Use local date comparison for \"today\" (user's current date)\n const now = new Date();\n const isTodayDate =\n day.getUTCFullYear() === now.getFullYear() &&\n day.getUTCMonth() === now.getMonth() &&\n day.getUTCDate() === now.getDate();\n return (\n <div key={`day-${index}`} className={`gantt-tsh-dayCell ${isWeekend ? 'gantt-tsh-weekendDay' : ''} ${isMonthBoundary ? 'gantt-tsh-monthBoundary' : ''} ${isTodayDate ? 'gantt-tsh-today' : ''}`}>\n <span className=\"gantt-tsh-dayLabel\">{format(day, 'd')}</span>\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default TimeScaleHeader;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { parseUTCDate, formatDateLabel } from '../../utils/dateUtils';\nimport { calculateTaskBar, pixelsToDate } from '../../utils/geometry';\nimport { useTaskDrag } from '../../hooks/useTaskDrag';\nimport { isTaskParent, getChildren } from '../../utils/dependencyUtils';\nimport type { Task } from '../GanttChart';\nimport './TaskRow.css';\n\nexport interface TaskRowProps {\n /** Task data to render */\n task: Task;\n /** Start of the month for positioning calculations */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via drag/resize */\n onChange?: (updatedTask: Task) => void;\n /** Callback when task drag state changes (for rendering guide lines) */\n onDragStateChange?: (state: {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n }) => void;\n /** Index of the task row (used for dependency rendering) */\n rowIndex?: number;\n /** All tasks in the chart (used for dependency validation) */\n allTasks?: Task[];\n /** Whether auto-scheduling is enabled */\n enableAutoSchedule?: boolean;\n /** Whether to disable constraint checking during drag */\n disableConstraints?: boolean;\n /** Position override for cascade preview — when set, overrides both static and drag position */\n overridePosition?: { left: number; width: number };\n /** Called each RAF during cascade drag with override positions for non-dragged chain tasks */\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n /** Called when cascade drag completes; receives all shifted tasks including dragged task */\n onCascade?: (tasks: Task[]) => void;\n /** Optional horizontal divider line - renders above or below the task row */\n divider?: 'top' | 'bottom';\n /** Highlight expired/overdue tasks with red background */\n highlightExpiredTasks?: boolean;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Only re-renders if task properties that affect rendering change.\n *\n * NOTE: onChange is intentionally excluded from this comparison because:\n * 1. The parent (GanttChart) wraps onChange in useCallback for referential stability\n * 2. onChange is only called AFTER drag completes (not during drag)\n * 3. During drag, only the dragged TaskRow re-renders due to its internal drag state\n * 4. Other TaskRows don't need to re-render when one task is dragged\n *\n * NOTE: monthStart MUST be included because task positions are calculated relative to it.\n * When the grid expands (e.g., dragging a task left beyond the boundary), monthStart changes\n * and all tasks need to re-render to update their positions.\n *\n * NOTE: onCascadeProgress and onCascade are excluded from comparison (same pattern as onChange —\n * callbacks excluded from comparison because GanttChart wraps them in useCallback).\n *\n * Excluding onChange prevents re-render storms when dragging tasks with ~100 tasks.\n */\nconst arePropsEqual = (prevProps: TaskRowProps, nextProps: TaskRowProps) => {\n return (\n prevProps.task.id === nextProps.task.id &&\n prevProps.task.name === nextProps.task.name &&\n prevProps.task.startDate === nextProps.task.startDate &&\n prevProps.task.endDate === nextProps.task.endDate &&\n prevProps.task.color === nextProps.task.color &&\n prevProps.task.progress === nextProps.task.progress &&\n prevProps.task.accepted === nextProps.task.accepted &&\n prevProps.monthStart.getTime() === nextProps.monthStart.getTime() &&\n prevProps.dayWidth === nextProps.dayWidth &&\n prevProps.rowHeight === nextProps.rowHeight &&\n prevProps.overridePosition?.left === nextProps.overridePosition?.left &&\n prevProps.overridePosition?.width === nextProps.overridePosition?.width &&\n prevProps.allTasks === nextProps.allTasks &&\n prevProps.disableConstraints === nextProps.disableConstraints &&\n prevProps.task.locked === nextProps.task.locked &&\n prevProps.task.divider === nextProps.task.divider &&\n prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks\n // onChange, onCascadeProgress, onCascade excluded - see note above\n );\n};\n\n/**\n * TaskRow component - renders a single task row with a task bar\n *\n * Uses React.memo for performance optimization (QL-01).\n * The task bar is positioned absolutely based on start/end dates.\n */\nconst TaskRow: React.FC<TaskRowProps> = React.memo(\n ({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks }) => {\n // Extract divider from task prop\n const { divider: taskDivider } = task;\n\n // Parse dates as UTC\n const taskStartDate = useMemo(() => parseUTCDate(task.startDate), [task.startDate]);\n const taskEndDate = useMemo(() => parseUTCDate(task.endDate), [task.endDate]);\n\n // Hierarchy: compute isParent and childCount\n const isParent = useMemo(() => {\n return allTasks ? isTaskParent(task.id, allTasks) : false;\n }, [allTasks, task.id]);\n\n const childCount = useMemo(() => {\n return allTasks ? getChildren(task.id, allTasks).length : 0;\n }, [allTasks, task.id]);\n\n // Calculate expiration status for overdue tasks\n const isExpired = useMemo(() => {\n if (!highlightExpiredTasks) return false;\n\n // Create today boundary using LOCAL time so the day boundary matches the user's timezone.\n // Using getUTCFullYear/Month/Date here would shift the day boundary by the UTC offset —\n // e.g. for UTC+3 at 00:30 local, getUTCDate() still returns yesterday.\n const now = new Date();\n const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));\n\n // Parse task dates as UTC\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n\n // Task must be incomplete (progress < 100%) to be expired\n const actualProgress = task.progress ?? 0;\n if (actualProgress >= 100) {\n return false; // Completed tasks are never expired\n }\n\n // Simple formula:\n // duration = (end - start + 1) days\n // elapsed = min(today - start, duration) days\n // expected = elapsed / duration * 100\n const msPerDay = 1000 * 60 * 60 * 24;\n const duration = taskEnd.getTime() - taskStart.getTime() + msPerDay;\n const elapsedFromToday = today.getTime() - taskStart.getTime();\n const elapsed = Math.min(Math.max(0, elapsedFromToday), duration);\n const expected = (elapsed / duration) * 100;\n\n return actualProgress < expected;\n }, [task.startDate, task.endDate, task.progress, highlightExpiredTasks]);\n\n // Calculate task bar position and dimensions\n const { left, width } = useMemo(\n () => calculateTaskBar(taskStartDate, taskEndDate, monthStart, dayWidth),\n [taskStartDate, taskEndDate, monthStart, dayWidth]\n );\n\n // Determine task bar color\n const barColor = isExpired\n ? 'var(--gantt-expired-color)'\n : (task.color || 'var(--gantt-task-bar-default-color)');\n\n // Parent bar uses gradient background (handled in CSS), override color here\n const parentBarStyle = isParent ? {} : { backgroundColor: barColor };\n\n // Calculate clamped and rounded progress width\n const progressWidth = useMemo(() => {\n if (task.progress === undefined || task.progress <= 0) return 0;\n return Math.min(100, Math.max(0, Math.round(task.progress)));\n }, [task.progress]);\n\n // Determine progress color based on completion status\n const progressColor = useMemo(() => {\n if (isExpired) {\n // Dark red for expired tasks\n return 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)';\n }\n if (progressWidth === 100) {\n return task.accepted\n ? 'var(--gantt-progress-accepted, #22c55e)' // Green for accepted\n : 'var(--gantt-progress-completed, #fbbf24)'; // Yellow for completed (not accepted)\n }\n // Darker shade using color-mix() with task color or default\n const baseColor = task.color || 'var(--gantt-task-bar-default-color)';\n return `color-mix(in srgb, ${baseColor} 40%, black)`;\n }, [isExpired, progressWidth, task.accepted, task.color]);\n\n // Handle drag end - call onChange with updated task\n const handleDragEnd = (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => {\n const updatedTask: Task = {\n ...task,\n startDate: result.startDate.toISOString(),\n endDate: result.endDate.toISOString(),\n ...(result.updatedDependencies !== undefined && { dependencies: result.updatedDependencies }),\n };\n onChange?.(updatedTask);\n };\n\n // Use drag hook for interactive drag/resize\n const {\n isDragging,\n dragMode,\n currentLeft,\n currentWidth,\n dragHandleProps,\n } = useTaskDrag({\n taskId: task.id,\n initialStartDate: taskStartDate,\n initialEndDate: taskEndDate,\n monthStart,\n dayWidth,\n onDragEnd: handleDragEnd,\n onDragStateChange,\n edgeZoneWidth: 20,\n allTasks,\n rowIndex,\n enableAutoSchedule,\n disableConstraints,\n locked: task.locked,\n onCascadeProgress,\n onCascade,\n });\n\n // Use override position (for cascade preview) with fallback to drag or static position\n const displayLeft = overridePosition?.left ?? (isDragging ? currentLeft : left);\n const displayWidth = overridePosition?.width ?? (isDragging ? currentWidth : width);\n\n // Format date labels for display - update in real-time during drag\n const currentStartDate = isDragging\n ? pixelsToDate(displayLeft, monthStart, dayWidth)\n : taskStartDate;\n const currentEndDate = isDragging\n ? pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth)\n : taskEndDate;\n\n const startDateLabel = formatDateLabel(currentStartDate);\n const endDateLabel = formatDateLabel(currentEndDate);\n\n // Calculate duration in days\n const durationDays = Math.round(\n (currentEndDate.getTime() - currentStartDate.getTime()) / (1000 * 60 * 60 * 24)\n ) + 1;\n\n // Format child count label for parent tasks (Russian plural)\n const getChildCountLabel = (count: number): string => {\n if (count === 1) return '1 задача';\n // For 2, 3, 4 tasks use \"задачи\" (genitive singular)\n // For 5+ tasks use \"задач\" (genitive plural)\n const lastTwoDigits = count % 100;\n const lastDigit = count % 10;\n if (lastTwoDigits >= 11 && lastTwoDigits <= 14) return `${count} задач`;\n if (lastDigit === 1) return `${count} задача`;\n if (lastDigit >= 2 && lastDigit <= 4) return `${count} задачи`;\n return `${count} задач`;\n };\n\n // Determine if progress text fits inside the bar\n // Estimate: duration text (~\"15 д\" = ~30px) + progress text (~\"100%\" = ~30px) + padding (~16px)\n const estimatedTextWidth = durationDays >= 10 ? 76 : 62; // \"15 д 100%\" = ~76px, \"1 д 100%\" = ~62px\n const showProgressInside = progressWidth > 0 && displayWidth > estimatedTextWidth;\n\n return (\n <div\n className=\"gantt-tr-row\"\n style={{ height: `${rowHeight}px` }}\n >\n {taskDivider === 'top' && <div className=\"gantt-tr-divider gantt-tr-divider-top\" />}\n <div className=\"gantt-tr-taskContainer\">\n <div\n data-taskbar\n className={`gantt-tr-taskBar ${isDragging ? 'gantt-tr-dragging' : ''} ${task.locked ? 'gantt-tr-locked' : ''} ${isParent ? 'gantt-tr-parentBar' : ''}`}\n style={{\n left: `${displayLeft}px`,\n width: `${displayWidth}px`,\n ...parentBarStyle,\n height: isParent ? 'var(--gantt-parent-bar-height, 14px)' : 'var(--gantt-task-bar-height)',\n cursor: dragHandleProps.style.cursor,\n userSelect: dragHandleProps.style.userSelect,\n }}\n onMouseDown={dragHandleProps.onMouseDown}\n >\n {progressWidth > 0 && (\n <div\n className=\"gantt-tr-progressBar\"\n style={{\n width: `${progressWidth}%`,\n backgroundColor: progressColor,\n }}\n />\n )}\n {!isParent && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleLeft\" />}\n <span className=\"gantt-tr-taskDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n {progressWidth > 0 && showProgressInside && (\n <span className=\"gantt-tr-progressText\">\n {progressWidth}%\n </span>\n )}\n {!isParent && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleRight\" />}\n </div>\n <div\n className={`gantt-tr-leftLabels ${task.locked ? 'gantt-tr-leftLabels-locked' : ''}`}\n style={{\n left: `${displayLeft}px`\n }}\n >\n <span className=\"gantt-tr-dateLabel gantt-tr-dateLabelLeft\">\n {startDateLabel}–{endDateLabel}\n </span>\n </div>\n {task.locked && (\n <svg\n className=\"gantt-tr-lockIcon\"\n style={{\n position: 'absolute',\n left: `${displayLeft - 16}px`,\n top: '50%',\n transform: 'translateY(-50%)',\n width: '12px',\n height: '12px',\n color: '#444',\n pointerEvents: 'none',\n }}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-label=\"Locked\"\n aria-hidden=\"false\"\n >\n <path d=\"M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM12 17c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z\" />\n </svg>\n )}\n <div\n className=\"gantt-tr-rightLabels\"\n style={{\n left: `${displayLeft + displayWidth}px`,\n }}\n >\n {progressWidth > 0 && !showProgressInside && (\n <span className=\"gantt-tr-externalProgress\">\n {progressWidth}%\n </span>\n )}\n <span className=\"gantt-tr-externalTaskName\">\n {task.name}\n </span>\n </div>\n </div>\n {taskDivider === 'bottom' && <div className=\"gantt-tr-divider gantt-tr-divider-bottom\" />}\n </div>\n );\n },\n arePropsEqual\n);\n\nTaskRow.displayName = 'TaskRow';\n\nexport default TaskRow;\n","/**\n * Calculate day difference in UTC\n */\nconst getUTCDayDifference = (date1: Date, date2: Date): number => {\n const ms1 = Date.UTC(\n date1.getUTCFullYear(),\n date1.getUTCMonth(),\n date1.getUTCDate()\n );\n const ms2 = Date.UTC(\n date2.getUTCFullYear(),\n date2.getUTCMonth(),\n date2.getUTCDate()\n );\n return Math.round((ms1 - ms2) / (1000 * 60 * 60 * 24));\n};\n\n/**\n * Calculate task bar positioning and dimensions\n * @param taskStartDate - Start date of the task\n * @param taskEndDate - End date of the task\n * @param monthStart - Start of the month/visible range\n * @param dayWidth - Width of each day in pixels\n * @returns Object with left position and width in pixels\n */\nexport const calculateTaskBar = (\n taskStartDate: Date,\n taskEndDate: Date,\n monthStart: Date,\n dayWidth: number\n): { left: number; width: number } => {\n const startOffset = getUTCDayDifference(taskStartDate, monthStart);\n const duration = getUTCDayDifference(taskEndDate, taskStartDate);\n\n // Round to avoid sub-pixel rendering issues\n const left = Math.round(startOffset * dayWidth);\n const width = Math.round((duration + 1) * dayWidth); // +1 to include end date\n\n return { left, width };\n};\n\n/**\n * Convert pixel position to date (inverse of calculateTaskBar)\n * @param pixels - Position in pixels (left or width)\n * @param monthStart - Start of the month/visible range\n * @param dayWidth - Width of each day in pixels\n * @returns Date calculated from pixel position\n */\nexport const pixelsToDate = (pixels: number, monthStart: Date, dayWidth: number): Date => {\n const days = Math.round(pixels / dayWidth);\n return new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + days\n ));\n};\n\n/**\n * Calculate total width for month grid\n * @param daysInMonth - Number of days in the month\n * @param dayWidth - Width of each day in pixels\n * @returns Total grid width in pixels\n */\nexport const calculateGridWidth = (daysInMonth: number, dayWidth: number): number => {\n return Math.round(daysInMonth * dayWidth);\n};\n\n/**\n * Detect which edge zone the cursor is in on a task bar\n * @param clientX - Mouse X coordinate relative to viewport\n * @param taskBarElement - The task bar DOM element\n * @param edgeZoneWidth - Width of edge zones in pixels (default: 12px)\n * @returns 'left' if in left edge, 'right' if in right edge, 'move' if in middle\n */\nexport const detectEdgeZone = (\n clientX: number,\n taskBarElement: HTMLElement,\n edgeZoneWidth: number = 12\n): 'left' | 'right' | 'move' => {\n const rect = taskBarElement.getBoundingClientRect();\n const relativeX = Math.round(clientX - rect.left);\n const width = Math.round(rect.width);\n\n // When zones overlap (width <= 2 * edgeZoneWidth), prefer the closer edge\n if (width <= 2 * edgeZoneWidth) {\n // Cursor is in overlapping edge zone, return closer edge\n const distanceToLeft = relativeX;\n const distanceToRight = width - relativeX;\n return distanceToLeft <= distanceToRight ? 'left' : 'right';\n }\n\n // Check left edge zone\n if (relativeX >= 0 && relativeX <= edgeZoneWidth) {\n return 'left';\n }\n\n // Check right edge zone\n if (relativeX >= width - edgeZoneWidth && relativeX <= width) {\n return 'right';\n }\n\n // Middle area - move mode\n return 'move';\n};\n\n/**\n * Get appropriate cursor style for drag position\n * @param position - The drag position (left edge, right edge, or move)\n * @returns CSS cursor string for the position\n */\nexport const getCursorForPosition = (position: 'left' | 'right' | 'move'): string => {\n switch (position) {\n case 'left':\n case 'right':\n return 'ew-resize';\n case 'move':\n return 'grab';\n default:\n return 'default';\n }\n};\n\n/**\n * Calculate grid line positions for a date range\n * @param dateRange - Array of Date objects representing the visible range\n * @param dayWidth - Width of each day column in pixels\n * @returns Array of grid line objects with x position and flags\n */\nexport const calculateGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean; isWeekStart: boolean }> => {\n const lines: Array<{ x: number; isMonthStart: boolean; isWeekStart: boolean }> = [];\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const x = Math.round(i * dayWidth);\n const isMonthStart = i === 0 ? false : date.getUTCDate() === 1;\n const isWeekStart = date.getUTCDay() === 1; // Monday\n\n lines.push({ x, isMonthStart, isWeekStart });\n }\n\n // Add final line at the end of the range\n if (dateRange.length > 0) {\n lines.push({\n x: Math.round(dateRange.length * dayWidth),\n isMonthStart: false,\n isWeekStart: false\n });\n }\n\n return lines;\n};\n\n/**\n * Calculate weekend background blocks for a date range\n * @param dateRange - Array of Date objects representing the visible range\n * @param dayWidth - Width of each day column in pixels\n * @returns Array of weekend block objects with left position and width\n */\nexport const calculateWeekendBlocks = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ left: number; width: number }> => {\n const blocks: Array<{ left: number; width: number }> = [];\n let inWeekend = false;\n let weekendStartIndex = -1;\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const dayOfWeek = date.getUTCDay();\n const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; // Sunday or Saturday\n\n if (isWeekend && !inWeekend) {\n // Start of a weekend block\n inWeekend = true;\n weekendStartIndex = i;\n } else if (!isWeekend && inWeekend) {\n // End of a weekend block\n inWeekend = false;\n const left = Math.round(weekendStartIndex * dayWidth);\n const width = Math.round((i - weekendStartIndex) * dayWidth);\n blocks.push({ left, width });\n }\n }\n\n // Handle case where range ends on a weekend\n if (inWeekend && weekendStartIndex >= 0) {\n const left = Math.round(weekendStartIndex * dayWidth);\n const width = Math.round((dateRange.length - weekendStartIndex) * dayWidth);\n blocks.push({ left, width });\n }\n\n return blocks;\n};\n\n/**\n * Calculate SVG cubic Bezier curve path for dependency lines\n * @param from - Start point {x, y} (right edge of predecessor)\n * @param to - End point {x, y} (left edge of successor)\n * @returns SVG path string for cubic Bezier curve\n */\nexport const calculateBezierPath = (\n from: { x: number; y: number },\n to: { x: number; y: number }\n): string => {\n // Control points create smooth vertical curve\n // Offset is proportional to vertical distance for natural-looking curves\n const verticalDistance = Math.abs(to.y - from.y);\n const cpOffset = Math.max(verticalDistance * 0.5, 20); // Minimum 20px for same-row connections\n\n // For same-row connections, use arc above the task bars\n if (from.y === to.y) {\n const arcHeight = 20;\n const midX = (from.x + to.x) / 2;\n return `M ${from.x} ${from.y} Q ${midX} ${from.y - arcHeight} ${to.x} ${to.y}`;\n }\n\n // Standard cubic Bezier for multi-row connections\n const cp1x = from.x;\n const cp1y = from.y + (to.y > from.y ? cpOffset : -cpOffset);\n const cp2x = to.x;\n const cp2y = to.y - (to.y > from.y ? cpOffset : -cpOffset);\n\n return `M ${Math.round(from.x)} ${Math.round(from.y)} C ${Math.round(cp1x)} ${Math.round(cp1y)}, ${Math.round(cp2x)} ${Math.round(cp2y)}, ${Math.round(to.x)} ${Math.round(to.y)}`;\n};\n\n/**\n * Calculate SVG path for dependency lines based on link type connection semantics.\n *\n * Connection points per link type:\n * - FS: predecessor RIGHT → successor LEFT (arrow points right, enters left edge)\n * - SS: predecessor LEFT → successor LEFT (arrow points right, enters left edge)\n * - FF: predecessor RIGHT → successor RIGHT (arrow points left, enters right edge)\n * - SF: predecessor LEFT → successor RIGHT (arrow points left, enters right edge)\n *\n * @param from - Start point {x, y}\n * @param to - End point {x, y}\n * @param arrivesFromRight - true for FF and SF (arrow enters right edge of successor)\n */\nexport const calculateDependencyPath = (\n from: { x: number; y: number },\n to: { x: number; y: number },\n arrivesFromRight: boolean\n): string => {\n const fx = Math.round(from.x);\n const fy = Math.round(from.y);\n const tx = Math.round(to.x);\n const ty = Math.round(to.y);\n\n // Same row: straight horizontal line\n if (fy === ty) {\n return `M ${fx} ${fy} H ${tx}`;\n }\n\n const C = 2; // chamfer size\n const goingDown = ty > fy;\n const dirY = goingDown ? 1 : -1;\n\n if (arrivesFromRight) {\n // Arrow arrives at the RIGHT edge of successor (FF, SF).\n // Same chamfer formula as the FS/SS branch: stop C short of tx in the direction of travel,\n // then diagonal to tx, then vertical. The endpoints differ (right edge vs left edge),\n // but the path shape — natural inside-corner chamfer — is identical.\n const goingRight = tx >= fx;\n const dirX = goingRight ? 1 : -1;\n\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n } else {\n // Arrow arrives at the LEFT edge of successor (FS, SS) — same as existing calculateOrthogonalPath\n const goingRight = tx >= fx;\n const dirX = goingRight ? 1 : -1;\n\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n }\n};\n\n/**\n * Calculate SVG Г-shaped (L-shaped) path for FS dependency lines.\n * Goes vertically from the right edge of the predecessor bar, then horizontally\n * to the left edge of the successor bar. Supports negative lag (overlap).\n * @param from - Start point {x, y} (right edge of predecessor, vertical center)\n * @param to - End point {x, y} (left edge of successor, vertical center)\n * @returns SVG path string\n */\nexport const calculateOrthogonalPath = (\n from: { x: number; y: number },\n to: { x: number; y: number }\n): string => {\n const fx = Math.round(from.x);\n const fy = Math.round(from.y);\n const tx = Math.round(to.x);\n const ty = Math.round(to.y);\n\n // Same row: straight horizontal line\n if (fy === ty) {\n return `M ${fx} ${fy} H ${tx}`;\n }\n\n const C = 2; // chamfer size\n const goingDown = ty > fy;\n const goingRight = tx >= fx;\n const dirY = goingDown ? 1 : -1;\n const dirX = goingRight ? 1 : -1;\n\n // Shape: horizontal exit → chamfer → vertical arrival (arrow points down/up)\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n\n // Sharp corner fallback (very short segments)\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n};\n","'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport { detectEdgeZone } from '../utils/geometry';\nimport type { Task, TaskDependency, LinkType } from '../types';\nimport { calculateSuccessorDate, getSuccessorChain, getTransitiveCascadeChain, recalculateIncomingLags, getChildren, isTaskParent, cascadeByLinks } from '../utils/dependencyUtils';\n\n/**\n * Get transitive closure of successors for cascading.\n *\n * For proper cascading in mixed link type chains (e.g., A--FS-->B--SS-->C),\n * we need to include cascaded tasks' successors regardless of link type.\n *\n * The chain is:\n * 1. Direct successors of the dragged task, filtered by firstLevelLinkTypes\n * 2. ALL successors (any type) of those tasks, recursively\n *\n * @param draggedTaskId - ID of the task being dragged\n * @param allTasks - All tasks in the chart\n * @param firstLevelLinkTypes - Link types to use for direct successors\n * @returns Array of tasks in the cascade chain (transitive closure)\n */\n/**\n * Global drag manager that persists across HMR\n *\n * This singleton manages active drag operations at the module level,\n * ensuring that drag state survives React Fast Refresh (HMR).\n *\n * The key insight: When HMR occurs during a drag operation:\n * 1. The component unmounts and its useEffect cleanup removes window listeners\n * 2. The component remounts with fresh refs (isDraggingRef = false)\n * 3. But the user is still holding the mouse button!\n * 4. Without module-level state, the drag operation is orphaned\n *\n * Solution: Store active drag state in module-level singleton and\n * use a global cleanup effect to always handle mouseup/mousemove.\n */\ninterface ActiveDragState {\n taskId: string;\n mode: 'move' | 'resize-left' | 'resize-right';\n startX: number;\n initialLeft: number;\n initialWidth: number;\n currentLeft: number;\n currentWidth: number;\n dayWidth: number;\n monthStart: Date;\n onProgress: (left: number, width: number) => void;\n onComplete: (finalLeft: number, finalWidth: number) => void;\n onCancel: () => void;\n allTasks: Task[];\n disableConstraints?: boolean;\n cascadeChain: Task[]; // FS+SS+FF+SF successors of dragged task (Phase 10: added SF)\n cascadeChainFS: Task[]; // FS-only successors (part of resize-right cascade with FF)\n cascadeChainStart: Task[]; // SS+SF successors (resize-left cascade) - Phase 10: renamed from cascadeChainSS\n cascadeChainEnd: Task[]; // FS+FF successors (resize-right cascade) - Phase 9\n hierarchyChain: Task[]; // Phase 19: children of parent task (for cascade drag)\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n}\n\nlet globalActiveDrag: ActiveDragState | null = null;\nlet globalRafId: number | null = null;\n\n/**\n * Complete the active drag operation\n */\nfunction completeDrag() {\n if (globalRafId !== null) {\n cancelAnimationFrame(globalRafId);\n globalRafId = null;\n }\n\n if (globalActiveDrag) {\n // Clear cascade overrides before completing (avoids stale preview positions)\n globalActiveDrag.onCascadeProgress?.(new Map());\n const { onComplete, currentLeft, currentWidth } = globalActiveDrag;\n globalActiveDrag = null;\n onComplete(currentLeft, currentWidth);\n }\n}\n\n/**\n * Cancel the active drag operation\n */\nfunction cancelDrag() {\n if (globalRafId !== null) {\n cancelAnimationFrame(globalRafId);\n globalRafId = null;\n }\n\n if (globalActiveDrag) {\n const { onCancel } = globalActiveDrag;\n globalActiveDrag = null;\n onCancel();\n }\n}\n\n/**\n * Snap pixel value to grid (day boundaries)\n */\nfunction snapToGrid(pixels: number, dayWidth: number): number {\n return Math.round(pixels / dayWidth) * dayWidth;\n}\n\n/**\n * Check if a task move would violate dependency constraints\n * Only blocks move operations, not resize (per requirements)\n */\nfunction canMoveTask(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[]\n): { allowed: boolean; reason?: string } {\n if (!task.dependencies || task.dependencies.length === 0) {\n return { allowed: true };\n }\n\n // For each predecessor, check if the new position respects the constraint\n for (const dep of task.dependencies) {\n const predecessor = allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n\n const predecessorStart = new Date(predecessor.startDate);\n const predecessorEnd = new Date(predecessor.endDate);\n\n // Calculate expected date based on link type (lag ignored, always 0)\n const expectedDate = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n dep.type,\n 0 // lag not used in calculations\n );\n\n // Check constraint based on link type\n const targetIsStart = dep.type.endsWith('S');\n const targetDate = targetIsStart ? newStartDate : newEndDate;\n\n // Allow move if target date is on or after expected date\n // (give 1-day tolerance for rounding)\n const dayDiff = (targetDate.getTime() - expectedDate.getTime()) / (24 * 60 * 60 * 1000);\n\n if (dayDiff < -1) {\n return {\n allowed: false,\n reason: `Would violate ${dep.type} dependency from \"${predecessor.name}\"`\n };\n }\n }\n\n return { allowed: true };\n}\n\n/**\n * Recalculate lag values for incoming dependencies after drag completion.\n *\n * Lag formulas:\n * - FS: lag = startB - endA (can be negative)\n * - SS: lag = startB - startA (floor at 0)\n * - FF: lag = endB - endA (can be negative)\n * - SF: lag = endB - startA (ceiling at 0)\n */\n/**\n * Global mouse move handler - attached once and persists across HMR\n */\nfunction handleGlobalMouseMove(e: MouseEvent) {\n if (!globalActiveDrag || globalRafId !== null) {\n return;\n }\n\n globalRafId = requestAnimationFrame(() => {\n if (!globalActiveDrag) {\n globalRafId = null;\n return;\n }\n\n const activeDrag = globalActiveDrag;\n\n const { startX, initialLeft, initialWidth, mode, dayWidth, onProgress, allTasks } = activeDrag;\n const deltaX = e.clientX - startX;\n\n let newLeft = initialLeft;\n let newWidth = initialWidth;\n\n switch (mode) {\n case 'move':\n newLeft = snapToGrid(initialLeft + deltaX, dayWidth);\n break;\n case 'resize-left':\n const snappedLeft = snapToGrid(initialLeft + deltaX, dayWidth);\n newLeft = snappedLeft;\n const rightEdge = initialLeft + initialWidth;\n newWidth = Math.max(dayWidth, rightEdge - snappedLeft);\n break;\n case 'resize-right':\n const snappedWidth = snapToGrid(initialWidth + deltaX, dayWidth);\n newWidth = Math.max(dayWidth, snappedWidth);\n break;\n }\n\n // Hard mode: check left-move boundary against predecessor.startDate (Phase 7)\n // Child can move left until its startDate would go before predecessor.startDate\n // Also applies to resize-left: the left edge cannot cross the predecessor's start date\n if ((mode === 'move' || mode === 'resize-left') && allTasks.length > 0 && !activeDrag.disableConstraints) {\n const currentTask = allTasks.find(t => t.id === activeDrag.taskId);\n if (currentTask && currentTask.dependencies && currentTask.dependencies.length > 0) {\n let minAllowedLeft = -Infinity; // in pixels from monthStart; -Infinity means no floor unless a real FS/SS predecessor sets one\n for (const dep of currentTask.dependencies) {\n if (dep.type !== 'FS' && dep.type !== 'SS') continue; // Phase 8: FS and SS\n const predecessor = activeDrag.allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n // Boundary: child.startDate >= predecessor.startDate (allows negative lag)\n const predStart = new Date(predecessor.startDate as string);\n const predStartOffset = Math.round(\n (Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const predStartLeft = Math.round(predStartOffset * activeDrag.dayWidth);\n minAllowedLeft = Math.max(minAllowedLeft, predStartLeft);\n }\n // Clamp: don't let task go left of boundary\n newLeft = Math.max(minAllowedLeft, newLeft);\n }\n // For resize-left, after clamping newLeft the right edge is fixed so newWidth must be recomputed\n if (mode === 'resize-left') {\n const rightEdge = activeDrag.initialLeft + activeDrag.initialWidth;\n newWidth = Math.max(activeDrag.dayWidth, rightEdge - newLeft);\n }\n }\n\n // Phase 10: SF constraint: endB <= startA (lag ceiling at 0)\n // Applies when B is moved right or resized-right\n if ((mode === 'move' || mode === 'resize-right') && allTasks.length > 0 && !activeDrag.disableConstraints) {\n const currentTask = allTasks.find(t => t.id === activeDrag.taskId);\n if (currentTask && currentTask.dependencies && currentTask.dependencies.length > 0) {\n for (const dep of currentTask.dependencies) {\n if (dep.type !== 'SF') continue;\n const predecessor = activeDrag.allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n const predStart = new Date(predecessor.startDate as string);\n const predStartOffset = Math.round(\n (Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) -\n Date.UTC(activeDrag.monthStart.getUTCFullYear(), activeDrag.monthStart.getUTCMonth(), activeDrag.monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const predStartLeft = Math.round(predStartOffset * activeDrag.dayWidth);\n\n // SF lag=0 boundary: B's visual end = day before A's start (adjacent = lag 0)\n // B.right (exclusive pixel) = predStartLeft at lag=0\n const sfBoundaryRight = predStartLeft;\n if (mode === 'move') {\n // Move mode: when B would hit startA constraint, stop movement entirely\n const proposedEndRight = newLeft + activeDrag.initialWidth;\n if (proposedEndRight > sfBoundaryRight) {\n newLeft = Math.max(activeDrag.initialLeft, sfBoundaryRight - activeDrag.initialWidth);\n }\n } else {\n // Resize-right mode: clamp width so endB = startA (lag=0)\n const currentEndRight = newLeft + newWidth;\n if (currentEndRight > sfBoundaryRight) {\n newWidth = Math.max(activeDrag.dayWidth, sfBoundaryRight - newLeft);\n }\n }\n }\n }\n }\n\n const draggedTask = allTasks.find(t => t.id === activeDrag.taskId);\n const isParentDrag = draggedTask ? isTaskParent(draggedTask.id, allTasks) : false;\n\n // Phase 9: select chain based on drag mode\n // move: all FS+SS+FF+SF successors follow\n // resize-right: FS+FF successors (endA changes, SS/SF unaffected)\n // resize-left: SS+SF successors only (startA changes, FS/FF unaffected)\n // Phase 10: added SF\n // Phase 19: merge hierarchy chain with dependency chain\n let activeChain =\n mode === 'resize-right' ? activeDrag.cascadeChainEnd : // FS + FF\n mode === 'resize-left' ? activeDrag.cascadeChainStart : // SS + SF\n /* move */ activeDrag.cascadeChain; // FS + SS + FF + SF\n\n // Phase 19: Merge hierarchy chain with dependency chain\n // Both systems work together: unique task IDs to prevent duplicates\n if (activeDrag.hierarchyChain.length > 0) {\n const chainIds = new Set(activeChain.map(t => t.id));\n const hierarchyTasks = activeDrag.hierarchyChain.filter(t => !chainIds.has(t.id));\n activeChain = [...activeChain, ...hierarchyTasks];\n }\n\n // Track which tasks are parents in the hierarchy chain (for special positioning)\n const hierarchyParents = new Set<string>();\n activeDrag.hierarchyChain.forEach(t => {\n if (isTaskParent(t.id, allTasks)) {\n hierarchyParents.add(t.id);\n }\n });\n\n // Parent drags need full constraint-based propagation via descendants, not\n // just direct successors of the parent task itself.\n if (isParentDrag &&\n !activeDrag.disableConstraints &&\n activeDrag.onCascadeProgress) {\n const previewStartDate = new Date(Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate() + Math.round(newLeft / activeDrag.dayWidth)\n ));\n const previewDurationDays = Math.round(newWidth / activeDrag.dayWidth) - 1;\n const previewEndDate = new Date(Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate() + Math.round(newLeft / activeDrag.dayWidth) + previewDurationDays\n ));\n\n const cascadedPreviewTasks = cascadeByLinks(\n activeDrag.taskId,\n previewStartDate,\n previewEndDate,\n allTasks\n );\n\n if (cascadedPreviewTasks.length > 0) {\n const overrides = new Map<string, { left: number; width: number }>();\n\n for (const chainTask of cascadedPreviewTasks) {\n const chainStart = new Date(chainTask.startDate as string);\n const chainEnd = new Date(chainTask.endDate as string);\n const chainStartOffset = Math.round(\n (Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainEndOffset = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n\n overrides.set(chainTask.id, {\n left: Math.round(chainStartOffset * activeDrag.dayWidth),\n width: Math.round((chainEndOffset - chainStartOffset + 1) * activeDrag.dayWidth),\n });\n }\n\n activeDrag.onCascadeProgress(overrides);\n }\n // Hard mode cascade: emit position overrides for successor chain members\n } else if ((mode === 'move' || mode === 'resize-right' ||\n (mode === 'resize-left' && activeDrag.cascadeChainStart.length > 0)) &&\n !activeDrag.disableConstraints &&\n activeChain.length > 0 &&\n activeDrag.onCascadeProgress) {\n // For move/resize-left: delta from left (startA shift)\n // For resize-right: delta from width (endA shift, startA fixed)\n const deltaDays = mode === 'resize-right'\n ? Math.round((newWidth - activeDrag.initialWidth) / activeDrag.dayWidth)\n : Math.round((newLeft - activeDrag.initialLeft) / activeDrag.dayWidth);\n const overrides = new Map<string, { left: number; width: number }>();\n const draggedTaskId = activeDrag.taskId;\n const dayWidth = activeDrag.dayWidth;\n const monthStart = activeDrag.monthStart;\n\n for (const chainTask of activeChain) {\n // Phase 11: locked tasks cannot be moved by cascade\n if (chainTask.locked) continue;\n\n const chainStart = new Date(chainTask.startDate as string);\n const chainEnd = new Date(chainTask.endDate as string);\n const chainStartOffset = Math.round(\n (Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate()) -\n Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainEndOffset = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainDuration = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate())\n ) / (24 * 60 * 60 * 1000)\n );\n\n // Phase 9: Check if this chainTask has FF dependency on dragged task\n // For FF tasks, calculate position from end offset (not start offset)\n // This fixes negative lag preview where child starts before parent\n // Phase 10: SF tasks also position from end offset (endB constrained to startA)\n const hasFFDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'FF'\n );\n const hasSFDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'SF'\n );\n\n let chainLeft;\n let chainWidth;\n if (hierarchyParents.has(chainTask.id)) {\n // Phase 19 fix: Parent task in hierarchy chain - compute from all children\n // Parent position = min(children.start) to max(children.end)\n const children = getChildren(chainTask.id, allTasks);\n if (children.length > 0) {\n let minChildStart = Infinity;\n let maxChildEnd = -Infinity;\n\n children.forEach(child => {\n let childStartOffset: number;\n let childEndOffset: number;\n\n // If this child is the dragged task, use current drag position (newLeft)\n if (child.id === draggedTaskId) {\n const currentLeftInDays = Math.round(newLeft / dayWidth);\n const currentWidthInDays = Math.round(newWidth / dayWidth) - 1; // -1 for inclusive\n childStartOffset = currentLeftInDays;\n childEndOffset = currentLeftInDays + currentWidthInDays;\n } else if (activeChain.some(c => c.id === child.id)) {\n // Child is being cascaded (moved by same delta)\n const childStart = new Date(child.startDate as string);\n const childEnd = new Date(child.endDate as string);\n const origStartOffset = Math.round(\n (Date.UTC(childStart.getUTCFullYear(), childStart.getUTCMonth(), childStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const origEndOffset = Math.round(\n (Date.UTC(childEnd.getUTCFullYear(), childEnd.getUTCMonth(), childEnd.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n childStartOffset = origStartOffset + deltaDays;\n childEndOffset = origEndOffset + deltaDays;\n } else {\n // Child not being moved - use original position\n const childStart = new Date(child.startDate as string);\n const childEnd = new Date(child.endDate as string);\n childStartOffset = Math.round(\n (Date.UTC(childStart.getUTCFullYear(), childStart.getUTCMonth(), childStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n childEndOffset = Math.round(\n (Date.UTC(childEnd.getUTCFullYear(), childEnd.getUTCMonth(), childEnd.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n }\n\n minChildStart = Math.min(minChildStart, childStartOffset);\n maxChildEnd = Math.max(maxChildEnd, childEndOffset);\n });\n\n chainLeft = Math.round(minChildStart * dayWidth);\n chainWidth = Math.round((maxChildEnd - minChildStart + 1) * dayWidth);\n } else {\n // No children - use original position\n chainLeft = Math.round(chainStartOffset * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n }\n } else if (hasFFDepOnDragged || hasSFDepOnDragged) {\n // FF/SF: position based on end date shift, then back up by duration\n // This works correctly even when child starts before parent (negative lag)\n // For SF: endB shifts with startA, then back up by duration\n chainLeft = Math.round((chainEndOffset + deltaDays - chainDuration) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n } else if (activeDrag.hierarchyChain.some(h => h.id === chainTask.id)) {\n // Phase 19: Hierarchy chain - children move with parent by same delta\n // Position based on start date shift (same as FS/SS move mode)\n chainLeft = Math.round((chainStartOffset + deltaDays) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n } else {\n // FS/SS: position based on start date shift\n chainLeft = Math.round((chainStartOffset + deltaDays) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n }\n\n // SS lag floor: when A moves left, B follows but chainLeft cannot go below A's new position\n // This keeps lag >= 0 (startB >= startA) during live drag preview\n // Phase 9: Only apply floor to SS tasks, not FF (FF allows negative lag)\n // Phase 10: SF uses end-based positioning, no floor needed\n const hasSSDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'SS'\n );\n if (hasSSDepOnDragged && (mode === 'move' || mode === 'resize-left')) {\n chainLeft = Math.max(chainLeft, newLeft);\n }\n\n overrides.set(chainTask.id, { left: chainLeft, width: chainWidth });\n }\n activeDrag.onCascadeProgress(overrides);\n }\n\n // Update current values in global state for completion\n activeDrag.currentLeft = newLeft;\n activeDrag.currentWidth = newWidth;\n\n onProgress(newLeft, newWidth);\n globalRafId = null;\n });\n}\n\n/**\n * Global mouse up handler - attached once and persists across HMR\n */\nfunction handleGlobalMouseUp() {\n if (globalActiveDrag) {\n completeDrag();\n }\n}\n\n/**\n * Track whether global listeners are attached\n */\nlet globalListenersAttached = false;\n\n/**\n * Ensure global listeners are attached (idempotent)\n */\nfunction ensureGlobalListeners() {\n if (!globalListenersAttached) {\n window.addEventListener('mousemove', handleGlobalMouseMove);\n window.addEventListener('mouseup', handleGlobalMouseUp);\n globalListenersAttached = true;\n }\n}\n\n/**\n * Cleanup global listeners - called when no components are using drag\n * Note: In practice with HMR, we keep these attached for safety\n */\nfunction cleanupGlobalListeners() {\n // We keep global listeners attached to handle orphaned drags after HMR\n // They will be cleaned up when the page is refreshed\n}\n\n/**\n * Options for useTaskDrag hook\n */\nexport interface UseTaskDragOptions {\n /** Unique identifier for the task */\n taskId: string;\n /** Initial start date of the task */\n initialStartDate: Date;\n /** Initial end date of the task */\n initialEndDate: Date;\n /** Start of the visible range (e.g., month start) */\n monthStart: Date;\n /** Width of each day in pixels */\n dayWidth: number;\n /** Callback when drag operation completes */\n onDragEnd?: (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => void;\n /** Callback for drag state changes (for parent components to render guide lines) */\n onDragStateChange?: (state: {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n }) => void;\n /** Width of edge zones for resize detection (default: 12px) */\n edgeZoneWidth?: number;\n /** Array of all tasks for dependency validation */\n allTasks?: Task[];\n /** Row index of this task (for task lookup) */\n rowIndex?: number;\n /** Enable automatic scheduling of dependent tasks */\n enableAutoSchedule?: boolean;\n /** When true, dependency constraint checking is skipped during drag (default: false) */\n disableConstraints?: boolean;\n /** Callback for real-time cascade preview — called each RAF with non-dragged chain member positions */\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n /** Callback when cascade completes — receives all shifted tasks including dragged task */\n onCascade?: (tasks: Task[]) => void;\n /** When true, all drag and resize interactions are disabled for this task */\n locked?: boolean;\n}\n\n/**\n * Return value from useTaskDrag hook\n */\nexport interface UseTaskDragReturn {\n /** Whether a drag operation is in progress */\n isDragging: boolean;\n /** Current drag mode (null when not dragging) */\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n /** Current left position in pixels (updated during drag) */\n currentLeft: number;\n /** Current width in pixels (updated during drag) */\n currentWidth: number;\n /** Props to spread on the drag handle element */\n dragHandleProps: {\n onMouseDown: (e: React.MouseEvent) => void;\n style: React.CSSProperties;\n };\n}\n\n/**\n * Custom hook for managing task drag interactions\n *\n * HMR-SAFE: Uses module-level singleton to ensure drag state survives\n * React Fast Refresh. Window event listeners are attached once at module\n * level rather than per component instance.\n */\nexport const useTaskDrag = (options: UseTaskDragOptions): UseTaskDragReturn => {\n const {\n taskId,\n initialStartDate,\n initialEndDate,\n monthStart,\n dayWidth,\n onDragEnd,\n onDragStateChange,\n edgeZoneWidth = 12,\n allTasks = [],\n rowIndex,\n enableAutoSchedule = false,\n disableConstraints = false,\n onCascadeProgress,\n onCascade,\n } = options;\n\n // Track if this hook instance owns the current global drag\n const isOwnerRef = useRef<boolean>(false);\n const locked = options.locked ?? false;\n\n // Display state (triggers re-renders only when needed)\n const [isDragging, setIsDragging] = useState<boolean>(false);\n const [dragMode, setDragMode] = useState<'move' | 'resize-left' | 'resize-right' | null>(null);\n const [currentLeft, setCurrentLeft] = useState<number>(0);\n const [currentWidth, setCurrentWidth] = useState<number>(0);\n\n /**\n * Calculate initial pixel position from dates\n */\n const getInitialPosition = useCallback((): { left: number; width: number } => {\n const getUTCDayDifference = (date1: Date, date2: Date): number => {\n const ms1 = Date.UTC(\n date1.getUTCFullYear(),\n date1.getUTCMonth(),\n date1.getUTCDate()\n );\n const ms2 = Date.UTC(\n date2.getUTCFullYear(),\n date2.getUTCMonth(),\n date2.getUTCDate()\n );\n return Math.round((ms1 - ms2) / (1000 * 60 * 60 * 24));\n };\n\n const startOffset = getUTCDayDifference(initialStartDate, monthStart);\n const duration = getUTCDayDifference(initialEndDate, initialStartDate);\n\n const left = Math.round(startOffset * dayWidth);\n const width = Math.round((duration + 1) * dayWidth); // +1 to include end date\n\n return { left, width };\n }, [initialStartDate, initialEndDate, monthStart, dayWidth]);\n\n /**\n * Initialize position when dates or dayWidth changes.\n * Skipped when this instance owns an active drag to avoid overriding drag state.\n */\n useEffect(() => {\n if (isOwnerRef.current && globalActiveDrag) return;\n const { left, width } = getInitialPosition();\n setCurrentLeft(left);\n setCurrentWidth(width);\n }, [getInitialPosition]);\n\n /**\n * When monthStart changes during an active drag (e.g. a month is prepended),\n * the pixel coordinate origin shifts. Adjust globalActiveDrag so that\n * subsequent move calculations stay in the new coordinate space.\n */\n useEffect(() => {\n if (!isOwnerRef.current || !globalActiveDrag) return;\n const oldMonthStart = globalActiveDrag.monthStart;\n if (oldMonthStart === monthStart) return;\n const daysShift = Math.round(\n (Date.UTC(oldMonthStart.getUTCFullYear(), oldMonthStart.getUTCMonth(), oldMonthStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate())) /\n (1000 * 60 * 60 * 24)\n );\n const pixelShift = daysShift * dayWidth;\n globalActiveDrag.initialLeft += pixelShift;\n globalActiveDrag.currentLeft += pixelShift;\n globalActiveDrag.monthStart = monthStart;\n }, [monthStart, dayWidth]);\n\n /**\n * Handle drag progress callback from global manager\n */\n const handleProgress = useCallback((left: number, width: number) => {\n setCurrentLeft(left);\n setCurrentWidth(width);\n\n if (onDragStateChange && isOwnerRef.current) {\n const mode = globalActiveDrag?.mode || null;\n onDragStateChange({\n isDragging: true,\n dragMode: mode,\n left,\n width,\n });\n }\n }, [onDragStateChange]);\n\n /**\n * Handle drag completion from global manager\n */\n const handleComplete = useCallback((finalLeft: number, finalWidth: number) => {\n const wasOwner = isOwnerRef.current;\n isOwnerRef.current = false;\n\n // Calculate new dates from final pixel values\n const dayOffset = Math.round(finalLeft / dayWidth);\n const durationDays = Math.round(finalWidth / dayWidth) - 1; // -1 because width includes end date\n\n const newStartDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n ));\n\n const newEndDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset + durationDays\n ));\n\n // Reset local state\n setIsDragging(false);\n setDragMode(null);\n\n // Notify parent of drag end\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: false,\n dragMode: null,\n left: finalLeft,\n width: finalWidth,\n });\n }\n\n if (wasOwner) {\n if (!disableConstraints && onCascade && allTasks.length > 0) {\n // Hard mode with onCascade: compute cascade and call onCascade\n const draggedTaskData = allTasks.find(t => t.id === taskId);\n const parentDragCascade = draggedTaskData && isTaskParent(taskId, allTasks)\n ? cascadeByLinks(taskId, newStartDate, newEndDate, allTasks)\n : null;\n\n if (parentDragCascade && parentDragCascade.length > 0) {\n onCascade([\n {\n ...(draggedTaskData ?? { id: taskId, name: '', startDate: '', endDate: '' }),\n startDate: newStartDate.toISOString(),\n endDate: newEndDate.toISOString(),\n ...(draggedTaskData?.dependencies && {\n dependencies: recalculateIncomingLags(draggedTaskData, newStartDate, newEndDate, allTasks),\n }),\n },\n ...parentDragCascade,\n ]);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n\n // CHANGE C: Dual-delta logic — compute from both start and end date changes\n // Compute delta from startDate change (correct for move and resize-left)\n const origStartMs = Date.UTC(\n initialStartDate.getUTCFullYear(),\n initialStartDate.getUTCMonth(),\n initialStartDate.getUTCDate()\n );\n const newStartMs = Date.UTC(\n newStartDate.getUTCFullYear(),\n newStartDate.getUTCMonth(),\n newStartDate.getUTCDate()\n );\n const deltaFromStart = Math.round((newStartMs - origStartMs) / (24 * 60 * 60 * 1000));\n\n // Compute delta from endDate change (correct for resize-right)\n const origEndMs = Date.UTC(\n initialEndDate.getUTCFullYear(),\n initialEndDate.getUTCMonth(),\n initialEndDate.getUTCDate()\n );\n const newEndMs = Date.UTC(\n newEndDate.getUTCFullYear(),\n newEndDate.getUTCMonth(),\n newEndDate.getUTCDate()\n );\n const deltaFromEnd = Math.round((newEndMs - origEndMs) / (24 * 60 * 60 * 1000));\n\n // For resize-right: startDate unchanged, use endDate delta (FS successors follow end)\n // For move and resize-left: use startDate delta (SS and FS-move successors follow start)\n // Detect resize-right: startDate didn't change\n const deltaDays = deltaFromStart === 0 ? deltaFromEnd : deltaFromStart;\n\n // CHANGE D: Phase 8: get correct chain for completion based on what changed\n // - resize-right (deltaFromStart === 0): only endDate changed → FS successors follow end\n // - resize-left (deltaFromStart !== 0, deltaFromEnd === 0): only startDate changed →\n // SS successors follow start; FS successors are anchored to predecessor's END which\n // is unchanged, so FS successors must NOT cascade on resize-left\n // - move (deltaFromStart !== 0, deltaFromEnd !== 0): both dates shift equally →\n // both FS and SS successors follow\n //\n // FIX: For proper transitive closure in mixed link type chains (e.g., A--FS-->B--SS-->C),\n // we use getTransitiveCascadeChain which includes cascaded tasks' successors regardless of link type.\n // Phase 9: FF included in resize-right and move chains\n const isResizeLeft = deltaFromStart !== 0 && deltaFromEnd === 0;\n let chainForCompletion = deltaFromStart === 0\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'FF']) // resize-right: FS + FF\n : isResizeLeft\n ? getTransitiveCascadeChain(taskId, allTasks, ['SS', 'SF']) // resize-left: SS + SF\n : getTransitiveCascadeChain(taskId, allTasks, ['FS', 'SS', 'FF', 'SF']); // move: all types\n\n // Phase 19: Merge hierarchy chain with dependency chain\n const currentTask = allTasks.find(t => t.id === taskId);\n if (currentTask && (currentTask as any).parentId) {\n // This is a child task - check if parent is being dragged\n // (Hierarchy chain is built when dragging starts, in handleMouseDown)\n }\n // Add hierarchy chain if this is a parent drag\n const hierarchyChildren = currentTask ? getChildren(taskId, allTasks) : [];\n if (hierarchyChildren.length > 0) {\n const chainIds = new Set(chainForCompletion.map(t => t.id));\n const uniqueHierarchyChildren = hierarchyChildren.filter(t => !chainIds.has(t.id));\n chainForCompletion = [...chainForCompletion, ...uniqueHierarchyChildren];\n }\n\n if (chainForCompletion.length > 0) {\n const cascadedTasks: Task[] = [\n {\n ...(draggedTaskData ?? { id: taskId, name: '', startDate: '', endDate: '' }),\n startDate: newStartDate.toISOString(),\n endDate: newEndDate.toISOString(),\n ...(draggedTaskData?.dependencies && {\n dependencies: recalculateIncomingLags(draggedTaskData, newStartDate, newEndDate, allTasks),\n }),\n },\n ...chainForCompletion\n .filter(chainTask => !chainTask.locked) // Phase 11: skip locked tasks in cascade\n .map(chainTask => {\n const origStart = new Date(chainTask.startDate as string);\n const origEnd = new Date(chainTask.endDate as string);\n const newStart = new Date(Date.UTC(\n origStart.getUTCFullYear(), origStart.getUTCMonth(), origStart.getUTCDate() + deltaDays\n ));\n const newEnd = new Date(Date.UTC(\n origEnd.getUTCFullYear(), origEnd.getUTCMonth(), origEnd.getUTCDate() + deltaDays\n ));\n return { ...chainTask, startDate: newStart.toISOString(), endDate: newEnd.toISOString() };\n }),\n ];\n onCascade(cascadedTasks);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n }\n\n // Soft mode OR hard mode with no FS successors: call onDragEnd\n // Always recalculate lag so hard-mode drags (chain.length===0) also persist the new lag\n if (allTasks.length > 0 && onDragEnd) {\n const currentTaskData = allTasks.find(t => t.id === taskId);\n const updatedDependencies = currentTaskData?.dependencies\n ? recalculateIncomingLags(currentTaskData, newStartDate, newEndDate, allTasks)\n : undefined;\n onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate, updatedDependencies });\n } else if (onDragEnd) {\n onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate });\n }\n }\n }, [dayWidth, monthStart, onDragEnd, onDragStateChange, taskId, disableConstraints, onCascade, allTasks, initialStartDate, initialEndDate]);\n\n /**\n * Handle drag cancellation (e.g., if HMR orphaned the drag)\n */\n const handleCancel = useCallback(() => {\n isOwnerRef.current = false;\n setIsDragging(false);\n setDragMode(null);\n\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: false,\n dragMode: null,\n left: currentLeft,\n width: currentWidth,\n });\n }\n }, [onDragStateChange, currentLeft, currentWidth]);\n\n /**\n * Cleanup on unmount - if this instance owns the drag, cancel it\n */\n useEffect(() => {\n return () => {\n if (isOwnerRef.current && globalActiveDrag) {\n // We're unmounting while owning the drag - cancel it\n cancelDrag();\n }\n };\n }, []);\n\n /**\n * Handle mouse down on drag handle\n */\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n // Phase 11: locked tasks cannot be dragged or resized\n if (locked) return;\n\n const target = e.currentTarget as HTMLElement;\n const edgeZone = detectEdgeZone(e.clientX, target, edgeZoneWidth);\n\n // Determine drag mode from edge zone\n let mode: 'move' | 'resize-left' | 'resize-right' | null = null;\n switch (edgeZone) {\n case 'left':\n mode = 'resize-left';\n break;\n case 'right':\n mode = 'resize-right';\n break;\n case 'move':\n mode = 'move';\n break;\n }\n\n // Phase 19: Parent tasks cannot be resized - their dates are computed from children\n // Force move mode for parent tasks to prevent resize operations\n if (mode === 'resize-left' || mode === 'resize-right') {\n const currentTask = allTasks.find(t => t.id === taskId);\n if (currentTask && isTaskParent(taskId, allTasks)) {\n mode = 'move';\n }\n }\n\n if (!mode) {\n return;\n }\n\n // Get current position from state (this is what we see on screen)\n const initialLeft = currentLeft;\n const initialWidth = currentWidth;\n\n // Mark this instance as the drag owner\n isOwnerRef.current = true;\n\n // Update display state\n setIsDragging(true);\n setDragMode(mode);\n\n // Notify parent of drag start\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: true,\n dragMode: mode,\n left: initialLeft,\n width: initialWidth,\n });\n }\n\n // Ensure global listeners are attached (idempotent)\n ensureGlobalListeners();\n\n // Phase 19: Build hierarchy chain for real-time parent movement\n // When dragging a child: include parent so it moves with children\n // When dragging a parent: include all children so they move with parent\n const currentTask = allTasks.find(t => t.id === taskId);\n let hierarchyChain: Task[] = [];\n\n if (currentTask) {\n const taskParentId = (currentTask as any).parentId;\n if (taskParentId) {\n // Dragging a child - include parent for real-time updates\n const parentTask = allTasks.find(t => t.id === taskParentId);\n if (parentTask) {\n hierarchyChain.push(parentTask);\n }\n } else {\n // Dragging a parent - include all children\n hierarchyChain = getChildren(taskId, allTasks);\n }\n }\n\n // Store drag state in global singleton\n globalActiveDrag = {\n taskId,\n mode,\n startX: e.clientX,\n initialLeft,\n initialWidth,\n currentLeft: initialLeft, // Initially same as initial\n currentWidth: initialWidth, // Initially same as initial\n dayWidth,\n monthStart,\n onProgress: handleProgress,\n onComplete: handleComplete,\n onCancel: handleCancel,\n allTasks,\n disableConstraints,\n cascadeChain: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'SS', 'FF', 'SF']) // all successors, used for move (Phase 10: added SF)\n : [],\n cascadeChainFS: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS']) // FS + transitive, used for resize-right\n : [],\n cascadeChainStart: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['SS', 'SF']) // SS + SF for resize-left cascade (Phase 10: renamed from cascadeChainSS)\n : [],\n cascadeChainEnd: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'FF']) // FS + FF for resize-right cascade (Phase 9)\n : [],\n hierarchyChain, // Phase 19: children of parent task\n onCascadeProgress,\n };\n }, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade, locked]);\n\n /**\n * Get cursor style based on current position\n */\n const getCursorStyle = useCallback((): string => {\n if (locked) return 'not-allowed';\n if (isDragging) {\n return 'grabbing';\n }\n return 'grab';\n }, [locked, isDragging]);\n\n return {\n isDragging,\n dragMode,\n currentLeft,\n currentWidth,\n dragHandleProps: {\n onMouseDown: handleMouseDown,\n style: {\n cursor: getCursorStyle(),\n userSelect: 'none',\n } as React.CSSProperties,\n },\n };\n};\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { getDayOffset } from '../../utils/dateUtils';\nimport './TodayIndicator.css';\n\nexport interface TodayIndicatorProps {\n /** Start of the month for positioning calculations */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n}\n\n/**\n * TodayIndicator component - displays a vertical line at the current date\n *\n * Only renders when the current date is within the visible month range.\n * Satisfies REND-04 requirement for visual today indicator.\n */\nconst TodayIndicator: React.FC<TodayIndicatorProps> = ({ monthStart, dayWidth }) => {\n // Use local date for \"today\" (not UTC) - user's current date matters\n const today = new Date();\n const todayLocal = new Date(Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate()\n ));\n\n // Calculate position based on offset from monthStart\n // The parent GanttChart component handles the date range check via todayInRange\n const position = useMemo(() => {\n const offset = getDayOffset(todayLocal, monthStart);\n return Math.round(offset * dayWidth);\n }, [monthStart, dayWidth, todayLocal]);\n\n // Allow negative positions (today before monthStart) - parent handles visibility\n if (isNaN(position)) {\n return null;\n }\n\n return (\n <div\n className=\"gantt-ti-indicator\"\n style={{\n left: `${position}px`,\n width: 'var(--gantt-today-indicator-width)',\n backgroundColor: 'var(--gantt-today-indicator-color)',\n }}\n aria-label=\"Today\"\n />\n );\n};\n\nexport default TodayIndicator;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { calculateGridLines, calculateWeekendBlocks } from '../../utils/geometry';\nimport type { GridLine } from '../../types';\nimport './GridBackground.css';\n\nexport interface GridBackgroundProps {\n /** Array of dates to display (from getMultiMonthDays) */\n dateRange: Date[];\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Total height of the grid area in pixels */\n totalHeight: number;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Re-renders when dateRange length, dayWidth, or totalHeight change.\n * Returns true (skip re-render) only when all three are unchanged.\n */\nconst arePropsEqual = (prevProps: GridBackgroundProps, nextProps: GridBackgroundProps) => {\n return (\n prevProps.dayWidth === nextProps.dayWidth &&\n prevProps.dateRange.length === nextProps.dateRange.length &&\n prevProps.totalHeight === nextProps.totalHeight // skip re-render only when totalHeight unchanged\n );\n};\n\n/**\n * GridBackground component - renders vertical grid lines and weekend background highlighting\n *\n * This component provides the visual grid structure that runs behind task rows.\n * It separates grid rendering from task rendering for better performance and cleaner code.\n *\n * Features:\n * - Vertical grid lines at month/week/day boundaries\n * - Pink background highlighting for weekend days\n * - React.memo optimization for performance\n * - Pointer events disabled (clicks pass through to tasks)\n */\nconst GridBackground: React.FC<GridBackgroundProps> = React.memo(\n ({ dateRange, dayWidth, totalHeight }) => {\n // Calculate grid line positions\n const gridLines = useMemo<GridLine[]>(() => {\n return calculateGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth]);\n\n // Calculate weekend background blocks\n const weekendBlocks = useMemo(() => {\n return calculateWeekendBlocks(dateRange, dayWidth);\n }, [dateRange, dayWidth]);\n\n // Calculate total grid width\n const gridWidth = useMemo(() => {\n return Math.round(dateRange.length * dayWidth);\n }, [dateRange.length, dayWidth]);\n\n return (\n <div\n className=\"gantt-gb-gridBackground\"\n style={{\n width: `${gridWidth}px`,\n height: `${totalHeight}px`,\n }}\n >\n {/* Weekend backgrounds (rendered first, behind lines) */}\n {weekendBlocks.map((block, index) => (\n <div\n key={`weekend-${index}`}\n className=\"gantt-gb-weekendBlock\"\n style={{\n left: `${block.left}px`,\n width: `${block.width}px`,\n }}\n />\n ))}\n\n {/* Vertical grid lines */}\n {gridLines.map((line, index) => {\n // Determine line type class based on flags\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : line.isWeekStart\n ? 'gantt-gb-weekSeparator'\n : 'gantt-gb-dayLine';\n\n return (\n <div\n key={`gridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{\n left: `${line.x}px`,\n }}\n />\n );\n })}\n </div>\n );\n },\n arePropsEqual\n);\n\nGridBackground.displayName = 'GridBackground';\n\nexport default GridBackground;\n","'use client';\n\nimport React from 'react';\nimport './DragGuideLines.css';\n\nexport interface DragGuideLinesProps {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n totalHeight: number;\n}\n\nconst DragGuideLines: React.FC<DragGuideLinesProps> = ({\n isDragging,\n dragMode,\n left,\n width,\n totalHeight,\n}) => {\n if (!isDragging || !dragMode) {\n return null;\n }\n\n // Determine which lines to show based on drag mode\n const showLeftLine = dragMode === 'move' || dragMode === 'resize-left';\n const showRightLine = dragMode === 'move' || dragMode === 'resize-right';\n\n return (\n <>\n {showLeftLine && (\n <div\n className=\"gantt-dgl-guideLine\"\n style={{\n left: `${left}px`,\n height: `${totalHeight}px`,\n }}\n />\n )}\n {showRightLine && (\n <div\n className=\"gantt-dgl-guideLine\"\n style={{\n left: `${left + width}px`,\n height: `${totalHeight}px`,\n }}\n />\n )}\n </>\n );\n};\n\nexport default DragGuideLines;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { Task } from '../../types';\nimport { calculateTaskBar, calculateDependencyPath, pixelsToDate } from '../../utils/geometry';\nimport { getAllDependencyEdges, detectCycles, computeLagFromDates } from '../../utils/dependencyUtils';\nimport type { LinkType } from '../../types';\nimport './DependencyLines.css';\n\n/**\n * Calculate effective lag based on current task pixel positions.\n * Delegates to computeLagFromDates for consistent semantics.\n */\nfunction calculateEffectiveLag(\n edge: { type: string },\n predPosition: { left: number; right: number },\n succPosition: { left: number; right: number },\n monthStart: Date,\n dayWidth: number\n): number {\n const predStart = pixelsToDate(predPosition.left, monthStart, dayWidth);\n const predEnd = pixelsToDate(predPosition.right - dayWidth, monthStart, dayWidth);\n const succStart = pixelsToDate(succPosition.left, monthStart, dayWidth);\n const succEnd = pixelsToDate(succPosition.right - dayWidth, monthStart, dayWidth);\n return computeLagFromDates(edge.type as LinkType, predStart, predEnd, succStart, succEnd);\n}\n\n/**\n * Check if a task is hidden inside a collapsed parent.\n */\nfunction isTaskHidden(taskId: string, collapsedParentIds: Set<string>, taskMap: Map<string, Task>): boolean {\n const task = taskMap.get(taskId);\n if (!task || !task.parentId) return false;\n return collapsedParentIds.has(task.parentId);\n}\n\n/**\n * Find the nearest visible ancestor of a hidden task.\n * Returns the ancestor task or null if the task is visible.\n */\nfunction findVisibleAncestor(\n task: Task,\n collapsedParentIds: Set<string>,\n taskMap: Map<string, Task>\n): Task | null {\n if (!task.parentId) return null;\n if (collapsedParentIds.has(task.parentId)) {\n const parent = taskMap.get(task.parentId);\n if (!parent) return null;\n // Check if parent is also hidden\n if (parent.parentId && collapsedParentIds.has(parent.parentId)) {\n return findVisibleAncestor(parent, collapsedParentIds, taskMap);\n }\n return parent;\n }\n return null;\n}\n\n/**\n * Check if two tasks share the same collapsed parent ancestor.\n * If both predecessor and successor are hidden inside the same parent,\n * the dependency line should NOT be rendered (it's internal to the collapsed group).\n */\nfunction areBothHiddenInSameParent(\n predecessorId: string,\n successorId: string,\n collapsedParentIds: Set<string>,\n taskMap: Map<string, Task>\n): boolean {\n const predTask = taskMap.get(predecessorId);\n const succTask = taskMap.get(successorId);\n\n if (!predTask || !succTask) return false;\n\n // Both must have parentIds\n if (!predTask.parentId || !succTask.parentId) return false;\n\n // Find the visible ancestor (collapsed parent) for each\n const predVisibleAncestor = findVisibleAncestor(predTask, collapsedParentIds, taskMap);\n const succVisibleAncestor = findVisibleAncestor(succTask, collapsedParentIds, taskMap);\n\n // Both must be hidden (have visible ancestors)\n if (!predVisibleAncestor || !succVisibleAncestor) return false;\n\n // Check if they share the same collapsed parent\n return predVisibleAncestor.id === succVisibleAncestor.id;\n}\n\nexport interface DependencyLinesProps {\n /** Visible tasks only (for row calculation) */\n tasks: Task[];\n /** All tasks including hidden children (for virtual position calculation) */\n allTasks?: Task[];\n /** Set of collapsed parent IDs */\n collapsedParentIds?: Set<string>;\n /** Start of the visible range (e.g., month start) */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of each task row in pixels */\n rowHeight: number;\n /** Total width of the grid in pixels */\n gridWidth: number;\n /** Real-time pixel overrides for task positions during drag (taskId -> {left, width}) */\n dragOverrides?: Map<string, { left: number; width: number }>;\n /** Currently selected dep chip — highlights the matching arrow in red */\n selectedDep?: { predecessorId: string; successorId: string; linkType: string } | null;\n}\n\n/**\n * SVG overlay component rendering dependency lines as orthogonal paths with rounded corners\n *\n * Lines connect from the right edge of predecessor tasks to the left edge\n * of successor tasks using horizontal/vertical lines with arc rounded corners.\n * Circular dependencies are highlighted in red.\n *\n * Virtual dependency links: When a task is hidden inside a collapsed parent,\n * its dependency lines render at \"virtual positions\" using the parent's row.\n * These virtual lines are styled with dashed strokes to indicate the hidden status.\n *\n * Performance: Uses React.memo to prevent re-renders when dependencies haven't changed.\n */\nexport const DependencyLines: React.FC<DependencyLinesProps> = React.memo(({\n tasks,\n allTasks,\n collapsedParentIds = new Set(),\n monthStart,\n dayWidth,\n rowHeight,\n gridWidth,\n dragOverrides,\n selectedDep,\n}) => {\n // Use allTasks for virtual position calculation if provided, otherwise use tasks\n const tasksForPositions = allTasks ?? tasks;\n\n // Create a lookup map for task positions and their indices\n const { taskPositions, taskIndices, hiddenTaskIds } = useMemo(() => {\n const positions = new Map<string, { left: number; right: number; rowTop: number; isVirtual: boolean }>();\n const indices = new Map<string, number>();\n const hidden = new Set<string>();\n const taskMap = new Map(tasksForPositions.map(t => [t.id, t]));\n const visibleTaskMap = new Map(tasks.map(t => [t.id, t]));\n\n // First pass: Calculate positions for visible tasks (existing logic)\n tasks.forEach((task, index) => {\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n\n // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const resolvedLeft = override?.left ?? computed.left;\n const resolvedWidth = override?.width ?? computed.width;\n\n indices.set(task.id, index);\n positions.set(task.id, {\n left: resolvedLeft,\n right: resolvedLeft + resolvedWidth,\n rowTop: index * rowHeight,\n isVirtual: false,\n });\n });\n\n // Second pass: Calculate virtual positions for hidden tasks\n if (allTasks && collapsedParentIds.size > 0) {\n for (const task of allTasks) {\n // Skip if already processed (visible task)\n if (positions.has(task.id)) continue;\n\n // Check if task is hidden inside a collapsed parent\n if (!isTaskHidden(task.id, collapsedParentIds, taskMap)) continue;\n\n hidden.add(task.id);\n\n // Find the visible ancestor (collapsed parent)\n const visibleAncestor = findVisibleAncestor(task, collapsedParentIds, taskMap);\n if (!visibleAncestor) continue;\n\n // Get the ancestor's row position\n const ancestorPosition = positions.get(visibleAncestor.id);\n if (!ancestorPosition) continue;\n\n // Calculate horizontal position from task's dates\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n\n // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const resolvedLeft = override?.left ?? computed.left;\n const resolvedWidth = override?.width ?? computed.width;\n\n // Store virtual position using ancestor's rowTop\n positions.set(task.id, {\n left: resolvedLeft,\n right: resolvedLeft + resolvedWidth,\n rowTop: ancestorPosition.rowTop,\n isVirtual: true,\n });\n }\n }\n\n return { taskPositions: positions, taskIndices: indices, hiddenTaskIds: hidden };\n }, [tasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, dragOverrides]);\n\n // Detect cycles for highlighting (use allTasks for accurate cycle detection)\n const cycleInfo = useMemo(() => {\n const tasksForCycleDetection = allTasks ?? tasks;\n const result = detectCycles(tasksForCycleDetection);\n const cycleTaskIds = new Set(result.cyclePath || []);\n return cycleTaskIds;\n }, [tasks, allTasks]);\n\n // Calculate all dependency line paths (use allTasks if available)\n const lines = useMemo(() => {\n const tasksForEdges = allTasks ?? tasks;\n const edges = getAllDependencyEdges(tasksForEdges);\n const lines: Array<{\n id: string;\n path: string;\n hasCycle: boolean;\n lag: number;\n fromX: number;\n toX: number;\n fromY: number;\n reverseOrder: boolean;\n isVirtual: boolean;\n }> = [];\n\n for (const edge of edges) {\n const predecessor = taskPositions.get(edge.predecessorId);\n const successor = taskPositions.get(edge.successorId);\n const predecessorIndex = taskIndices.get(edge.predecessorId);\n const successorIndex = taskIndices.get(edge.successorId);\n\n if (!predecessor || !successor) {\n continue; // Skip if task not found (shouldn't happen with validation)\n }\n\n // Check if both tasks are hidden inside the same collapsed parent\n // If so, skip rendering this line (it's internal to the collapsed group)\n if (allTasks && collapsedParentIds.size > 0) {\n const taskMap = new Map(allTasks.map(t => [t.id, t]));\n if (areBothHiddenInSameParent(edge.predecessorId, edge.successorId, collapsedParentIds, taskMap)) {\n continue;\n }\n }\n\n // Check if either endpoint is virtual (hidden task)\n const isVirtual = predecessor.isVirtual || successor.isVirtual;\n\n // Determine if tasks are in reverse order (predecessor appears below successor)\n // For virtual tasks, use the predecessor's rowTop for comparison\n let reverseOrder = false;\n if (predecessorIndex !== undefined && successorIndex !== undefined) {\n reverseOrder = predecessorIndex > successorIndex;\n } else {\n // One or both are virtual - use rowTop for comparison\n reverseOrder = predecessor.rowTop > successor.rowTop;\n }\n\n // Calculate direction-specific Y coordinates\n let fromY: number;\n let toY: number;\n\n if (reverseOrder) {\n // Arrow goes UP: exit from top of parent bar, enter at bottom of child bar\n fromY = predecessor.rowTop + 10; // 8px from top of parent bar\n toY = successor.rowTop + rowHeight - 6; // 8px from bottom of child bar\n } else {\n // Arrow goes DOWN: exit from bottom of parent bar, enter at top of child bar\n fromY = predecessor.rowTop + rowHeight - 10; // 8px from bottom of parent bar\n toY = successor.rowTop + 6; // 8px from top of child bar\n }\n\n // Determine connection points based on link type:\n // FS: right → left\n // SS: left → left\n // FF: right → right\n // SF: left → right\n const fromX = (edge.type === 'SS' || edge.type === 'SF')\n ? predecessor.left\n : predecessor.right;\n\n const toX = (edge.type === 'FF' || edge.type === 'SF')\n ? successor.right\n : successor.left;\n\n const arrivesFromRight = edge.type === 'FF' || edge.type === 'SF';\n\n const from = { x: fromX, y: fromY };\n const to = { x: toX, y: toY };\n\n const path = calculateDependencyPath(from, to, arrivesFromRight);\n\n // Check if this edge is part of a cycle\n const hasCycle = cycleInfo.has(edge.predecessorId) || cycleInfo.has(edge.successorId);\n\n // Calculate effective lag from actual positions (always, not just during drag)\n const lag = calculateEffectiveLag(edge, predecessor, successor, monthStart, dayWidth);\n\n lines.push({\n id: `${edge.predecessorId}-${edge.successorId}-${edge.type}`,\n path,\n hasCycle,\n lag,\n fromX,\n toX,\n fromY,\n reverseOrder,\n isVirtual,\n });\n }\n\n return lines;\n }, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, monthStart, dayWidth, dragOverrides]);\n\n // Calculate SVG height based on visible tasks (not all tasks)\n const svgHeight = tasks.length * rowHeight;\n\n return (\n <svg\n className=\"gantt-dependencies-svg\"\n width={gridWidth}\n height={svgHeight}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n {/* Arrow marker for dependency lines */}\n <marker\n id=\"arrowhead\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"var(--gantt-dependency-line-color, #666666)\"\n />\n </marker>\n\n {/* Red arrow marker for circular dependencies */}\n <marker\n id=\"arrowhead-cycle\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"var(--gantt-dependency-cycle-color, #ef4444)\"\n />\n </marker>\n\n {/* Red arrow marker for selected dependency */}\n <marker\n id=\"arrowhead-selected\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"#ef4444\"\n />\n </marker>\n </defs>\n\n {lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual }) => {\n const isSelected =\n selectedDep != null &&\n id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;\n\n let pathClassName = 'gantt-dependency-path';\n if (isSelected) pathClassName += ' gantt-dependency-selected';\n else if (hasCycle) pathClassName += ' gantt-dependency-cycle';\n if (isVirtual && !isSelected) pathClassName += ' gantt-dependency-virtual';\n\n let markerEnd: string;\n if (isSelected) markerEnd = 'url(#arrowhead-selected)';\n else if (hasCycle) markerEnd = 'url(#arrowhead-cycle)';\n else markerEnd = 'url(#arrowhead)';\n\n const lagColor = isSelected\n ? '#ef4444'\n : hasCycle\n ? 'var(--gantt-dependency-cycle-color, #ef4444)'\n : 'var(--gantt-dependency-line-color, #666666)';\n\n return (\n <React.Fragment key={id}>\n <path\n d={path}\n className={pathClassName}\n markerEnd={markerEnd}\n />\n {lag !== 0 && (\n <text\n className=\"gantt-dependency-lag-label\"\n x={lag < 0 ? toX + 14 : toX - 14}\n y={reverseOrder ? fromY - 4 : fromY + 12}\n textAnchor=\"middle\"\n fontSize=\"10\"\n fill={lagColor}\n >\n {lag > 0 ? `+${lag}` : `${lag}`}\n </text>\n )}\n </React.Fragment>\n );\n })}\n </svg>\n );\n});\n\nDependencyLines.displayName = 'DependencyLines';\n\nexport default DependencyLines;\n","'use client';\n\nimport React, { useMemo, useCallback, useState, useEffect, useRef } from 'react';\nimport type { Task, TaskDependency } from '../GanttChart';\nimport type { LinkType } from '../../types';\nimport { validateDependencies, calculateSuccessorDate, isTaskParent } from '../../utils/dependencyUtils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/Popover';\nimport { TaskListRow } from './TaskListRow';\nimport { NewTaskRow } from './NewTaskRow';\nimport { LINK_TYPE_ICONS, LINK_TYPE_LABELS } from './DepIcons';\nimport './TaskList.css';\n\nexport { LINK_TYPE_ICONS };\n\nconst LINK_TYPE_ORDER: LinkType[] = ['FS', 'SS', 'FF', 'SF'];\n\nexport interface TaskListProps {\n /** Array of tasks to display */\n tasks: Task[];\n /** Height of each row in pixels (must match Gantt chart's rowHeight) */\n rowHeight: number;\n /** Height of the header row in pixels (must match Gantt chart's headerHeight) */\n headerHeight: number;\n /** Width of the task list overlay in pixels (default: 400) */\n taskListWidth?: number;\n /** Callback when task is modified via inline edit */\n onTaskChange?: (task: Task) => void;\n /** ID of currently selected task */\n selectedTaskId?: string;\n /** Callback when task row is clicked */\n onTaskSelect?: (taskId: string | null) => void;\n /** Show or hide the task list (default: true) */\n show?: boolean;\n /** Disable task name editing in the task list (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing (hides +, ×, and type menu; read-only column) (default: false) */\n disableDependencyEditing?: boolean;\n /** Callback to scroll the chart grid to a task (wired to № cell click) */\n onScrollToTask?: (taskId: string) => void;\n /** Callback when selected chip changes (used by GanttChart to highlight the corresponding arrow) */\n onSelectedChipChange?: (chip: { successorId: string; predecessorId: string; linkType: string } | null) => void;\n /** Callback when a new task is added (called with full Task object including generated id) */\n onAdd?: (task: Task) => void;\n /** Callback when a task is deleted (called with taskId) */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted after a specific task */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void;\n /** ID of task that should enter edit mode on mount (for auto-edit after insert) */\n editingTaskId?: string | null;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n /** Set of collapsed parent task IDs */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked */\n onToggleCollapse?: (parentId: string) => void;\n /** Callback when task is promoted (parentId removed) */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when task is demoted (parentId set to previous task) */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n}\n\n/**\n * TaskList component - displays tasks in a table format as an overlay\n *\n * Renders a table with columns: № (number), Name, Start Date, End Date, Dependencies\n * Uses position: sticky for synchronized vertical scrolling with the chart.\n */\nexport const TaskList: React.FC<TaskListProps> = ({\n tasks,\n rowHeight,\n headerHeight,\n taskListWidth = 542,\n onTaskChange,\n selectedTaskId,\n onTaskSelect,\n show = true,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n onScrollToTask,\n onSelectedChipChange,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n editingTaskId: propEditingTaskId,\n enableAddTask = true,\n collapsedParentIds: externalCollapsedParentIds,\n onToggleCollapse: externalOnToggleCollapse,\n onPromoteTask,\n onDemoteTask,\n}) => {\n // Hierarchy state: collapsed parent IDs (uncontrolled mode - internal state)\n const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState<Set<string>>(new Set());\n\n // Use external collapsedParentIds if provided (controlled mode), otherwise use internal state\n const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;\n\n // Use external onToggleCollapse if provided (controlled mode), otherwise use internal handler\n const handleToggleCollapse = externalOnToggleCollapse ?? useCallback((parentId: string) => {\n setInternalCollapsedParentIds(prev => {\n const next = new Set(prev);\n if (next.has(parentId)) {\n next.delete(parentId);\n } else {\n next.add(parentId);\n }\n return next;\n });\n }, []);\n\n // Filter tasks to hide children of collapsed parents\n const visibleTasks = useMemo(() => {\n return tasks.filter(task => {\n // Root-level tasks (no parentId) are always visible\n if (!task.parentId) return true;\n // Child tasks are visible only if their parent is not collapsed\n const parentCollapsed = collapsedParentIds.has(task.parentId);\n return !parentCollapsed;\n });\n }, [tasks, collapsedParentIds]);\n\n const totalHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.length, rowHeight]\n );\n\n const handleRowClick = useCallback((taskId: string) => {\n onTaskSelect?.(taskId);\n }, [onTaskSelect]);\n\n // Dependency state\n const [activeLinkType, setActiveLinkType] = useState<LinkType>('FS');\n const [selectingPredecessorFor, setSelectingPredecessorFor] = useState<string | null>(null);\n const [typeMenuOpen, setTypeMenuOpen] = useState(false);\n const [cycleError, setCycleError] = useState(false);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n // Selected chip state: clicking a chip on a successor row selects it,\n // causing the predecessor row to show a \"Удалить\" button\n const [selectedChip, setSelectedChip] = useState<{\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null>(null);\n\n const handleChipSelect = useCallback((chip: {\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null) => {\n setSelectedChip(chip);\n onSelectedChipChange?.(chip);\n }, [onSelectedChipChange]);\n\n // Escape / outside-click cancel for picker mode and chip selection\n useEffect(() => {\n if (!selectingPredecessorFor && !selectedChip) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n }\n };\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as Element;\n if (overlayRef.current?.contains(target)) return;\n // Don't clear when clicking inside a floating portal (popover, date picker, etc.)\n if (target.closest?.('.gantt-popover')) return;\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n };\n document.addEventListener('keydown', handleKeyDown);\n document.addEventListener('mousedown', handleMouseDown, true);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleMouseDown, true);\n };\n }, [selectingPredecessorFor, selectedChip, onSelectedChipChange]);\n\n const handleAddDependency = useCallback((\n successorTaskId: string,\n predecessorTaskId: string,\n linkType: LinkType\n ) => {\n // Guard: no self-links\n if (successorTaskId === predecessorTaskId) return;\n\n // Guard: no duplicate (same taskId + type)\n const successor = tasks.find(t => t.id === successorTaskId);\n if (!successor) return;\n const alreadyExists = (successor.dependencies ?? []).some(\n d => d.taskId === predecessorTaskId && d.type === linkType\n );\n if (alreadyExists) {\n setSelectingPredecessorFor(null);\n return;\n }\n\n // Build hypothetical tasks array to validate for cycles\n const newDep: TaskDependency = { taskId: predecessorTaskId, type: linkType, lag: 0 };\n const hypothetical = tasks.map(t =>\n t.id === successorTaskId\n ? { ...t, dependencies: [...(t.dependencies ?? []), newDep] }\n : t\n );\n const validation = validateDependencies(hypothetical);\n if (!validation.isValid) {\n setCycleError(true);\n setTimeout(() => setCycleError(false), 3000);\n return;\n }\n\n const updatedTask = hypothetical.find(t => t.id === successorTaskId)!;\n\n // Snap successor dates to the predecessor position (lag=0)\n const predecessor = tasks.find(t => t.id === predecessorTaskId);\n if (predecessor) {\n const predStart = new Date(predecessor.startDate as string);\n const predEnd = new Date(predecessor.endDate as string);\n const constraintDate = calculateSuccessorDate(predStart, predEnd, linkType, 0);\n\n const origSuccessor = tasks.find(t => t.id === successorTaskId)!;\n const durationMs =\n new Date(origSuccessor.endDate as string).getTime() -\n new Date(origSuccessor.startDate as string).getTime();\n\n let newStart: Date;\n let newEnd: Date;\n\n if (linkType === 'FS' || linkType === 'SS') {\n newStart = constraintDate;\n newEnd = new Date(constraintDate.getTime() + durationMs);\n } else {\n newEnd = constraintDate;\n newStart = new Date(constraintDate.getTime() - durationMs);\n }\n\n const snappedTask: Task = {\n ...updatedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n };\n onTaskChange?.(snappedTask);\n } else {\n // Predecessor not found — emit without snap (graceful fallback)\n onTaskChange?.(updatedTask);\n }\n\n setSelectingPredecessorFor(null);\n }, [tasks, onTaskChange]);\n\n const handleRemoveDependency = useCallback((\n taskId: string,\n predecessorTaskId: string,\n linkType: LinkType\n ) => {\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n const updatedDeps = (task.dependencies ?? []).filter(\n d => !(d.taskId === predecessorTaskId && d.type === linkType)\n );\n onTaskChange?.({ ...task, dependencies: updatedDeps });\n }, [tasks, onTaskChange]);\n\n // New task creation state\n const [isCreating, setIsCreating] = useState(false);\n\n // Drag-to-reorder state\n const [draggingIndex, setDraggingIndex] = useState<number | null>(null);\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);\n const dragOriginIndexRef = useRef<number | null>(null);\n\n const handleDragStart = useCallback((index: number, e: React.DragEvent) => {\n e.dataTransfer.effectAllowed = 'move';\n setDraggingIndex(index);\n dragOriginIndexRef.current = index;\n }, []);\n\n const handleDragOver = useCallback((index: number, e: React.DragEvent) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(index);\n }, []);\n\n const handleDrop = useCallback((dropIndex: number, e: React.DragEvent) => {\n e.preventDefault();\n const originIndex = dragOriginIndexRef.current;\n // No-op: same position (line is already where the row is)\n if (originIndex === null || originIndex === dropIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n return;\n }\n const reordered = [...tasks];\n const [moved] = reordered.splice(originIndex, 1);\n\n // Blue line appears ABOVE row at dropIndex\n // So dropIndex=0 means insert at 0 (before first row)\n // dropIndex=1 means insert at 1 (between row 0 and row 1)\n // dropIndex=tasks.length means insert at the end (after last row)\n // When dragging down (originIndex < dropIndex), after splice the indices shift by 1\n // So we need to insert at dropIndex - 1\n const insertIndex = dropIndex === tasks.length\n ? tasks.length - 1 // After last means position at last\n : originIndex < dropIndex ? dropIndex - 1 : dropIndex;\n\n // ============================================\n // COMPREHENSIVE LOGGING - START\n // ============================================\n const isChild = !!moved.parentId;\n const isParent = tasks.some(t => t.parentId === moved.id);\n const taskType = isParent ? 'PARENT' : (isChild ? 'CHILD' : 'ROOT');\n\n console.log('=== DRAG & DROP START ===');\n console.log('[MOVED TASK]', {\n id: moved.id,\n name: moved.name,\n type: taskType,\n parentId: moved.parentId,\n originIndex: originIndex,\n dropIndex: dropIndex,\n insertIndex: insertIndex,\n direction: originIndex < dropIndex ? 'DOWN' : 'UP'\n });\n console.log('[TASKS ARRAY LENGTH]', tasks.length);\n // ============================================\n\n // parentId inference: determine if task should be in a group\n // IMPORTANT: Calculate this BEFORE splicing moved task back into reordered\n // because we need to find the parent's position in the array WITHOUT the moved task\n let inferredParentId: string | undefined;\n\n if (moved.parentId) {\n // Task is currently a child - check if it's staying in or leaving its group\n // Find parent position in the array WITHOUT the moved task (reordered after first splice)\n const parentIndex = reordered.findIndex(t => t.id === moved.parentId);\n\n console.log('[CHILD TASK - CHECKING GROUP POSITION]', {\n currentParentId: moved.parentId,\n parentIndex: parentIndex,\n parentFound: parentIndex !== -1\n });\n\n if (parentIndex === -1) {\n // Parent not found - should not happen, but handle gracefully\n console.log('[PARENT NOT FOUND] - Setting parentId to undefined');\n inferredParentId = undefined;\n } else {\n // Calculate where the moved task will end up AFTER we splice it in\n // The key question: is insertIndex outside the range [parentIndex, parentIndex + numSiblings]?\n const numSiblings = reordered.filter(t => t.parentId === moved.parentId).length;\n const groupEnd = parentIndex + numSiblings;\n\n console.log('[GROUP RANGE CALCULATION]', {\n parentIndex: parentIndex,\n numSiblings: numSiblings,\n groupEnd: groupEnd,\n groupRange: `[${parentIndex}, ${groupEnd}]`,\n insertIndex: insertIndex,\n condition1_atOrAboveParent: insertIndex <= parentIndex,\n condition2_belowAllSiblings: insertIndex > groupEnd\n });\n\n // If insertIndex is <= parent (at or above parent position) or > groupEnd (below all siblings)\n // Note: insertIndex == parentIndex means child will be inserted at parent's position,\n // which after splicing puts child above parent (parent shifts down by 1)\n if (insertIndex <= parentIndex || insertIndex > groupEnd) {\n console.log('[DECISION] EXIT GROUP - insertIndex is outside group range');\n console.log(' -> Reason:', insertIndex <= parentIndex ? 'At or above parent position' : 'Below all siblings');\n console.log(' -> Setting inferredParentId = undefined');\n inferredParentId = undefined; // Exit group - become root\n } else {\n console.log('[DECISION] STAY IN GROUP - insertIndex is within group range');\n console.log(' -> Keeping original parentId:', moved.parentId);\n // Staying within group - keep original parentId\n inferredParentId = moved.parentId;\n }\n }\n } else {\n // Task is currently root - check if it should join a group\n console.log('[ROOT TASK] - Will check if it should join a group after splicing');\n // This needs to be calculated AFTER splicing, so we do it below\n }\n\n // Now splice the moved task into its final position\n reordered.splice(insertIndex, 0, moved);\n\n console.log('[AFTER SPLICE]', {\n movedTaskFinalPosition: insertIndex,\n totalTasks: reordered.length\n });\n\n // For root tasks, check if they should join a group (need reordered for this)\n if (!moved.parentId) {\n // Prefer taskAbove if it has a parent (joining that group)\n if (insertIndex > 0) {\n const taskAbove = reordered[insertIndex - 1];\n console.log('[ROOT TASK - CHECK TASK ABOVE]', {\n taskAboveId: taskAbove.id,\n taskAboveName: taskAbove.name,\n taskAboveParentId: taskAbove.parentId\n });\n if (taskAbove.parentId) {\n console.log(' -> Joining group from taskAbove:', taskAbove.parentId);\n inferredParentId = taskAbove.parentId;\n }\n }\n\n // Otherwise check taskBelow\n if (inferredParentId === undefined && insertIndex < reordered.length - 1) {\n const taskBelow = reordered[insertIndex + 1];\n console.log('[ROOT TASK - CHECK TASK BELOW]', {\n taskBelowId: taskBelow.id,\n taskBelowName: taskBelow.name,\n taskBelowParentId: taskBelow.parentId\n });\n if (taskBelow.parentId) {\n console.log(' -> Joining group from taskBelow:', taskBelow.parentId);\n inferredParentId = taskBelow.parentId;\n }\n }\n\n if (!inferredParentId) {\n console.log('[ROOT TASK] - Staying as root (no group to join)');\n }\n }\n\n console.log('[FINAL RESULT]', {\n inferredParentId: inferredParentId,\n willExitGroup: moved.parentId && !inferredParentId,\n willJoinGroup: !moved.parentId && !!inferredParentId,\n willStayInGroup: moved.parentId && inferredParentId === moved.parentId,\n willStayRoot: !moved.parentId && !inferredParentId\n });\n console.log('=== DRAG & DROP END ===\\n');\n\n onReorder?.(reordered, moved.id, inferredParentId);\n onTaskSelect?.(moved.id);\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n }, [tasks, onReorder, onTaskSelect]);\n\n const handleDragEnd = useCallback(() => {\n // Called when drag ends without a valid drop (Escape, or dropped outside)\n // handleDrop already clears state on successful drop, so this is only the cancel path\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n }, []);\n\n const handleConfirmNewTask = useCallback((name: string) => {\n const now = new Date();\n const todayISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()\n )).toISOString().split('T')[0];\n const endISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 7\n )).toISOString().split('T')[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name,\n startDate: todayISO,\n endDate: endISO,\n };\n onAdd?.(newTask);\n setIsCreating(false);\n }, [onAdd]);\n\n const handleCancelNewTask = useCallback(() => setIsCreating(false), []);\n\n return (\n <div\n ref={overlayRef}\n className={`gantt-tl-overlay${show ? '' : ' gantt-tl-hidden'}`}\n style={{ width: `${taskListWidth}px` }}\n >\n <div className=\"gantt-tl-table\">\n {/* Header row - aligns with TimeScaleHeader, 1px taller for row alignment */}\n <div className=\"gantt-tl-header\" style={{ height: `${headerHeight + 0.5}px` }}>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-number\">№</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-name\">Имя</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-date\">Начало</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-date\">Окончание</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-progress\">%</div>\n {/* Dependencies column header with type switcher */}\n <div className=\"gantt-tl-headerCell gantt-tl-cell-deps\" style={{ position: 'relative' }}>\n <Popover open={typeMenuOpen} onOpenChange={setTypeMenuOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"gantt-tl-dep-type-trigger\"\n disabled={disableDependencyEditing}\n onClick={(e) => e.stopPropagation()}\n >\n Связи {React.createElement(LINK_TYPE_ICONS[activeLinkType])} &#9662;\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div className=\"gantt-tl-dep-type-menu\">\n {LINK_TYPE_ORDER.map(lt => (\n <button\n key={lt}\n className={`gantt-tl-dep-type-option${activeLinkType === lt ? ' active' : ''}`}\n onClick={() => { setActiveLinkType(lt); setTypeMenuOpen(false); }}\n >\n {React.createElement(LINK_TYPE_ICONS[lt])}\n <span>{LINK_TYPE_LABELS[lt]}</span>\n </button>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n {cycleError && (\n <div className=\"gantt-tl-dep-error\">Цикл зависимостей!</div>\n )}\n </div>\n </div>\n\n {/* Data rows */}\n <div className=\"gantt-tl-body\" style={{ height: `${totalHeight}px` }}>\n {visibleTasks.map((task, index) => (\n <TaskListRow\n key={task.id}\n task={task}\n rowIndex={index}\n rowHeight={rowHeight}\n onTaskChange={onTaskChange}\n selectedTaskId={selectedTaskId}\n onRowClick={handleRowClick}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n allTasks={tasks}\n activeLinkType={activeLinkType}\n selectingPredecessorFor={selectingPredecessorFor}\n onSetSelectingPredecessorFor={setSelectingPredecessorFor}\n onAddDependency={handleAddDependency}\n onRemoveDependency={handleRemoveDependency}\n selectedChip={selectedChip}\n onChipSelect={handleChipSelect}\n onScrollToTask={onScrollToTask}\n onDelete={onDelete}\n onAdd={onAdd}\n onInsertAfter={onInsertAfter}\n editingTaskId={propEditingTaskId}\n isDragging={draggingIndex === index}\n isDragOver={dragOverIndex === index}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onDragEnd={handleDragEnd}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={onPromoteTask}\n onDemoteTask={onDemoteTask}\n />\n ))}\n </div>\n\n {/* Ghost row for new task creation — positioned OUTSIDE body div to avoid height desync */}\n {isCreating && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmNewTask}\n onCancel={handleCancelNewTask}\n />\n )}\n\n {/* Add task button - also serves as drop target for moving tasks to end */}\n {enableAddTask && onAdd && !isCreating && (\n <button\n className={`gantt-tl-add-btn${dragOverIndex === tasks.length ? ' gantt-tl-add-btn-drag-over' : ''}`}\n onClick={() => setIsCreating(true)}\n onDragEnter={(e) => {\n e.preventDefault();\n setDragOverIndex(tasks.length);\n }}\n onDragOver={(e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(tasks.length);\n }}\n onDragLeave={(e) => {\n e.preventDefault();\n setDragOverIndex(null);\n }}\n onDrop={(e) => {\n e.preventDefault();\n handleDrop(tasks.length, e);\n }}\n type=\"button\"\n >\n + Добавить задачу\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default TaskList;\n","'use client';\n\nimport React from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\n\nexport interface PopoverProps {\n /** Whether the popover is open */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** The trigger element */\n children: React.ReactNode;\n}\n\nexport interface PopoverContentProps {\n /** Content to display inside the popover */\n children: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Alignment relative to trigger */\n align?: 'start' | 'center' | 'end';\n /** Side to render the popover */\n side?: 'top' | 'right' | 'bottom' | 'left';\n /** Whether to use a portal for rendering */\n portal?: boolean;\n /** Collision padding */\n collisionPadding?: number;\n /** Callback when user interacts outside the popover */\n onInteractOutside?: (event: CustomEvent) => void;\n}\n\n/**\n * Popover root component wrapping Radix UI Popover\n */\nexport const Popover: React.FC<PopoverProps> = ({ open, onOpenChange, children }) => {\n return (\n <RadixPopover.Root open={open} onOpenChange={onOpenChange}>\n {children}\n </RadixPopover.Root>\n );\n};\n\n/**\n * Popover trigger — wraps the element that opens the popover\n */\nexport const PopoverTrigger = RadixPopover.Trigger;\n\n/**\n * Popover content — the floating panel\n */\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n className,\n align = 'start',\n side = 'bottom',\n portal = true,\n collisionPadding = 8,\n onInteractOutside,\n}) => {\n const content = (\n <RadixPopover.Content\n className={`gantt-popover${className ? ` ${className}` : ''}`}\n align={align}\n side={side}\n collisionPadding={collisionPadding}\n sideOffset={4}\n onInteractOutside={onInteractOutside}\n >\n {children}\n </RadixPopover.Content>\n );\n\n if (portal) {\n return <RadixPopover.Portal>{content}</RadixPopover.Portal>;\n }\n\n return content;\n};\n\nexport default Popover;\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';\nimport type { Task } from '../GanttChart';\nimport type { LinkType } from '../../types';\nimport { parseUTCDate } from '../../utils/dateUtils';\nimport { computeLagFromDates, isTaskParent, findParentId } from '../../utils/dependencyUtils';\nimport { Input } from '../ui/Input';\nimport { DatePicker } from '../ui/DatePicker';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/Popover';\nimport { LINK_TYPE_ICONS } from './DepIcons';\n\n// ---------------------------------------------------------------------------\n// DepChip — local unified component used in both single-chip cell and popover\n// ---------------------------------------------------------------------------\ninterface DepChipProps {\n lag?: number;\n dep: { taskId: string; type: LinkType };\n taskId: string;\n predecessorName?: string;\n selectedChip: TaskListRowProps['selectedChip'];\n disableDependencyEditing: boolean;\n onChipSelect: TaskListRowProps['onChipSelect'];\n onRowClick: TaskListRowProps['onRowClick'];\n onScrollToTask: TaskListRowProps['onScrollToTask'];\n onRemoveDependency: TaskListRowProps['onRemoveDependency'];\n onChipSelectClear: () => void;\n}\n\nconst TrashIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n);\n\nconst PlusIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n);\n\nconst DragHandleIcon = () => (\n <svg width=\"10\" height=\"14\" viewBox=\"0 0 10 14\" fill=\"currentColor\">\n <circle cx=\"2\" cy=\"2\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"2\" r=\"1.5\" />\n <circle cx=\"2\" cy=\"7\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"7\" r=\"1.5\" />\n <circle cx=\"2\" cy=\"12\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"12\" r=\"1.5\" />\n </svg>\n);\n\n// ---------------------------------------------------------------------------\n// HierarchyButton — Single button with left/right arrows for hierarchy navigation\n// ---------------------------------------------------------------------------\ninterface HierarchyButtonProps {\n /** Whether the task is a child (can be promoted) */\n isChild: boolean;\n /** Whether the task is a parent (has children) */\n isParent: boolean;\n /** Row index - first row cannot demote */\n rowIndex: number;\n /** Callback when promote is clicked (left arrow) */\n onPromote?: (e: React.MouseEvent) => void;\n /** Callback when demote is clicked (right arrow) */\n onDemote?: (e: React.MouseEvent) => void;\n}\n\nconst HierarchyButton: React.FC<HierarchyButtonProps> = ({\n isChild,\n isParent,\n rowIndex,\n onPromote,\n onDemote,\n}) => {\n // Can promote if task is a child\n const canPromote = isChild && onPromote;\n // Can demote if not a parent and not first row\n const canDemote = !isParent && onDemote && rowIndex > 0;\n\n // If neither action available, don't render\n if (!canPromote && !canDemote) {\n return null;\n }\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (canPromote) {\n onPromote!(e);\n } else if (canDemote) {\n onDemote!(e);\n }\n };\n\n const title = canPromote\n ? 'Повысить (сделать корневой)'\n : 'Понизить (сделать подчиненной)';\n\n const ArrowLeft = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m12 19-7-7 7-7\"/>\n <path d=\"M19 12H5\"/>\n </svg>\n );\n\n const ArrowRight = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M5 12h14\"/>\n <path d=\"m12 5 7 7-7 7\"/>\n </svg>\n );\n\n return (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={handleClick}\n title={title}\n >\n {canPromote ? <ArrowLeft /> : <ArrowRight />}\n </button>\n );\n};\n\nfunction formatDepDescription(type: LinkType, lag: number | undefined): string {\n const effectiveLag = lag ?? 0;\n\n if (type === 'FS') {\n if (effectiveLag > 0) return `Начать через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0) return `Начать за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Начать сразу после окончания`;\n }\n if (type === 'FF') {\n if (effectiveLag > 0) return `Завершить через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0) return `Завершить за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Завершить после окончания`;\n }\n if (type === 'SS') {\n if (effectiveLag > 0) return `Начать через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0) return `Начать за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Начать вместе с началом`;\n }\n if (type === 'SF') {\n if (effectiveLag > 0) return `Завершить через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0) return `Завершить за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Завершить до начала`;\n }\n return '';\n}\n\nconst DepChip: React.FC<DepChipProps> = ({\n lag,\n dep,\n taskId,\n predecessorName,\n selectedChip,\n disableDependencyEditing,\n onChipSelect,\n onRowClick,\n onScrollToTask,\n onRemoveDependency,\n onChipSelectClear,\n}) => {\n const isSelected =\n selectedChip?.successorId === taskId &&\n selectedChip?.predecessorId === dep.taskId &&\n selectedChip?.linkType === dep.type;\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (disableDependencyEditing) return;\n // When clicking on an already selected chip, prevent the PopoverTrigger from toggling\n if (isSelected) {\n e.preventDefault();\n onChipSelect?.(null);\n return;\n }\n onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });\n onScrollToTask?.(dep.taskId);\n };\n\n const handleOpenChange = useCallback((open: boolean) => {\n if (!open) {\n onChipSelect?.(null);\n }\n }, [onChipSelect]);\n\n const handleTrashClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemoveDependency?.(taskId, dep.taskId, dep.type);\n onChipSelectClear();\n };\n\n const Icon = LINK_TYPE_ICONS[dep.type];\n const depPrefix = formatDepDescription(dep.type, lag);\n const depName = predecessorName ?? dep.taskId;\n\n // TEMP: render without Popover to test click handler\n return (\n <span className=\"gantt-tl-dep-chip-wrapper\">\n <span\n className={`gantt-tl-dep-chip${isSelected ? ' gantt-tl-dep-chip-selected' : ''}`}\n onClick={handleClick}\n >\n <><Icon />{lag != null && lag !== 0 ? (lag > 0 ? `+${lag}` : `${lag}`) : ''}</>\n </span>\n {!disableDependencyEditing && (\n <button\n type=\"button\"\n className=\"gantt-tl-dep-chip-trash\"\n aria-label=\"Удалить связь\"\n onClick={handleTrashClick}\n >\n <TrashIcon />\n </button>\n )}\n </span>\n );\n};\n\nexport interface TaskListRowProps {\n /** Task data to render */\n task: Task;\n /** Index of the task row (for display in № column) */\n rowIndex: number;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via inline edit */\n onTaskChange?: (task: Task) => void;\n /** ID of currently selected task */\n selectedTaskId?: string;\n /** Callback when task row is clicked */\n onRowClick?: (taskId: string) => void;\n /** Disable task name editing (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing (default: false) */\n disableDependencyEditing?: boolean;\n /** All tasks (for dependency picker) */\n allTasks?: Task[];\n /** Currently active link type for new dependencies */\n activeLinkType?: LinkType;\n /** Task ID currently in predecessor-picking mode (null if not picking) */\n selectingPredecessorFor?: string | null;\n /** Callback to set the task currently in predecessor-picking mode */\n onSetSelectingPredecessorFor?: (taskId: string | null) => void;\n /** Callback to add a dependency link */\n onAddDependency?: (successorTaskId: string, predecessorTaskId: string, linkType: LinkType) => void;\n /** Callback to remove a dependency link */\n onRemoveDependency?: (taskId: string, predecessorTaskId: string, linkType: LinkType) => void;\n /** Currently selected chip (for predecessor-side delete) */\n selectedChip?: { successorId: string; predecessorId: string; linkType: string } | null;\n /** Callback when a chip is clicked (selects it) */\n onChipSelect?: (chip: { successorId: string; predecessorId: string; linkType: LinkType } | null) => void;\n /** Callback to scroll the chart grid to center this task (called when task name is clicked) */\n onScrollToTask?: (taskId: string) => void;\n /** Callback when task is deleted */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted below this row */\n onAdd?: (task: Task) => void;\n /** Callback when a new task is inserted after this task */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** ID of task that should enter edit mode on mount (for auto-edit after insert) */\n editingTaskId?: string | null;\n /** Whether this row is currently being dragged (shows semi-transparent) */\n isDragging?: boolean;\n /** Whether this row is the current drag-over target (shows top border indicator) */\n isDragOver?: boolean;\n /** Called when drag starts on the handle for this row */\n onDragStart?: (index: number, e: React.DragEvent) => void;\n /** Called when something is dragged over this row */\n onDragOver?: (index: number, e: React.DragEvent) => void;\n /** Called when something is dropped on this row */\n onDrop?: (index: number, e: React.DragEvent) => void;\n /** Called when drag ends (drop or Escape) */\n onDragEnd?: (e: React.DragEvent) => void;\n /** Set of collapsed parent task IDs */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked */\n onToggleCollapse?: (parentId: string) => void;\n /** Callback when task is promoted (parentId removed) */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when task is demoted (parentId set to previous task) */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n}\n\nconst toISODate = (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString().split('T')[0];\n // Handle full ISO strings like \"2026-02-12T00:00:00.000Z\"\n if (typeof value === 'string' && value.includes('T')) return value.split('T')[0];\n return value as string;\n};\n\nexport const TaskListRow: React.FC<TaskListRowProps> = React.memo(\n ({\n task,\n rowIndex,\n rowHeight,\n onTaskChange,\n selectedTaskId,\n onRowClick,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n allTasks = [],\n activeLinkType,\n selectingPredecessorFor,\n onSetSelectingPredecessorFor,\n onAddDependency,\n onRemoveDependency,\n selectedChip,\n onChipSelect,\n onScrollToTask,\n onDelete,\n onAdd,\n onInsertAfter,\n editingTaskId,\n isDragging = false,\n isDragOver = false,\n onDragStart,\n onDragOver,\n onDrop,\n onDragEnd,\n collapsedParentIds = new Set(),\n onToggleCollapse,\n onPromoteTask,\n onDemoteTask,\n }) => {\n const [editingName, setEditingName] = useState(false);\n const [nameValue, setNameValue] = useState('');\n const nameInputRef = useRef<HTMLInputElement>(null);\n const [editingProgress, setEditingProgress] = useState(false);\n const [progressValue, setProgressValue] = useState(0);\n const progressInputRef = useRef<HTMLInputElement>(null);\n const [overflowOpen, setOverflowOpen] = useState(false);\n const confirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const autoEditedForRef = useRef<string | null>(null); // Track which editingTaskId we already auto-entered for\n const editTriggerRef = useRef<'keypress' | 'doubleclick' | 'autoedit'>('doubleclick'); // How editing was started\n const [deletePending, setDeletePending] = useState(false);\n const deleteButtonRef = useRef<HTMLButtonElement>(null);\n\n const isSelected = selectedTaskId === task.id;\n\n // Hierarchy computed values\n const isParent = useMemo(() => isTaskParent(task.id, allTasks), [task.id, allTasks]);\n const isChild = task.parentId !== undefined;\n const isCollapsed = collapsedParentIds.has(task.id);\n\n // Picker mode flags for this row\n const isPicking = selectingPredecessorFor != null;\n const isSourceRow = isPicking && selectingPredecessorFor === task.id;\n\n // Chip data: compute effective lag from actual dates (always correct, even on initial load)\n const chips = useMemo(() => {\n const succStart = new Date(task.startDate as string);\n const succEnd = new Date(task.endDate as string);\n const taskById = new Map((allTasks ?? []).map(t => [t.id, t]));\n return (task.dependencies ?? []).map(dep => {\n const pred = taskById.get(dep.taskId);\n const lag = pred\n ? computeLagFromDates(\n dep.type,\n new Date(pred.startDate as string),\n new Date(pred.endDate as string),\n succStart,\n succEnd\n )\n : (dep.lag ?? 0);\n return { dep, lag, predecessorName: pred?.name ?? dep.taskId };\n });\n }, [task.dependencies, task.startDate, task.endDate, allTasks]);\n\n const linkWord = chips.length <= 4 ? 'связи' : 'связей';\n\n useEffect(() => {\n if (editingName && nameInputRef.current) {\n nameInputRef.current.focus();\n if (editTriggerRef.current === 'keypress') {\n // Cursor to end — the typed char is already in the input, don't select it\n const len = nameInputRef.current.value.length;\n nameInputRef.current.setSelectionRange(len, len);\n } else {\n // Double-click or auto-edit-on-insert: select all for easy replacement\n nameInputRef.current.select();\n }\n }\n }, [editingName]);\n\n // Reset delete confirmation when clicking elsewhere\n useEffect(() => {\n const handleMouseDownOutside = (event: MouseEvent) => {\n if (deletePending && deleteButtonRef.current && !deleteButtonRef.current.contains(event.target as Node)) {\n setDeletePending(false);\n }\n };\n\n if (deletePending) {\n document.addEventListener('mousedown', handleMouseDownOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleMouseDownOutside);\n };\n }, [deletePending]);\n\n // Auto-enter edit mode when this task is created via insert.\n // We track which editingTaskId we already reacted to (autoEditedForRef) so that\n // subsequent re-renders caused by saving the name (which changes task.name) do NOT\n // re-trigger edit mode. Without this guard, saving the name → onTaskChange → new task.name\n // → re-render → effect fires again → edit mode re-entered → user must press Enter twice.\n useEffect(() => {\n if (\n editingTaskId === task.id &&\n !disableTaskNameEditing &&\n autoEditedForRef.current !== editingTaskId\n ) {\n autoEditedForRef.current = editingTaskId;\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'autoedit';\n setNameValue(task.name);\n setEditingName(true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editingTaskId, task.id, disableTaskNameEditing]);\n\n const handleNameClick = useCallback((e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n onRowClick?.(task.id);\n onScrollToTask?.(task.id);\n }, [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]);\n\n const handleNameDoubleClick = useCallback((e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'doubleclick';\n setNameValue(task.name);\n setEditingName(true);\n }, [task.name, disableTaskNameEditing]);\n\n const handleRowKeyDown = useCallback((e: React.KeyboardEvent) => {\n // Don't handle row keyboard events when editing progress\n if (editingProgress) return;\n // F2: enter edit mode with cursor at end of existing name\n if (!editingName && !disableTaskNameEditing && e.key === 'F2') {\n e.preventDefault();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'keypress'; // 'keypress' trigger = cursor at end (not select-all)\n setNameValue(task.name);\n setEditingName(true);\n return;\n }\n // If not editing and a printable key is pressed, start editing\n if (!editingName && !disableTaskNameEditing && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'keypress';\n setNameValue(e.key);\n setEditingName(true);\n // Input will be focused by existing useEffect; cursor placed at end (not select-all)\n }\n }, [editingName, disableTaskNameEditing, task.name]);\n\n const handleNameSave = useCallback(() => {\n if (confirmedRef.current) {\n // Already saved via Enter key, skip blur handler\n confirmedRef.current = false;\n return;\n }\n if (nameValue.trim()) {\n onTaskChange?.({ ...task, name: nameValue.trim() });\n }\n setEditingName(false);\n }, [nameValue, task, onTaskChange]);\n\n const handleNameCancel = useCallback(() => {\n setEditingName(false);\n }, []);\n\n const handleNameKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n confirmedRef.current = true; // Mark as saved to prevent blur from triggering again\n if (nameValue.trim()) {\n onTaskChange?.({ ...task, name: nameValue.trim() });\n }\n setEditingName(false);\n } else if (e.key === 'Escape') {\n handleNameCancel();\n }\n }, [nameValue, task, onTaskChange, handleNameCancel]);\n\n const handleProgressClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n confirmedRef.current = false;\n setProgressValue(task.progress ?? 0);\n setEditingProgress(true);\n }, [task.progress]);\n\n const handleProgressSave = useCallback(() => {\n if (confirmedRef.current) {\n confirmedRef.current = false;\n return;\n }\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n onTaskChange?.({ ...task, progress: clampedValue });\n setEditingProgress(false);\n }, [progressValue, task, onTaskChange]);\n\n const handleProgressCancel = useCallback(() => {\n setEditingProgress(false);\n }, []);\n\n const handleProgressKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation(); // Prevent row-level keyboard handler from interfering\n if (e.key === 'Enter') {\n confirmedRef.current = true;\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n onTaskChange?.({ ...task, progress: clampedValue });\n setEditingProgress(false);\n } else if (e.key === 'Escape') {\n handleProgressCancel();\n }\n }, [progressValue, task, onTaskChange, handleProgressCancel]);\n\n useEffect(() => {\n if (editingProgress && progressInputRef.current) {\n progressInputRef.current.focus();\n progressInputRef.current.select();\n }\n }, [editingProgress]);\n\n // Both date pickers shift the whole task (preserving duration), same as drag-move\n const handleStartDateChange = useCallback((newDateISO: string) => {\n if (!newDateISO) return;\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const newStart = new Date(newDateISO + 'T00:00:00Z');\n const newEnd = new Date(newStart.getTime() + durationMs);\n onTaskChange?.({ ...task, startDate: newDateISO, endDate: newEnd.toISOString().split('T')[0] });\n }, [task, onTaskChange]);\n\n const handleEndDateChange = useCallback((newDateISO: string) => {\n if (!newDateISO) return;\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const newEnd = new Date(newDateISO + 'T00:00:00Z');\n const newStart = new Date(newEnd.getTime() - durationMs);\n onTaskChange?.({ ...task, startDate: newStart.toISOString().split('T')[0], endDate: newDateISO });\n }, [task, onTaskChange]);\n\n const handleRowClickInternal = useCallback(() => {\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleNumberClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleToggleCollapse = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleCollapse?.(task.id);\n }, [task.id, onToggleCollapse]);\n\n // Hierarchy handlers - promote/demote\n const handlePromote = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onPromoteTask?.(task.id);\n }, [task.id, onPromoteTask]);\n\n const handleDemote = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n // Find previous task in allTasks\n const currentIndex = allTasks.findIndex(t => t.id === task.id);\n if (currentIndex > 0) {\n const previousTask = allTasks[currentIndex - 1];\n // Smart demote: if previous task has a parent, use that parent (sibling behavior)\n // Otherwise, use previous task as parent (child behavior)\n const targetParentId = previousTask.parentId || previousTask.id;\n onDemoteTask?.(task.id, targetParentId);\n }\n }, [task.id, allTasks, onDemoteTask]);\n\n // Dependency handlers\n const handleAddClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(task.id);\n }, [task.id, onSetSelectingPredecessorFor]);\n\n const handlePredecessorPick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (!isPicking || isSourceRow) return;\n if (!selectingPredecessorFor || !activeLinkType) return;\n onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);\n }, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);\n\n const handleCancelPicking = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(null);\n }, [onSetSelectingPredecessorFor]);\n\n // True when this row is the predecessor for the currently selected chip\n const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;\n\n // Delete the selected dependency from the predecessor row's \"Удалить\" button\n const handleDeleteSelected = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (!selectedChip) return;\n onRemoveDependency?.(selectedChip.successorId, selectedChip.predecessorId, selectedChip.linkType as LinkType);\n onChipSelect?.(null);\n }, [selectedChip, onRemoveDependency, onChipSelect]);\n\n const startDateISO = toISODate(task.startDate);\n const endDateISO = toISODate(task.endDate);\n\n return (\n <div\n className={[\n 'gantt-tl-row',\n isSelected ? 'gantt-tl-row-selected' : '',\n isPicking && !isSourceRow ? 'gantt-tl-row-picking' : '',\n isSourceRow ? 'gantt-tl-row-picking-self' : '',\n isDragging ? 'gantt-tl-row-dragging' : '',\n isDragOver ? 'gantt-tl-row-drag-over' : '',\n isChild ? 'gantt-tl-row-child' : '',\n isParent ? 'gantt-tl-row-parent' : '',\n ].filter(Boolean).join(' ')}\n style={{ minHeight: `${rowHeight}px`, position: 'relative' }}\n onClick={handleRowClickInternal}\n onKeyDown={handleRowKeyDown}\n onDragOver={(e) => onDragOver?.(rowIndex, e)}\n onDrop={(e) => onDrop?.(rowIndex, e)}\n onMouseLeave={() => {\n if (deletePending) {\n setDeletePending(false);\n }\n }}\n tabIndex={isSelected ? 0 : -1}\n >\n {/* Number column — click selects the row */}\n <div\n className=\"gantt-tl-cell gantt-tl-cell-number\"\n onClick={handleNumberClick}\n >\n {isParent ? (\n <button\n type=\"button\"\n className=\"gantt-tl-collapse-btn\"\n onClick={handleToggleCollapse}\n aria-label={isCollapsed ? 'Развернуть' : 'Свернуть'}\n >\n {isCollapsed ? '+' : '-'}\n </button>\n ) : (\n <>\n <span\n className=\"gantt-tl-drag-handle\"\n draggable={true}\n onDragStart={(e) => {\n e.stopPropagation();\n onDragStart?.(rowIndex, e);\n }}\n onDragEnd={(e) => onDragEnd?.(e)}\n onClick={(e) => e.stopPropagation()}\n >\n <DragHandleIcon />\n </span>\n <span className=\"gantt-tl-num-label\">{rowIndex + 1}</span>\n </>\n )}\n </div>\n\n {/* Name column — styled Input overlay on edit */}\n <div className=\"gantt-tl-cell gantt-tl-cell-name\">\n {editingName && (\n <Input\n ref={nameInputRef}\n type=\"text\"\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n onBlur={handleNameSave}\n onKeyDown={handleNameKeyDown}\n className=\"gantt-tl-name-input\"\n onClick={(e) => e.stopPropagation()}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-name-trigger ${disableTaskNameEditing ? 'gantt-tl-name-locked' : ''}`}\n onClick={handleNameClick}\n onDoubleClick={handleNameDoubleClick}\n style={editingName ? { visibility: 'hidden', pointerEvents: 'none' } : undefined}\n >\n {task.name}\n </button>\n {!editingName && (\n <div className=\"gantt-tl-name-actions\">\n {onInsertAfter && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-insert\"\n onClick={(e) => {\n e.stopPropagation();\n const now = new Date();\n const todayISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()\n )).toISOString().split('T')[0];\n const endISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 7\n )).toISOString().split('T')[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name: 'Новая задача',\n startDate: todayISO,\n endDate: endISO,\n };\n onInsertAfter(task.id, newTask);\n }}\n aria-label=\"Вставить задачу после этой\"\n >\n <PlusIcon />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n ref={deleteButtonRef}\n className={`gantt-tl-name-action-btn gantt-tl-action-delete${deletePending ? ' gantt-tl-action-delete-confirm' : ''}`}\n onClick={(e) => {\n e.stopPropagation();\n if (!deletePending) {\n setDeletePending(true);\n } else {\n setDeletePending(false);\n onDelete(task.id);\n }\n }}\n aria-label=\"Удалить задачу\"\n >\n {deletePending ? 'Удалить?' : <TrashIcon />}\n </button>\n )}\n <HierarchyButton\n isChild={isChild}\n isParent={isParent}\n rowIndex={rowIndex}\n onPromote={onPromoteTask ? handlePromote : undefined}\n onDemote={onDemoteTask ? handleDemote : undefined}\n />\n </div>\n )}\n </div>\n\n {/* Start Date — DatePicker component */}\n <div className=\"gantt-tl-cell gantt-tl-cell-date\" onClick={(e) => e.stopPropagation()}>\n <DatePicker\n value={startDateISO}\n onChange={handleStartDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n />\n </div>\n\n {/* End Date — DatePicker component */}\n <div className=\"gantt-tl-cell gantt-tl-cell-date\" onClick={(e) => e.stopPropagation()}>\n <DatePicker\n value={endDateISO}\n onChange={handleEndDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n />\n </div>\n\n {/* Progress column */}\n <div className=\"gantt-tl-cell gantt-tl-cell-progress\" onClick={handleProgressClick}>\n {editingProgress && (\n <Input\n ref={progressInputRef}\n type=\"number\"\n min={0}\n max={100}\n value={progressValue}\n onChange={(e) => setProgressValue(parseInt(e.target.value) || 0)}\n onBlur={handleProgressSave}\n onKeyDown={handleProgressKeyDown}\n className=\"gantt-tl-progress-input\"\n onClick={(e) => e.stopPropagation()}\n />\n )}\n <span style={editingProgress ? { visibility: 'hidden', pointerEvents: 'none' } : undefined}>\n {task.progress ? `${Math.round(task.progress)}%` : '0%'}\n </span>\n </div>\n\n {/* Dependencies column */}\n <div\n className=\"gantt-tl-cell gantt-tl-cell-deps\"\n onClick={isSourceRow ? handleCancelPicking : (isPicking ? handlePredecessorPick : undefined)}\n >\n {isSourceRow ? (\n <span className=\"gantt-tl-dep-source-hint\">Выберите задачу</span>\n ) : isSelectedPredecessor && !disableDependencyEditing ? (\n /* Full-replacement: \"Зависит от [name]\" → hover → \"Удалить\" */\n <button\n type=\"button\"\n className=\"gantt-tl-dep-delete-label\"\n onClick={handleDeleteSelected}\n aria-label=\"Удалить связь\"\n >\n <span className=\"gantt-tl-dep-delete-label-default\">Связано с</span>\n <span className=\"gantt-tl-dep-delete-label-hover\">Удалить связь</span>\n </button>\n ) : (\n <>\n {chips.length >= 2 ? (\n /* 2+ deps — show only \"N связей\" summary chip that opens a popover */\n <Popover open={overflowOpen} onOpenChange={setOverflowOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-summary-chip\"\n onClick={(e) => { e.stopPropagation(); setOverflowOpen(v => !v); }}\n >\n {chips.length} {linkWord}\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div className=\"gantt-tl-dep-overflow-list\" onClick={(e) => e.stopPropagation()}>\n {chips.map(({ dep, lag, predecessorName }) => (\n <DepChip\n key={`${dep.taskId}-${dep.type}`}\n lag={lag}\n dep={dep}\n taskId={task.id}\n predecessorName={predecessorName}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n />\n ))}\n </div>\n </PopoverContent>\n </Popover>\n ) : chips.length === 1 ? (\n /* Single chip — unified DepChip */\n <DepChip\n lag={chips[0].lag}\n dep={chips[0].dep}\n taskId={task.id}\n predecessorName={chips[0].predecessorName}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n />\n ) : null}\n\n {/* \"+\" add dependency button — hidden in picker mode and when editing disabled, hover-reveal */}\n {!disableDependencyEditing && !isPicking && (\n <button\n type=\"button\"\n className={`gantt-tl-dep-add gantt-tl-dep-add-hover${selectedChip ? ' gantt-tl-dep-add-hidden' : ''}`}\n onClick={handleAddClick}\n aria-label=\"Добавить связь\"\n >\n +\n </button>\n )}\n </>\n )}\n </div>\n </div>\n );\n }\n);\n\nTaskListRow.displayName = 'TaskListRow';\nexport default TaskListRow;\n","'use client';\n\nimport React from 'react';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Additional CSS class names */\n className?: string;\n}\n\n/**\n * Styled text input component using gantt-lib CSS variables\n */\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => {\n return (\n <input\n ref={ref}\n className={`gantt-input${className ? ` ${className}` : ''}`}\n {...props}\n />\n );\n }\n);\n\nInput.displayName = 'Input';\nexport default Input;\n","'use client';\n\nimport React, { useState, useCallback } from 'react';\nimport { format, isValid } from 'date-fns';\nimport { Calendar } from './Calendar';\nimport { Popover, PopoverTrigger, PopoverContent } from './Popover';\n\nexport interface DatePickerProps {\n /** Current date value as ISO string (YYYY-MM-DD) */\n value?: string;\n /** Callback with new ISO date string (YYYY-MM-DD) when date is selected */\n onChange?: (isoDate: string) => void;\n /** Display format for the input (default: dd.MM.yyyy) */\n format?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether to use portal for popover (default: true) */\n portal?: boolean;\n /** Additional CSS class names for the trigger button */\n className?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n}\n\n/**\n * DatePicker component — shows formatted date as a button, opens calendar popup on click\n * Accepts and returns ISO date strings (YYYY-MM-DD)\n */\nexport const DatePicker: React.FC<DatePickerProps> = ({\n value,\n onChange,\n format: displayFormat = 'dd.MM.yyyy',\n placeholder = 'Pick a date',\n portal = true,\n className,\n disabled = false,\n}) => {\n const [open, setOpen] = useState(false);\n\n // Parse ISO string to Date for calendar\n const selectedDate: Date | undefined = (() => {\n if (!value) return undefined;\n const d = new Date(value + 'T00:00:00Z');\n return isValid(d) ? d : undefined;\n })();\n\n // Format Date for display\n const displayValue = selectedDate\n ? format(selectedDate, displayFormat)\n : placeholder;\n\n const handleSelect = useCallback(\n (day: Date) => {\n // Convert to ISO string using local date parts to avoid timezone shift\n const iso = [\n day.getFullYear(),\n String(day.getMonth() + 1).padStart(2, '0'),\n String(day.getDate()).padStart(2, '0'),\n ].join('-');\n onChange?.(iso);\n setOpen(false);\n },\n [onChange]\n );\n\n return (\n <Popover open={open} onOpenChange={disabled ? undefined : setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className={`gantt-datepicker-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {displayValue}\n </button>\n </PopoverTrigger>\n <PopoverContent\n portal={portal}\n align=\"start\"\n side=\"bottom\"\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={handleSelect}\n initialDate={selectedDate}\n />\n </PopoverContent>\n </Popover>\n );\n};\n\nDatePicker.displayName = 'DatePicker';\nexport default DatePicker;\n","'use client';\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useMemo,\n} from 'react';\nimport {\n startOfMonth,\n getDaysInMonth,\n format,\n addMonths,\n subMonths,\n addDays,\n subDays,\n isSameDay,\n getDay,\n isToday,\n isWeekend,\n isBefore,\n startOfDay,\n} from 'date-fns';\nimport { ru } from 'date-fns/locale';\n\nexport interface CalendarProps {\n selected?: Date;\n onSelect?: (date: Date) => void;\n initialDate?: Date;\n mode?: 'single' | 'range';\n disabled?: boolean;\n}\n\nfunction getDayClassName(day: Date, selected: Date | undefined): string {\n const classes: string[] = ['gantt-day-btn'];\n\n if (selected && isSameDay(day, selected)) classes.push('selected');\n if (isToday(day)) classes.push('today');\n if (isWeekend(day)) classes.push('weekend');\n if (isBefore(day, startOfDay(new Date())) && !isToday(day)) classes.push('past');\n\n return classes.join(' ');\n}\n\nexport const Calendar: React.FC<CalendarProps> = ({\n selected,\n onSelect,\n initialDate,\n mode = 'single',\n disabled = false,\n}) => {\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const initialMonth = useMemo(\n () => startOfMonth(initialDate ?? selected ?? new Date()),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n const [months, setMonths] = useState<Date[]>(() => [\n subMonths(initialMonth, 1),\n initialMonth,\n addMonths(initialMonth, 1),\n ]);\n\n const loadMoreMonths = useCallback((direction: 'up' | 'down') => {\n setMonths((prev) => {\n if (direction === 'up') {\n return [subMonths(prev[0], 1), ...prev];\n } else {\n return [...prev, addMonths(prev[prev.length - 1], 1)];\n }\n });\n }, []);\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n if (container.scrollTop <= 100) {\n const prevScrollHeight = container.scrollHeight;\n const prevScrollTop = container.scrollTop;\n loadMoreMonths('up');\n setTimeout(() => {\n container.scrollTop =\n container.scrollHeight - prevScrollHeight + prevScrollTop;\n }, 0);\n } else if (\n container.scrollTop + container.clientHeight >=\n container.scrollHeight - 100\n ) {\n loadMoreMonths('down');\n }\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [loadMoreMonths]);\n\n // Scroll to the selected/initial month on mount\n useEffect(() => {\n if (!scrollRef.current) return;\n const target = selected ?? initialDate ?? new Date();\n const monthKey = format(startOfMonth(target), 'yyyy-MM');\n const el = scrollRef.current.querySelector(`[data-month=\"${monthKey}\"]`);\n if (el) {\n (el as HTMLElement).scrollIntoView({ behavior: 'auto', block: 'start' });\n }\n // Run once on mount only\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const renderMonth = useCallback(\n (month: Date) => {\n const firstDay = startOfMonth(month);\n const totalDays = getDaysInMonth(month);\n // Monday-first: Sunday (0) -> 6, Monday (1) -> 0, ...\n const emptyDays = (getDay(firstDay) + 6) % 7;\n const monthKey = format(month, 'yyyy-MM');\n const monthLabel = format(month, 'LLLL yyyy', { locale: ru });\n\n const emptyCells = Array.from({ length: emptyDays }, (_, i) => (\n <div key={`e-${i}`} className=\"gantt-cal-empty-day\" />\n ));\n\n const dayCells = Array.from({ length: totalDays }, (_, i) => {\n const dayNum = i + 1;\n const day = new Date(month.getFullYear(), month.getMonth(), dayNum);\n const className = getDayClassName(day, selected);\n return (\n <button\n key={dayNum}\n type=\"button\"\n className={className}\n disabled={disabled}\n onClick={() => {\n if (!disabled && onSelect) {\n onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));\n }\n }}\n >\n {dayNum}\n </button>\n );\n });\n\n return (\n <div key={monthKey} className=\"gantt-cal-month\" data-month={monthKey}>\n <div className=\"gantt-cal-month-header\">{monthLabel}</div>\n <div className=\"gantt-cal-month-days\">\n {emptyCells}\n {dayCells}\n </div>\n </div>\n );\n },\n [selected, onSelect, disabled]\n );\n\n const renderedMonths = useMemo(\n () => months.map(renderMonth),\n [months, renderMonth]\n );\n\n const handleDayShift = useCallback(\n (deltaDays: number) => {\n if (!onSelect || disabled) return;\n const baseDate = selected ?? new Date();\n onSelect(addDays(baseDate, deltaDays));\n },\n [onSelect, selected, disabled]\n );\n\n const handleToday = useCallback(() => {\n if (!onSelect || disabled) return;\n onSelect(new Date());\n }, [onSelect, disabled]);\n\n return (\n <div ref={scrollRef} className=\"gantt-cal-container\">\n {renderedMonths}\n <div className=\"gantt-cal-nav\">\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(-7)}\n disabled={disabled}\n >\n -7\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(-1)}\n disabled={disabled}\n >\n -1\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={handleToday}\n disabled={disabled}\n >\n Сегодня\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(1)}\n disabled={disabled}\n >\n +1\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(7)}\n disabled={disabled}\n >\n +7\n </button>\n </div>\n </div>\n );\n};\n\nCalendar.displayName = 'Calendar';\nexport default Calendar;\n","import React from 'react';\nimport type { LinkType } from '../../types';\n\nconst DepIconFS = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m10 15 5 5 5-5\" /><path d=\"M4 4h7a4 4 0 0 1 4 4v12\" />\n </svg>\n);\n\nconst DepIconSS = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 5v14\" /><path d=\"M21 12H7\" /><path d=\"m15 18 6-6-6-6\" />\n </svg>\n);\n\nconst DepIconFF = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M17 12H3\" /><path d=\"m11 18 6-6-6-6\" /><path d=\"M21 5v14\" />\n </svg>\n);\n\nconst DepIconSF = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m14 15-5 5-5-5\" /><path d=\"M20 4h-7a4 4 0 0 0-4 4v12\" />\n </svg>\n);\n\nexport const LINK_TYPE_ICONS: Record<LinkType, React.FC> = {\n FS: DepIconFS,\n SS: DepIconSS,\n FF: DepIconFF,\n SF: DepIconSF,\n};\n\nexport const LINK_TYPE_LABELS: Record<LinkType, string> = {\n FS: 'Окончание-начало',\n SS: 'Начало-начало',\n FF: 'Окончание-окончание',\n SF: 'Начало-окончание',\n};\n","'use client';\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { Input } from '../ui/Input';\n\ninterface NewTaskRowProps {\n rowHeight: number;\n onConfirm: (name: string) => void;\n onCancel: () => void;\n}\n\nexport const NewTaskRow: React.FC<NewTaskRowProps> = ({ rowHeight, onConfirm, onCancel }) => {\n const [nameValue, setNameValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n const confirmedRef = useRef(false);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, []);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n if (nameValue.trim()) {\n confirmedRef.current = true;\n onConfirm(nameValue.trim());\n } else {\n onCancel();\n }\n } else if (e.key === 'Escape') {\n onCancel();\n }\n };\n\n const handleBlur = () => {\n if (confirmedRef.current) return; // already confirmed via Enter\n if (nameValue.trim()) {\n confirmedRef.current = true;\n onConfirm(nameValue.trim());\n } else {\n onCancel();\n }\n };\n\n return (\n <div className=\"gantt-tl-row gantt-tl-row-new\" style={{ minHeight: `${rowHeight}px` }}>\n <div className=\"gantt-tl-cell gantt-tl-cell-number\" />\n <div className=\"gantt-tl-cell gantt-tl-cell-name gantt-tl-cell-new-name\">\n <Input\n ref={inputRef}\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n placeholder=\"Название\"\n className=\"gantt-tl-name-input\"\n />\n </div>\n <div className=\"gantt-tl-cell\" />\n <div className=\"gantt-tl-cell\" />\n <div className=\"gantt-tl-cell\" />\n </div>\n );\n};\n\nexport default NewTaskRow;\n","'use client';\n\nimport React from 'react';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual variant */\n variant?: 'default' | 'ghost' | 'outline';\n /** Size variant */\n size?: 'default' | 'sm' | 'icon';\n /** Additional CSS class names */\n className?: string;\n}\n\n/**\n * Simple button component for calendar navigation and UI actions\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', children, ...props }, ref) => {\n const classes = [\n 'gantt-btn',\n variant !== 'default' ? `gantt-btn-${variant}` : '',\n size !== 'default' ? `gantt-btn-${size}` : '',\n className || '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button ref={ref} className={classes} {...props}>\n {children}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\nexport default Button;\n"],"mappings":"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","names":["import_react","startOfMonth","isWeekend","import_react","isWeekend","import_react","dayWidth","getUTCDayDifference","currentTask","import_jsx_runtime","React","import_react","import_jsx_runtime","import_react","import_jsx_runtime","arePropsEqual","React","import_jsx_runtime","import_react","import_jsx_runtime","React","lines","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","React","import_react","import_date_fns","import_react","import_date_fns","import_locale","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","newProgress","filteredTasks","tasks","import_react","import_jsx_runtime","React"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/GanttChart/GanttChart.tsx","../src/utils/dateUtils.ts","../src/utils/dependencyUtils.ts","../src/utils/hierarchyOrder.ts","../src/components/TimeScaleHeader/TimeScaleHeader.tsx","../src/components/TaskRow/TaskRow.tsx","../src/utils/geometry.ts","../src/hooks/useTaskDrag.ts","../src/components/TodayIndicator/TodayIndicator.tsx","../src/components/GridBackground/GridBackground.tsx","../src/components/DragGuideLines/DragGuideLines.tsx","../src/components/DependencyLines/DependencyLines.tsx","../src/components/TaskList/TaskList.tsx","../src/components/ui/Popover.tsx","../src/components/TaskList/TaskListRow.tsx","../src/components/ui/Input.tsx","../src/components/ui/DatePicker.tsx","../src/components/ui/Calendar.tsx","../src/components/TaskList/DepIcons.tsx","../src/components/TaskList/NewTaskRow.tsx","../src/components/ui/Button.tsx"],"sourcesContent":["'use client';\n\n// CSS import triggers tsup to emit dist/index.css (renamed to dist/styles.css by onSuccess)\nimport './styles.css';\n\n// Components\nexport { GanttChart, type Task, type TaskDependency, type GanttChartProps, type GanttChartHandle } from './components/GanttChart';\nexport { default as TaskRow } from './components/TaskRow';\nexport { default as TimeScaleHeader } from './components/TimeScaleHeader';\nexport { default as GridBackground } from './components/GridBackground';\nexport { default as TodayIndicator } from './components/TodayIndicator';\nexport { default as DragGuideLines } from './components/DragGuideLines/DragGuideLines';\nexport { TaskList, type TaskListProps } from './components/TaskList';\n\n// UI Components\nexport { Input, type InputProps } from './components/ui/Input';\nexport { Button, type ButtonProps } from './components/ui/Button';\nexport { Popover, PopoverTrigger, PopoverContent, type PopoverProps, type PopoverContentProps } from './components/ui/Popover';\nexport { Calendar, type CalendarProps } from './components/ui/Calendar';\nexport { DatePicker, type DatePickerProps } from './components/ui/DatePicker';\n\n// Hooks\nexport { useTaskDrag } from './hooks';\n\n// Utils\nexport * from './utils';\n\n// Types\nexport type {\n GanttDateRange,\n TaskBarGeometry,\n GridConfig,\n MonthSpan,\n GridLine,\n WeekendBlock,\n} from './types';\n","'use client';\n\nimport React, { useMemo, useCallback, useRef, useState, useEffect, useImperativeHandle, forwardRef } from 'react';\nimport { getMultiMonthDays } from '../../utils/dateUtils';\nimport { calculateGridWidth } from '../../utils/geometry';\nimport { validateDependencies, cascadeByLinks, computeParentDates, computeParentProgress, getChildren, removeDependenciesBetweenTasks } from '../../utils/dependencyUtils';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport type { ValidationResult } from '../../types';\nimport TimeScaleHeader from '../TimeScaleHeader';\nimport TaskRow from '../TaskRow';\nimport TodayIndicator from '../TodayIndicator';\nimport GridBackground from '../GridBackground';\nimport DragGuideLines from '../DragGuideLines/DragGuideLines';\nimport { DependencyLines } from '../DependencyLines';\nimport { TaskList } from '../TaskList';\nimport './GanttChart.css';\n\n/**\n * Task data structure for Gantt chart\n */\nexport interface Task {\n /** Unique identifier for the task */\n id: string;\n /** Display name of the task */\n name: string;\n /** Task start date (ISO string or Date object) */\n startDate: string | Date;\n /** Task end date (ISO string or Date object) */\n endDate: string | Date;\n /** Optional color for task bar visualization */\n color?: string;\n /** Optional parent task ID for hierarchy relationship */\n parentId?: string;\n /**\n * Optional progress value from 0-100\n * - Decimal values are allowed and rounded to nearest integer for display\n * - Values are clamped to 0-100 range\n * - Undefined or 0 means no progress is displayed\n * - Progress is visual-only, no user interaction\n */\n progress?: number;\n /**\n * Optional flag indicating if task is accepted\n * - Only meaningful when progress is 100%\n * - Affects the color of the progress bar (green for accepted, yellow for completed)\n */\n accepted?: boolean;\n /**\n * Optional array of task dependencies\n * - Each dependency references a predecessor task by ID\n * - Supports 4 link types: FS (finish-to-start), SS (start-to-start), FF (finish-to-finish), SF (start-to-finish)\n * - Lag is optional and defaults to 0 (positive = delay, negative = overlap)\n */\n dependencies?: TaskDependency[];\n /**\n * Optional flag to prevent drag and resize interactions.\n * When true, the task bar cannot be moved or resized.\n * Independent of accepted/progress — consumer controls both separately.\n */\n locked?: boolean;\n /**\n * Optional horizontal divider line for visual grouping.\n * - 'top' renders a bold line above the task row\n * - 'bottom' renders a bold line below the task row\n * The line spans the full grid width.\n */\n divider?: 'top' | 'bottom';\n}\n\n/**\n * Task dependency definition\n */\nexport interface TaskDependency {\n /** ID of the predecessor task */\n taskId: string;\n /** Link type: FS, SS, FF, or SF */\n type: 'FS' | 'SS' | 'FF' | 'SF';\n /** Optional lag in days (default: 0) */\n lag?: number;\n}\n\nexport interface GanttChartProps {\n /** Array of tasks to display */\n tasks: Task[];\n /** Width of each day column in pixels (default: 40) */\n dayWidth?: number;\n /** Height of each task row in pixels (default: 40) */\n rowHeight?: number;\n /** Height of the header row in pixels (default: 40) */\n headerHeight?: number;\n /** Container height. Can be pixels (600), string (\"90vh\", \"100%\", \"500px\"), or undefined for auto height */\n containerHeight?: number | string;\n /** Callback when tasks are modified via drag/resize. Can receive either the new tasks array or a functional updater. */\n onChange?: (tasks: Task[] | ((currentTasks: Task[]) => Task[])) => void;\n /** Optional callback for dependency validation results */\n onValidateDependencies?: (result: ValidationResult) => void;\n /** Enable automatic shifting of dependent tasks when predecessor moves (default: false) */\n enableAutoSchedule?: boolean;\n /** Disable dependency constraint checking during drag (default: false) */\n disableConstraints?: boolean;\n /** Called when a cascade drag completes; receives all shifted tasks (including dragged task) in hard mode */\n onCascade?: (tasks: Task[]) => void;\n /** Show task list overlay on the left side of the chart (default: false) */\n showTaskList?: boolean;\n /** Width of the task list overlay in pixels (default: 300) */\n taskListWidth?: number;\n /** Disable task name editing in the task list (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing in the task list (default: false) */\n disableDependencyEditing?: boolean;\n /** Highlight expired/overdue tasks with red background (default: false) */\n highlightExpiredTasks?: boolean;\n /** Callback when a new task is added via the task list */\n onAdd?: (task: Task) => void;\n /** Callback when a task is deleted via the task list */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted after a specific task via the task list */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n}\n\n/**\n * Ref handle type for GanttChart — exposes imperative scroll methods.\n */\nexport interface GanttChartHandle {\n scrollToToday: () => void;\n scrollToTask: (taskId: string) => void;\n}\n\n/**\n * GanttChart component - displays tasks on a monthly timeline with Excel-like styling\n *\n * The calendar automatically shows full months based on task date ranges.\n * For example, if tasks span from March 25 to May 5, the calendar shows\n * the complete months of March, April, and May (March 1 - May 31).\n *\n * @example\n * ```tsx\n * <GanttChart\n * tasks={[\n * { id: '1', name: 'Task 1', startDate: '2026-02-01', endDate: '2026-02-05' }\n * ]}\n * />\n * ```\n * @example\n * ```tsx\n * // Hide add task button\n * <GanttChart\n * tasks={tasks}\n * enableAddTask={false}\n * />\n * ```\n */\nexport const GanttChart = forwardRef<GanttChartHandle, GanttChartProps>(({\n tasks,\n dayWidth = 40,\n rowHeight = 40,\n headerHeight = 40,\n containerHeight,\n onChange,\n onValidateDependencies,\n enableAutoSchedule,\n disableConstraints,\n onCascade,\n showTaskList = false,\n taskListWidth = 520,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n highlightExpiredTasks = false,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n enableAddTask = true,\n}, ref) => {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n // Track selected task ID for highlighting in both TaskList and TaskRow\n const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null);\n\n // Track selected dep chip for arrow highlighting in DependencyLines\n const [selectedChip, setSelectedChip] = useState<{ successorId: string; predecessorId: string; linkType: string } | null>(null);\n\n // Hierarchy state: collapsed parent IDs\n const [collapsedParentIds, setCollapsedParentIds] = useState<Set<string>>(new Set());\n\n // Track editing task ID for auto-edit mode after insert\n const [editingTaskId, setEditingTaskId] = useState<string | null>(null);\n\n const normalizedTasks = useMemo(() => normalizeHierarchyTasks(tasks), [tasks]);\n\n // Calculate multi-month date range from normalized tasks\n const dateRange = useMemo(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);\n\n // Track dependency validation results\n const [validationResult, setValidationResult] = useState<ValidationResult | null>(null);\n\n // Cascade override positions for non-dragged chain members\n const [cascadeOverrides, setCascadeOverrides] = useState<Map<string, { left: number; width: number }>>(new Map());\n\n // Calculate grid width\n const gridWidth = useMemo(\n () => Math.round(dateRange.length * dayWidth),\n [dateRange.length, dayWidth]\n );\n\n // Filter tasks to hide children of collapsed parents (for chart rendering)\n const filteredTasks = useMemo(() => {\n return normalizedTasks.filter(task => {\n // Root-level tasks (no parentId) are always visible\n if (!task.parentId) return true;\n // Child tasks are visible only if their parent is not collapsed\n const parentCollapsed = collapsedParentIds.has(task.parentId);\n return !parentCollapsed;\n });\n }, [normalizedTasks, collapsedParentIds]);\n\n // Calculate total grid height (based on filtered tasks)\n const totalGridHeight = useMemo(\n () => filteredTasks.length * rowHeight,\n [filteredTasks.length, rowHeight]\n );\n\n // Get month start for calculations (first day of date range)\n const monthStart = useMemo(() => {\n if (dateRange.length === 0) {\n return new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 1));\n }\n const firstDay = dateRange[0];\n return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));\n }, [dateRange]);\n\n // Only render TodayIndicator if today is in the visible date range\n const todayInRange = useMemo(() => {\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n return dateRange.some(day => day.getTime() === today.getTime());\n }, [dateRange]);\n\n // Center chart on today's date on initial mount\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n const todayIndex = dateRange.findIndex(day => day.getTime() === today.getTime());\n\n if (todayIndex === -1) return;\n\n // Calculate scroll position to center today\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset - (containerWidth / 2) + (dayWidth / 2));\n\n container.scrollLeft = Math.max(0, scrollLeft);\n }, []); // Empty deps array - run only on mount\n\n /**\n * Scroll to today's date when the \"Today\" button is clicked\n */\n const scrollToToday = useCallback(() => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const now = new Date();\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n const todayIndex = dateRange.findIndex(day => day.getTime() === today.getTime());\n\n if (todayIndex === -1) return;\n\n // Calculate scroll position to center today\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset - (containerWidth / 2) + (dayWidth / 2));\n\n container.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });\n }, [dateRange, dayWidth]);\n\n /**\n * Scroll to a specific task by ID, centering its start date horizontally in the grid.\n */\n const scrollToTask = useCallback((taskId: string) => {\n const container = scrollContainerRef.current;\n if (!container || dateRange.length === 0) return;\n\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n\n const taskStart = new Date(task.startDate as string);\n const taskStartUTC = new Date(Date.UTC(\n taskStart.getUTCFullYear(),\n taskStart.getUTCMonth(),\n taskStart.getUTCDate()\n ));\n const taskIndex = dateRange.findIndex(day => day.getTime() === taskStartUTC.getTime());\n if (taskIndex === -1) return;\n\n const taskOffset = taskIndex * dayWidth;\n const scrollLeft = Math.round(taskOffset - dayWidth * 2);\n container.scrollTo({ left: Math.max(0, scrollLeft), behavior: 'smooth' });\n }, [tasks, dateRange, dayWidth]);\n\n /**\n * Expose scrollToToday and scrollToTask methods to parent component via ref\n */\n useImperativeHandle(\n ref,\n () => ({\n scrollToToday,\n scrollToTask,\n }),\n [scrollToToday, scrollToTask]\n );\n\n // Track drag state for guide lines\n const [dragGuideLines, setDragGuideLines] = useState<{\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n } | null>(null);\n\n // Track currently-dragged task's pixel position for real-time dependency line updates\n const [draggedTaskOverride, setDraggedTaskOverride] = useState<{ taskId: string; left: number; width: number } | null>(null);\n\n // Validate dependencies when tasks change\n useEffect(() => {\n const result = validateDependencies(tasks);\n setValidationResult(result);\n onValidateDependencies?.(result);\n }, [tasks, onValidateDependencies]);\n\n /**\n * Stable callback for task updates\n *\n * FIXED: No longer depends on `tasks` to avoid stale closure bugs.\n * Uses functional state update pattern: the callback receives an updater function\n * that maps over the current tasks state, ensuring we always use the latest state.\n *\n * This prevents the \"reverting\" bug where dragging a second task causes the\n * first task to revert to its original position.\n *\n * To prevent re-render storms during drag:\n * 1. The onChange callback is only called AFTER drag completes (mouseUp)\n * 2. During drag, only the dragged TaskRow re-renders (due to its internal state)\n * 3. Other TaskRows don't re-render because their props haven't changed\n *\n * The React.memo comparison in TaskRow excludes onChange from comparison,\n * relying on the fact that onChange fires only after drag completes.\n */\n const handleTaskChange = useCallback((updatedTask: Task) => {\n // Find original task to detect date changes\n const originalTask = tasks.find(t => t.id === updatedTask.id);\n if (!originalTask) {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n // Clear editingTaskId after name edit completes\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n const origStart = new Date(originalTask.startDate as string);\n const origEnd = new Date(originalTask.endDate as string);\n const newStart = new Date(updatedTask.startDate as string);\n const newEnd = new Date(updatedTask.endDate as string);\n const datesChanged = origStart.getTime() !== newStart.getTime() || origEnd.getTime() !== newEnd.getTime();\n\n if (!datesChanged) {\n // Dates didn't change, but progress or other fields might have\n // Check if this task has a parent and update parent progress if needed\n const taskParentId = (updatedTask as any).parentId;\n if (taskParentId) {\n onChange?.((currentTasks) => {\n let finalTasks = currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t);\n // Update parent progress\n const newProgress = computeParentProgress(taskParentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === taskParentId\n ? { ...t, progress: newProgress }\n : t\n );\n return finalTasks;\n });\n } else {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n }\n // Clear editingTaskId after name edit completes\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n let cascadedTasksForCallback: Task[];\n\n if (disableConstraints) {\n cascadedTasksForCallback = [updatedTask];\n } else {\n const cascadedChain = cascadeByLinks(updatedTask.id, newStart, newEnd, tasks);\n cascadedTasksForCallback = [updatedTask, ...cascadedChain];\n }\n\n // Apply changes\n if (disableConstraints) {\n onChange?.((currentTasks) => currentTasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n } else {\n onChange?.((currentTasks) => {\n const m = new Map(cascadedTasksForCallback.map(t => [t.id, t]));\n\n // Phase 19: Update parent dates when child task changes\n // For each updated task, check if it has a parent and update parent dates\n let finalTasks = currentTasks.map(t => m.get(t.id) ?? t);\n\n // Collect parent IDs that need updating\n const parentIdsToUpdate = new Set<string>();\n cascadedTasksForCallback.forEach(task => {\n if ((task as any).parentId) {\n parentIdsToUpdate.add((task as any).parentId);\n }\n });\n\n // Update each parent's dates and progress\n parentIdsToUpdate.forEach(parentId => {\n // Skip recomputing dates for the updated task itself if it's a parent\n // The user's manual drag/resize position should be preserved\n if (parentId === updatedTask.id) {\n // Still update progress from children, but not dates\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, progress: newProgress }\n : t\n );\n return;\n }\n\n const newDates = computeParentDates(parentId, finalTasks);\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, startDate: newDates.startDate.toISOString().split('T')[0], endDate: newDates.endDate.toISOString().split('T')[0], progress: newProgress }\n : t\n );\n });\n\n return finalTasks;\n });\n onCascade?.(cascadedTasksForCallback);\n }\n }, [tasks, onChange, disableConstraints, onCascade, editingTaskId]);\n\n /**\n * Handle task deletion: purge deleted taskId from all other tasks' dependency arrays,\n * emit onChange with cleaned tasks, then emit onDelete with the taskId.\n * For parent tasks, cascade delete to all children.\n */\n const handleDelete = useCallback((taskId: string) => {\n onChange?.((currentTasks) => {\n // Collect all tasks to delete (parent + descendants)\n const toDelete = new Set<string>([taskId]);\n\n function collectDescendants(parentId: string) {\n const children = getChildren(parentId, currentTasks);\n children.forEach(child => {\n toDelete.add(child.id);\n collectDescendants(child.id);\n });\n }\n\n collectDescendants(taskId);\n\n // Filter out deleted tasks\n const filteredTasks = currentTasks.filter(t => !toDelete.has(t.id));\n\n // Clean dependencies pointing to deleted tasks\n const cleanedTasks = filteredTasks.map(task => {\n if (!task.dependencies) return task;\n return {\n ...task,\n dependencies: task.dependencies.filter(dep => !toDelete.has(dep.taskId))\n };\n });\n\n return cleanedTasks;\n });\n onDelete?.(taskId);\n }, [onChange, onDelete]);\n\n /**\n * Handle task insertion: set editingTaskId to trigger auto-edit mode,\n * then notify external consumer via onInsertAfter callback.\n *\n * NOTE: The external onInsertAfter callback is responsible for adding\n * the task to the tasks array via onChange.\n */\n const handleInsertAfter = useCallback((taskId: string, newTask: Task) => {\n setEditingTaskId(newTask.id);\n onInsertAfter?.(taskId, newTask);\n }, [onInsertAfter]);\n\n /**\n * Handle task reordering: notify external consumer via onChange and onReorder callbacks.\n *\n * NOTE: onChange receives the full reordered array directly (not a functional updater).\n * Reordering is always a full replacement, never a diff.\n *\n * Extended signature: also accepts movedTaskId and inferredParentId for smart hierarchy.\n */\n const handleReorder = useCallback((reorderedTasks: Task[], movedTaskId?: string, inferredParentId?: string) => {\n console.log('=== GANTT CHART handleReorder START ===');\n console.log('[INPUTS]', {\n movedTaskId,\n inferredParentId,\n inferredParentIdType: typeof inferredParentId,\n reorderedTasksCount: reorderedTasks.length\n });\n\n // Find the moved task in reorderedTasks\n const movedTaskInReordered = reorderedTasks.find(t => t.id === movedTaskId);\n if (movedTaskInReordered) {\n console.log('[MOVED TASK IN REORDERED]', {\n id: movedTaskInReordered.id,\n name: movedTaskInReordered.name,\n currentParentId: movedTaskInReordered.parentId\n });\n } else {\n console.log('[MOVED TASK NOT FOUND IN REORDERED]');\n }\n\n onChange?.((currentTasks) => {\n console.log('[ONCHANGE START]', {\n currentTasksCount: currentTasks.length,\n movedTaskId,\n inferredParentId\n });\n\n // Find the moved task in currentTasks\n const movedTaskInCurrent = currentTasks.find(t => t.id === movedTaskId);\n if (movedTaskInCurrent) {\n console.log('[MOVED TASK IN CURRENT BEFORE UPDATE]', {\n id: movedTaskInCurrent.id,\n name: movedTaskInCurrent.name,\n currentParentId: movedTaskInCurrent.parentId\n });\n }\n\n let updated = reorderedTasks;\n // CRITICAL: Check movedTaskId only, NOT inferredParentId !== undefined\n // When inferredParentId is undefined, we want to CLEAR the parentId (exit group)\n // The old condition `inferredParentId !== undefined` prevented this!\n if (movedTaskId) {\n console.log('[CONDITION CHECK]', {\n condition: 'if (movedTaskId)',\n movedTaskId,\n isTrue: !!movedTaskId,\n willUpdateParentId: true\n });\n updated = updated.map(t => {\n if (t.id === movedTaskId) {\n const newParentId = inferredParentId || undefined;\n console.log('[UPDATING TASK]', {\n taskId: t.id,\n taskName: t.name,\n oldParentId: t.parentId,\n newParentId: newParentId,\n inferredParentId: inferredParentId,\n finalValue: newParentId\n });\n return { ...t, parentId: newParentId };\n }\n return t;\n });\n } else {\n console.log('[CONDITION CHECK]', {\n condition: 'if (movedTaskId)',\n movedTaskId,\n isTrue: false,\n willUpdateParentId: false\n });\n }\n\n // Verify the updated task\n const updatedTask = updated.find(t => t.id === movedTaskId);\n if (updatedTask) {\n console.log('[UPDATED TASK VERIFICATION]', {\n id: updatedTask.id,\n name: updatedTask.name,\n finalParentId: updatedTask.parentId\n });\n }\n\n console.log('[ONCHANGE END]', {\n updatedCount: updated.length\n });\n console.log('=== GANTT CHART handleReorder END ===\\n');\n\n return normalizeHierarchyTasks(updated);\n });\n onReorder?.(normalizeHierarchyTasks(reorderedTasks), movedTaskId, inferredParentId);\n }, [onChange, onReorder]);\n\n // Build merged pixel overrides for DependencyLines: dragged task + cascade chain members\n const dependencyOverrides = useMemo(() => {\n const map = new Map(cascadeOverrides);\n if (draggedTaskOverride) {\n map.set(draggedTaskOverride.taskId, {\n left: draggedTaskOverride.left,\n width: draggedTaskOverride.width,\n });\n }\n return map;\n }, [cascadeOverrides, draggedTaskOverride]);\n\n /**\n * Handle real-time cascade progress — updates cascadeOverrides state each RAF\n * so non-dragged chain members re-render with their preview positions.\n * new Map() forces React to detect the state change.\n */\n const handleCascadeProgress = useCallback((overrides: Map<string, { left: number; width: number }>) => {\n setCascadeOverrides(new Map(overrides));\n }, []);\n\n /**\n * Handle cascade completion — updates all shifted tasks via onChange (functional updater)\n * and notifies the external onCascade consumer.\n */\n const handleCascade = useCallback((cascadedTasks: Task[]) => {\n // Update state by merging cascaded tasks into current tasks\n onChange?.((currentTasks) => {\n const cascadeMap = new Map(cascadedTasks.map(t => [t.id, t]));\n let finalTasks = currentTasks.map(t => cascadeMap.get(t.id) ?? t);\n\n // The first task in cascadedTasks is always the dragged task (from useTaskDrag.ts)\n // If the dragged task is a parent, its dates should NOT be recomputed from children\n // because the user explicitly positioned it. Children should follow the parent.\n const draggedTaskId = cascadedTasks[0]?.id;\n\n // Update parent dates for any cascaded tasks that have parents\n // Collect parent IDs that need updating\n const parentIdsToUpdate = new Set<string>();\n cascadedTasks.forEach(task => {\n if ((task as any).parentId) {\n parentIdsToUpdate.add((task as any).parentId);\n }\n });\n\n // Update each parent's dates and progress\n parentIdsToUpdate.forEach(parentId => {\n // Skip recomputing dates for the dragged task itself\n // The user's manual drag position should be preserved\n if (parentId === draggedTaskId) {\n // Still update progress from children, but not dates\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, progress: newProgress }\n : t\n );\n return;\n }\n\n const newDates = computeParentDates(parentId, finalTasks);\n const newProgress = computeParentProgress(parentId, finalTasks);\n finalTasks = finalTasks.map(t =>\n t.id === parentId\n ? { ...t, startDate: newDates.startDate.toISOString().split('T')[0], endDate: newDates.endDate.toISOString().split('T')[0], progress: newProgress }\n : t\n );\n });\n\n return finalTasks;\n });\n // Notify external consumer\n onCascade?.(cascadedTasks);\n }, [onChange, onCascade]);\n\n /**\n * Handle task selection from TaskList or TaskRow\n */\n const handleTaskSelect = useCallback((taskId: string | null) => {\n setSelectedTaskId(taskId);\n }, []);\n\n // Hierarchy callbacks\n const handleToggleCollapse = useCallback((parentId: string) => {\n setCollapsedParentIds(prev => {\n const next = new Set(prev);\n if (next.has(parentId)) {\n next.delete(parentId);\n } else {\n next.add(parentId);\n }\n return next;\n });\n }, []);\n\n const handlePromoteTask = useCallback((taskId: string) => {\n onChange?.((currentTasks) => {\n // Find the task to promote\n const taskToPromote = currentTasks.find(t => t.id === taskId);\n if (!taskToPromote || !(taskToPromote as any).parentId) {\n return currentTasks; // No parent to remove from\n }\n\n const parentId = (taskToPromote as any).parentId;\n\n // Find all siblings (children of the same parent)\n const siblings = currentTasks.filter(t => (t as any).parentId === parentId);\n\n if (siblings.length <= 1) {\n // Only child, just remove parentId\n return normalizeHierarchyTasks(currentTasks.map(t =>\n t.id === taskId ? { ...t, parentId: undefined } : t\n ));\n }\n\n // Find the last sibling in array order\n const lastSiblingIndex = currentTasks\n .map((t, i) => ({ task: t, index: i }))\n .filter(({ task }) => (task as any).parentId === parentId)\n .sort((a, b) => b.index - a.index)[0];\n\n if (!lastSiblingIndex) {\n return normalizeHierarchyTasks(currentTasks.map(t =>\n t.id === taskId ? { ...t, parentId: undefined } : t\n ));\n }\n\n // Create new array with task moved after last sibling\n const withoutPromotedTask = currentTasks.filter(t => t.id !== taskId);\n const insertIndex = lastSiblingIndex.index + 1;\n\n const promotedTask = { ...taskToPromote, parentId: undefined };\n const newTasks = [\n ...withoutPromotedTask.slice(0, insertIndex),\n promotedTask,\n ...withoutPromotedTask.slice(insertIndex)\n ];\n\n return normalizeHierarchyTasks(newTasks);\n });\n }, [onChange]);\n\n const handleDemoteTask = useCallback((taskId: string, newParentId: string) => {\n onChange?.((currentTasks) => {\n // Check for circular hierarchy\n const wouldCreateCircular = (targetId: string, parentId: string, tasks: Task[]): boolean => {\n if (targetId === parentId) return true; // Can't be own parent\n\n const descendants = new Set<string>();\n function collect(id: string) {\n const children = getChildren(id, tasks);\n children.forEach(child => {\n descendants.add(child.id);\n collect(child.id);\n });\n }\n collect(targetId);\n return descendants.has(parentId);\n };\n\n if (wouldCreateCircular(taskId, newParentId, currentTasks)) {\n // Circular hierarchy detected, return unchanged\n return currentTasks;\n }\n\n // Remove any existing dependencies between the two tasks\n let updatedTasks = removeDependenciesBetweenTasks(taskId, newParentId, currentTasks);\n\n // Apply parentId change\n updatedTasks = updatedTasks.map(t => {\n if (t.id === taskId) {\n // Set parentId to demote under new parent\n return { ...t, parentId: newParentId };\n }\n return t;\n });\n\n // Compute and apply parent dates from all children\n const parentDates = computeParentDates(newParentId, updatedTasks);\n const parentProgress = computeParentProgress(newParentId, updatedTasks);\n\n updatedTasks = updatedTasks.map(t =>\n t.id === newParentId\n ? { ...t, startDate: parentDates.startDate.toISOString().split('T')[0], endDate: parentDates.endDate.toISOString().split('T')[0], progress: parentProgress }\n : t\n );\n\n return normalizeHierarchyTasks(updatedTasks);\n });\n }, [onChange]);\n\n // Pan (grab-scroll) on empty grid area\n const panStateRef = useRef<{ active: boolean; startX: number; startY: number; scrollX: number; scrollY: number } | null>(null);\n\n const handlePanStart = useCallback((e: React.MouseEvent) => {\n // Only pan on left click, skip if clicking on a task bar, input, or task list\n if (e.button !== 0) return;\n const target = e.target as HTMLElement;\n if (target.closest('[data-taskbar]')) return;\n if (target.closest('input, button, textarea, [contenteditable]')) return;\n if (target.closest('.gantt-tl-overlay')) return;\n\n const container = scrollContainerRef.current;\n if (!container) return;\n\n panStateRef.current = {\n active: true,\n startX: e.clientX,\n startY: e.clientY,\n scrollX: container.scrollLeft,\n scrollY: container.scrollTop,\n };\n // Blur any focused input so onBlur save handlers fire before pan starts\n if (document.activeElement instanceof HTMLElement) {\n document.activeElement.blur();\n }\n container.style.cursor = 'grabbing';\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n const handlePanMove = (e: MouseEvent) => {\n const pan = panStateRef.current;\n if (!pan?.active) return;\n const container = scrollContainerRef.current;\n if (!container) return;\n\n container.scrollLeft = pan.scrollX - (e.clientX - pan.startX);\n container.scrollTop = pan.scrollY - (e.clientY - pan.startY);\n };\n\n const handlePanEnd = () => {\n if (!panStateRef.current?.active) return;\n panStateRef.current = null;\n const container = scrollContainerRef.current;\n if (container) container.style.cursor = '';\n };\n\n window.addEventListener('mousemove', handlePanMove);\n window.addEventListener('mouseup', handlePanEnd);\n return () => {\n window.removeEventListener('mousemove', handlePanMove);\n window.removeEventListener('mouseup', handlePanEnd);\n };\n }, []);\n\n return (\n <div className=\"gantt-container\">\n <div\n ref={scrollContainerRef}\n className=\"gantt-scrollContainer\"\n style={{ height: containerHeight ?? 'auto', cursor: 'grab' }}\n onMouseDown={handlePanStart}\n >\n {/* Content wrapper - enables TaskList to scroll with chart horizontally */}\n <div className=\"gantt-scrollContent\">\n {/* TaskList - sticky left, scrolls with content horizontally */}\n <TaskList\n tasks={normalizedTasks}\n rowHeight={rowHeight}\n headerHeight={headerHeight}\n taskListWidth={taskListWidth}\n onTaskChange={handleTaskChange}\n selectedTaskId={selectedTaskId ?? undefined}\n onTaskSelect={handleTaskSelect}\n show={showTaskList}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n onScrollToTask={scrollToTask}\n onSelectedChipChange={setSelectedChip}\n onAdd={onAdd}\n onDelete={handleDelete}\n onInsertAfter={handleInsertAfter}\n onReorder={handleReorder}\n editingTaskId={editingTaskId}\n enableAddTask={enableAddTask}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={handlePromoteTask}\n onDemoteTask={handleDemoteTask}\n />\n\n {/* Chart area */}\n <div style={{ minWidth: `${gridWidth}px`, flex: 1 }}>\n {/* Sticky header - stays at top during vertical scroll, scrolls with content horizontally */}\n <div className=\"gantt-stickyHeader\" style={{ width: `${gridWidth}px` }}>\n <TimeScaleHeader\n days={dateRange}\n dayWidth={dayWidth}\n headerHeight={headerHeight}\n />\n </div>\n\n {/* Task area */}\n <div\n className=\"gantt-taskArea\"\n style={{\n position: 'relative',\n width: `${gridWidth}px`,\n }}\n >\n <GridBackground\n dateRange={dateRange}\n dayWidth={dayWidth}\n totalHeight={totalGridHeight}\n />\n\n {todayInRange && <TodayIndicator monthStart={monthStart} dayWidth={dayWidth} />}\n\n {/* Dependency lines SVG overlay */}\n <DependencyLines\n tasks={filteredTasks}\n allTasks={normalizedTasks}\n collapsedParentIds={collapsedParentIds}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n gridWidth={gridWidth}\n dragOverrides={dependencyOverrides}\n selectedDep={selectedChip}\n />\n\n {dragGuideLines && (\n <DragGuideLines\n isDragging={dragGuideLines.isDragging}\n dragMode={dragGuideLines.dragMode}\n left={dragGuideLines.left}\n width={dragGuideLines.width}\n totalHeight={totalGridHeight}\n />\n )}\n\n {filteredTasks.map((task, index) => (\n <TaskRow\n key={task.id}\n task={task}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n onChange={handleTaskChange}\n onDragStateChange={(state) => {\n if (state.isDragging) {\n setDragGuideLines(state);\n setDraggedTaskOverride({ taskId: task.id, left: state.left, width: state.width });\n } else {\n setDragGuideLines(null);\n setDraggedTaskOverride(null);\n }\n }}\n rowIndex={index}\n allTasks={normalizedTasks}\n enableAutoSchedule={enableAutoSchedule ?? false}\n disableConstraints={disableConstraints ?? false}\n overridePosition={cascadeOverrides.get(task.id)}\n onCascadeProgress={handleCascadeProgress}\n onCascade={handleCascade}\n highlightExpiredTasks={highlightExpiredTasks}\n />\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\nGanttChart.displayName = 'GanttChart';\n\nexport default GanttChart;\n","import { parseISO, isValid } from 'date-fns';\n\n/**\n * Parse date string as UTC to prevent DST issues\n * @param date - Date string or Date object\n * @returns Date object representing UTC midnight\n * @throws Error if date string is invalid\n */\nexport const parseUTCDate = (date: string | Date): Date => {\n if (typeof date === 'string') {\n // If already an ISO string (contains 'T'), parse directly\n // Otherwise, append UTC time for simple date strings (YYYY-MM-DD)\n const dateStr = date.includes('T') ? date : `${date}T00:00:00Z`;\n const parsed = new Date(dateStr);\n if (isNaN(parsed.getTime())) {\n throw new Error(`Invalid date string: ${date}`);\n }\n return parsed;\n }\n return date;\n};\n\n/**\n * Get all days in the month of given date (UTC)\n * @param date - Reference date (any day in the target month)\n * @returns Array of Date objects for each day in the month\n */\nexport const getMonthDays = (date: Date | string): Date[] => {\n const utcDate = parseUTCDate(date);\n const year = utcDate.getUTCFullYear();\n const month = utcDate.getUTCMonth();\n\n // Get days in month (handles leap years)\n const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n\n const days: Date[] = [];\n for (let day = 1; day <= daysInMonth; day++) {\n days.push(new Date(Date.UTC(year, month, day)));\n }\n\n return days;\n};\n\n/**\n * Calculate day offset from month start (0-based)\n * @param date - The date to calculate offset for\n * @param monthStart - The start of the month as reference\n * @returns Number of days from month start (negative if date is before month start)\n */\nexport const getDayOffset = (date: Date, monthStart: Date): number => {\n const dateMs = Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n );\n const startMs = Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n );\n return Math.round((dateMs - startMs) / (1000 * 60 * 60 * 24));\n};\n\n/**\n * Check if date is today (local timezone comparison)\n * Uses local time to determine today's date boundary so the result matches\n * the user's timezone rather than UTC (prevents off-by-one errors at midnight).\n * @param date - Date to check\n * @returns True if date is today, false otherwise\n */\nexport const isToday = (date: Date): boolean => {\n const now = new Date();\n // Use local time methods so the \"today\" boundary reflects the user's timezone.\n // getUTCFullYear/Month/Date would shift the day for non-UTC users.\n const today = new Date(Date.UTC(\n now.getFullYear(),\n now.getMonth(),\n now.getDate()\n ));\n const compareDate = new Date(Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n ));\n return today.getTime() === compareDate.getTime();\n};\n\n/**\n * Check if date is a weekend day (Saturday or Sunday)\n * @param date - Date to check\n * @returns True if date is Saturday (6) or Sunday (0), false otherwise\n */\nexport const isWeekend = (date: Date): boolean => {\n const day = date.getUTCDay();\n return day === 0 || day === 6; // Sunday (0) or Saturday (6)\n};\n\n/**\n * Calculate multi-month date range from task dates\n * Expands range to include full months with padding on both ends for drag flexibility\n * Adds 1 month before and 2 months after the task range\n * @param tasks - Array of tasks with startDate and endDate\n * @returns Array of Date objects for all days in the expanded range\n */\nexport const getMultiMonthDays = (tasks: Array<{ startDate: string | Date; endDate: string | Date }>): Date[] => {\n // Handle empty task array by returning current month\n if (!tasks || tasks.length === 0) {\n return getMonthDays(new Date());\n }\n\n // Find min and max dates from all tasks\n let minDate: Date | null = null;\n let maxDate: Date | null = null;\n\n for (const task of tasks) {\n const start = parseUTCDate(task.startDate);\n const end = parseUTCDate(task.endDate);\n\n if (!minDate || start.getTime() < minDate.getTime()) {\n minDate = start;\n }\n if (!maxDate || end.getTime() > maxDate.getTime()) {\n maxDate = end;\n }\n }\n\n if (!minDate || !maxDate) {\n return getMonthDays(new Date());\n }\n\n // Extend to full months: 1st of first month to last day of last month\n // Add padding: 2 months after for drag flexibility\n const startOfMonth = new Date(Date.UTC(\n minDate.getUTCFullYear(),\n minDate.getUTCMonth(),\n 1\n ));\n\n const endOfMonth = new Date(Date.UTC(\n maxDate.getUTCFullYear(),\n maxDate.getUTCMonth() + 1 + 2, // Original + 2 months padding after\n 0\n ));\n\n // Generate all dates in range\n const days: Date[] = [];\n const current = new Date(startOfMonth);\n\n while (current.getTime() <= endOfMonth.getTime()) {\n days.push(new Date(Date.UTC(\n current.getUTCFullYear(),\n current.getUTCMonth(),\n current.getUTCDate()\n )));\n // Move to next day\n current.setUTCDate(current.getUTCDate() + 1);\n }\n\n return days;\n};\n\n/**\n * Calculate month spans within a date range\n * @param dateRange - Array of Date objects representing the full range\n * @returns Array of month span objects with month, days count, and start index\n */\nexport const getMonthSpans = (\n dateRange: Date[]\n): Array<{ month: Date; days: number; startIndex: number }> => {\n if (dateRange.length === 0) {\n return [];\n }\n\n const spans: Array<{ month: Date; days: number; startIndex: number }> = [];\n let currentMonthYear = `${dateRange[0].getUTCFullYear()}-${dateRange[0].getUTCMonth()}`;\n let startOfMonthIndex = 0;\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const monthYear = `${date.getUTCFullYear()}-${date.getUTCMonth()}`;\n\n // When month changes, finalize the previous span and start a new one\n if (monthYear !== currentMonthYear) {\n spans.push({\n month: new Date(Date.UTC(\n dateRange[startOfMonthIndex].getUTCFullYear(),\n dateRange[startOfMonthIndex].getUTCMonth(),\n 1\n )),\n days: i - startOfMonthIndex,\n startIndex: startOfMonthIndex\n });\n currentMonthYear = monthYear;\n startOfMonthIndex = i;\n }\n\n // Last date - finalize the last span\n if (i === dateRange.length - 1) {\n spans.push({\n month: new Date(Date.UTC(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n 1\n )),\n days: i - startOfMonthIndex + 1,\n startIndex: startOfMonthIndex\n });\n }\n }\n\n return spans;\n};\n\n/**\n * Format date as DD.MM (e.g., 25.03 for March 25th)\n * @param date - Date to format\n * @returns Formatted date string in DD.MM format\n */\nexport const formatDateLabel = (date: Date | string): string => {\n const parsed = parseUTCDate(date);\n const day = String(parsed.getUTCDate()).padStart(2, '0');\n const month = String(parsed.getUTCMonth() + 1).padStart(2, '0');\n return `${day}.${month}`;\n};\n","import { Task, TaskDependency, LinkType, ValidationResult, DependencyError } from '../types';\n\n/**\n * Build adjacency list for dependency graph (task -> successors)\n */\nexport function buildAdjacencyList(tasks: Task[]): Map<string, string[]> {\n const taskMap = new Map(tasks.map(t => [t.id, t]));\n const graph = new Map<string, string[]>();\n\n for (const task of tasks) {\n const successors: string[] = [];\n\n // Find all tasks that depend on this task (this task is a predecessor)\n for (const otherTask of tasks) {\n if (otherTask.dependencies) {\n for (const dep of otherTask.dependencies) {\n if (dep.taskId === task.id) {\n successors.push(otherTask.id);\n break;\n }\n }\n }\n }\n\n graph.set(task.id, successors);\n }\n\n return graph;\n}\n\n/**\n * Detect circular dependencies using depth-first search\n */\nexport function detectCycles(tasks: Task[]): { hasCycle: boolean; cyclePath?: string[] } {\n const graph = buildAdjacencyList(tasks);\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const path: string[] = [];\n\n function dfs(taskId: string): boolean {\n if (visiting.has(taskId)) {\n // Found cycle - current task is already in recursion stack\n return true;\n }\n if (visited.has(taskId)) {\n return false;\n }\n\n visiting.add(taskId);\n path.push(taskId);\n\n const successors = graph.get(taskId) || [];\n for (const successor of successors) {\n if (dfs(successor)) {\n return true;\n }\n }\n\n visiting.delete(taskId);\n path.pop();\n visited.add(taskId);\n return false;\n }\n\n for (const task of tasks) {\n if (dfs(task.id)) {\n return { hasCycle: true, cyclePath: [...path] };\n }\n }\n\n return { hasCycle: false };\n}\n\n/**\n * Compute lag (in days) from actual predecessor/successor dates.\n * This is the single source of truth for lag semantics across chips, arrows, and drag.\n *\n * Semantics (lag=0 = natural, gap-free connection):\n * - FS: lag = succStart - predEnd - 1 (adjacent days = 0)\n * - SS: lag = succStart - predStart\n * - FF: lag = succEnd - predEnd\n * - SF: lag = succEnd - predStart + 1 (symmetric to FS)\n */\nexport function computeLagFromDates(\n linkType: LinkType,\n predStart: Date,\n predEnd: Date,\n succStart: Date,\n succEnd: Date\n): number {\n const DAY_MS = 24 * 60 * 60 * 1000;\n const pS = Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate());\n const pE = Date.UTC(predEnd.getUTCFullYear(), predEnd.getUTCMonth(), predEnd.getUTCDate());\n const sS = Date.UTC(succStart.getUTCFullYear(), succStart.getUTCMonth(), succStart.getUTCDate());\n const sE = Date.UTC(succEnd.getUTCFullYear(), succEnd.getUTCMonth(), succEnd.getUTCDate());\n switch (linkType) {\n case 'FS': return Math.round((sS - pE) / DAY_MS) - 1;\n case 'SS': return Math.round((sS - pS) / DAY_MS);\n case 'FF': return Math.round((sE - pE) / DAY_MS);\n case 'SF': return Math.round((sE - pS) / DAY_MS) + 1;\n }\n}\n\n/**\n * Calculate successor date based on predecessor dates, link type, and lag\n *\n * Link type semantics:\n * - FS: Successor start = Predecessor end + lag + 1 day (lag=0 → next day)\n * - SS: Successor start = Predecessor start + lag\n * - FF: Successor end = Predecessor end + lag\n * - SF: Successor end = Predecessor start + lag - 1 day (lag=0 → day before)\n */\nexport function calculateSuccessorDate(\n predecessorStart: Date,\n predecessorEnd: Date,\n linkType: LinkType,\n lag: number = 0\n): Date {\n const DAY_MS = 24 * 60 * 60 * 1000;\n\n switch (linkType) {\n case 'FS':\n // lag=0 → successor starts the day after predecessor ends (inclusive dates)\n return new Date(predecessorEnd.getTime() + (lag + 1) * DAY_MS);\n case 'SS':\n return new Date(predecessorStart.getTime() + lag * DAY_MS);\n case 'FF':\n return new Date(predecessorEnd.getTime() + lag * DAY_MS);\n case 'SF':\n // lag=0 → successor ends the day before predecessor starts (inclusive dates)\n return new Date(predecessorStart.getTime() + (lag - 1) * DAY_MS);\n }\n}\n\n/**\n * Validate all dependencies in the task list\n */\nexport function validateDependencies(tasks: Task[]): ValidationResult {\n const errors: DependencyError[] = [];\n const taskIds = new Set(tasks.map(t => t.id));\n\n // Check for missing predecessor references\n for (const task of tasks) {\n if (task.dependencies) {\n for (const dep of task.dependencies) {\n if (!taskIds.has(dep.taskId)) {\n errors.push({\n type: 'missing-task',\n taskId: task.id,\n message: `Dependency references non-existent task: ${dep.taskId}`,\n relatedTaskIds: [dep.taskId],\n });\n }\n }\n }\n }\n\n // Check for cycles\n const cycleResult = detectCycles(tasks);\n if (cycleResult.hasCycle && cycleResult.cyclePath) {\n errors.push({\n type: 'cycle',\n taskId: cycleResult.cyclePath[0],\n message: 'Circular dependency detected',\n relatedTaskIds: cycleResult.cyclePath,\n });\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Get successor tasks of a dragged task using BFS, filtered by link type(s).\n *\n * Returns tasks in breadth-first order (direct successors first, then their successors).\n * The dragged task itself is NOT included in the returned array.\n *\n * The visited set prevents infinite loops in case of cycles (cycle detection already\n * prevents cycles in valid data, but the guard adds safety during cascade computation).\n *\n * @param draggedTaskId - ID of the task being dragged\n * @param allTasks - All tasks in the chart\n * @param linkTypes - Dependency types to follow (default: ['FS'] preserves Phase 7 behavior)\n */\nexport function getSuccessorChain(\n draggedTaskId: string,\n allTasks: Task[],\n linkTypes: LinkType[] = ['FS']\n): Task[] {\n // Build successor map filtered by requested link types: predecessor -> [successors]\n const successorMap = new Map<string, string[]>();\n for (const task of allTasks) {\n successorMap.set(task.id, []);\n }\n for (const task of allTasks) {\n if (!task.dependencies) continue;\n for (const dep of task.dependencies) {\n if (linkTypes.includes(dep.type)) {\n const list = successorMap.get(dep.taskId) ?? [];\n list.push(task.id);\n successorMap.set(dep.taskId, list);\n }\n }\n }\n\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n const visited = new Set<string>();\n const queue: string[] = [draggedTaskId];\n const chain: Task[] = [];\n visited.add(draggedTaskId); // seed — not added to chain\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const successors = successorMap.get(current) ?? [];\n for (const sid of successors) {\n if (!visited.has(sid)) {\n visited.add(sid);\n const t = taskById.get(sid);\n if (t) {\n chain.push(t);\n queue.push(sid);\n }\n }\n }\n }\n\n return chain; // excludes dragged task\n}\n\n/**\n * Cascade successors by actual link constraints (BFS, constraint-based).\n *\n * Each successor in the chain is positioned using calculateSuccessorDate\n * with the predecessor's NEW dates and the actual lag — not a flat delta.\n *\n * - FS/SS: constraintDate = new start of successor (duration preserved)\n * - FF/SF: constraintDate = new end of successor (duration preserved)\n *\n * Locked tasks break the chain.\n * Also cascades hierarchy children when a parent moves (when parent moves by\n * dependency link, children must move with it to maintain parent-child relationship).\n * Returns only the cascaded successors (not the moved task itself).\n */\nexport function cascadeByLinks(\n movedTaskId: string,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[]\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n // Track each task's updated dates\n const updatedDates = new Map<string, { start: Date; end: Date }>();\n updatedDates.set(movedTaskId, { start: newStart, end: newEnd });\n\n const result: Task[] = [];\n const queue: string[] = [movedTaskId];\n const visited = new Set<string>([movedTaskId]);\n\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n const { start: predStart, end: predEnd } = updatedDates.get(currentId)!;\n\n // First, cascade hierarchy children of the current task if it's a parent\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (visited.has(child.id) || child.locked) continue;\n\n // When a parent moves, its children move by the same delta\n const origStart = new Date(child.startDate as string);\n const origEnd = new Date(child.endDate as string);\n const durationMs = origEnd.getTime() - origStart.getTime();\n\n const parentOrig = taskById.get(currentId)!;\n const parentOrigStart = new Date(parentOrig.startDate as string);\n const parentOrigEnd = new Date(parentOrig.endDate as string);\n\n // Calculate delta from parent's original to new position\n const parentStartDelta = predStart.getTime() - parentOrigStart.getTime();\n const parentEndDelta = predEnd.getTime() - parentOrigEnd.getTime();\n\n const newChildStart = new Date(origStart.getTime() + parentStartDelta);\n const newChildEnd = new Date(origEnd.getTime() + parentEndDelta);\n\n visited.add(child.id);\n updatedDates.set(child.id, { start: newChildStart, end: newChildEnd });\n result.push({\n ...child,\n startDate: newChildStart.toISOString().split('T')[0],\n endDate: newChildEnd.toISOString().split('T')[0],\n });\n queue.push(child.id);\n }\n\n // Then, cascade dependency successors\n for (const task of allTasks) {\n if (visited.has(task.id) || !task.dependencies || task.locked) continue;\n\n for (const dep of task.dependencies) {\n if (dep.taskId !== currentId) continue;\n\n const orig = taskById.get(task.id)!;\n const origStart = new Date(orig.startDate as string);\n const origEnd = new Date(orig.endDate as string);\n const durationMs = origEnd.getTime() - origStart.getTime();\n\n const constraintDate = calculateSuccessorDate(predStart, predEnd, dep.type, dep.lag ?? 0);\n\n let newSuccStart: Date;\n let newSuccEnd: Date;\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n newSuccStart = constraintDate;\n newSuccEnd = new Date(constraintDate.getTime() + durationMs);\n } else {\n // FF or SF: constraintDate is the end date\n newSuccEnd = constraintDate;\n newSuccStart = new Date(constraintDate.getTime() - durationMs);\n }\n\n visited.add(task.id);\n updatedDates.set(task.id, { start: newSuccStart, end: newSuccEnd });\n result.push({\n ...task,\n startDate: newSuccStart.toISOString().split('T')[0],\n endDate: newSuccEnd.toISOString().split('T')[0],\n });\n queue.push(task.id);\n break; // one predecessor per cascade step\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get transitive closure of successors for cascading.\n *\n * Direct successors of the changed task are filtered by firstLevelLinkTypes.\n * Their successors (and so on) are included regardless of link type.\n *\n * Also includes hierarchy children of any parent task in the chain - when a parent\n * moves via dependency cascade, its children must move with it.\n */\nexport function getTransitiveCascadeChain(\n changedTaskId: string,\n allTasks: Task[],\n firstLevelLinkTypes: LinkType[]\n): Task[] {\n const allTypesSuccessorMap = new Map<string, Task[]>();\n for (const task of allTasks) {\n allTypesSuccessorMap.set(task.id, []);\n }\n for (const task of allTasks) {\n if (!task.dependencies) continue;\n for (const dep of task.dependencies) {\n const list = allTypesSuccessorMap.get(dep.taskId) ?? [];\n list.push(task);\n allTypesSuccessorMap.set(dep.taskId, list);\n }\n }\n\n const directChildren = getChildren(changedTaskId, allTasks);\n const directSuccessors = getSuccessorChain(changedTaskId, allTasks, firstLevelLinkTypes);\n const initialChain = [...directChildren, ...directSuccessors].filter((task, index, arr) =>\n arr.findIndex(candidate => candidate.id === task.id) === index\n );\n\n const chain = [...initialChain];\n const visited = new Set<string>([changedTaskId, ...initialChain.map(t => t.id)]);\n const queue = [...initialChain];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n // Add hierarchy children of the current task if it's a parent\n const children = getChildren(current.id, allTasks);\n for (const child of children) {\n if (!visited.has(child.id)) {\n visited.add(child.id);\n chain.push(child);\n queue.push(child);\n }\n }\n\n const successors = allTypesSuccessorMap.get(current.id) ?? [];\n for (const successor of successors) {\n if (!visited.has(successor.id)) {\n visited.add(successor.id);\n chain.push(successor);\n queue.push(successor);\n }\n }\n }\n\n return chain;\n}\n\n/**\n * Recalculate incoming dependency lags after a task's dates change.\n * Used when completing a drag or applying a manual date change.\n */\nexport function recalculateIncomingLags(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[]\n): NonNullable<Task['dependencies']> {\n if (!task.dependencies) return [];\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n return task.dependencies.map(dep => {\n const predecessor = taskById.get(dep.taskId);\n if (!predecessor) return dep;\n\n const predStart = new Date(predecessor.startDate as string);\n const predEnd = new Date(predecessor.endDate as string);\n const lagDays = computeLagFromDates(dep.type, predStart, predEnd, newStartDate, newEndDate);\n return { ...dep, lag: lagDays };\n });\n}\n\n/**\n * Get all dependency edges for rendering\n * Returns array of { predecessorId, successorId, type, lag }\n */\nexport function getAllDependencyEdges(tasks: Task[]): Array<{\n predecessorId: string;\n successorId: string;\n type: LinkType;\n lag: number;\n}> {\n const edges: Array<{ predecessorId: string; successorId: string; type: LinkType; lag: number }> = [];\n\n for (const task of tasks) {\n if (task.dependencies) {\n for (const dep of task.dependencies) {\n edges.push({\n predecessorId: dep.taskId,\n successorId: task.id,\n type: dep.type,\n lag: dep.lag ?? 0,\n });\n }\n }\n }\n\n return edges;\n}\n\n// ============================================================================\n// Hierarchy Utilities (Phase 19)\n// ============================================================================\n\n/**\n * Get all child tasks of a parent task.\n * Returns tasks where task.parentId === parentId.\n */\nexport function getChildren(parentId: string, tasks: Task[]): Task[] {\n return tasks.filter(t => (t as any).parentId === parentId);\n}\n\n/**\n * Check if a task is a parent (has children).\n * Returns true if any task has this task as parentId.\n */\nexport function isTaskParent(taskId: string, tasks: Task[]): boolean {\n return tasks.some(t => (t as any).parentId === taskId);\n}\n\n/**\n * Compute parent task dates from children.\n * Returns { startDate, endDate } where:\n * - startDate = min(children.startDate) or own startDate if no children\n * - endDate = max(children.endDate) or own endDate if no children\n */\nexport function computeParentDates(parentId: string, tasks: Task[]): { startDate: Date; endDate: Date } {\n const children = getChildren(parentId, tasks);\n\n if (children.length === 0) {\n // Empty parent - use own dates or default\n const parent = tasks.find(t => t.id === parentId);\n const start = parent ? new Date(parent.startDate) : new Date();\n const end = parent ? new Date(parent.endDate) : new Date();\n return { startDate: start, endDate: end };\n }\n\n const startDates = children.map(c => new Date(c.startDate));\n const endDates = children.map(c => new Date(c.endDate));\n\n const minTime = Math.min(...startDates.map(d => d.getTime()));\n const maxTime = Math.max(...endDates.map(d => d.getTime()));\n\n return {\n startDate: new Date(minTime),\n endDate: new Date(maxTime),\n };\n}\n\n/**\n * Compute parent task progress from children (weighted average by duration).\n * Returns 0 if no children.\n * Progress is rounded to 1 decimal place.\n */\nexport function computeParentProgress(parentId: string, tasks: Task[]): number {\n const children = getChildren(parentId, tasks);\n\n if (children.length === 0) {\n return 0;\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n let totalWeight = 0;\n let weightedSum = 0;\n\n for (const child of children) {\n const start = new Date(child.startDate).getTime();\n const end = new Date(child.endDate).getTime();\n // Inclusive duration: (end - start + 1 day) / DAY_MS\n const duration = (end - start + DAY_MS) / DAY_MS;\n const progress = (child.progress ?? 0);\n\n totalWeight += duration;\n weightedSum += duration * progress;\n }\n\n if (totalWeight === 0) {\n return 0;\n }\n\n // Round to 1 decimal place\n return Math.round((weightedSum / totalWeight) * 10) / 10;\n}\n\n/**\n * Remove dependencies between two tasks in both directions.\n * When tasks become parent-child, their dependency link becomes meaningless.\n *\n * @param taskId1 - First task ID\n * @param taskId2 - Second task ID\n * @param tasks - All tasks array\n * @returns New tasks array with dependencies between the two tasks removed\n */\nexport function removeDependenciesBetweenTasks(\n taskId1: string,\n taskId2: string,\n tasks: Task[]\n): Task[] {\n return tasks.map(task => {\n if (task.id === taskId1 || task.id === taskId2) {\n if (!task.dependencies) return task;\n const otherTaskId = task.id === taskId1 ? taskId2 : taskId1;\n const filteredDependencies = task.dependencies.filter(dep => dep.taskId !== otherTaskId);\n // Only create new object if dependencies actually changed\n if (filteredDependencies.length === task.dependencies.length) {\n return task;\n }\n return {\n ...task,\n dependencies: filteredDependencies.length > 0 ? filteredDependencies : undefined,\n };\n }\n return task;\n });\n}\n\n/**\n * Find the parent ID of a task.\n * Returns the parentId of the task if found, undefined otherwise.\n *\n * @param taskId - ID of the task to find parent for\n * @param tasks - All tasks array\n * @returns Parent task ID or undefined if task is root or not found\n */\nexport function findParentId(taskId: string, tasks: Task[]): string | undefined {\n const task = tasks.find(t => t.id === taskId);\n return task?.parentId;\n}\n","import type { Task } from '../types';\nimport { computeParentDates, computeParentProgress, isTaskParent } from './dependencyUtils';\n\n/**\n * Build a stable depth-first task order from parentId links.\n * Sibling order follows the order in the input array.\n * Tasks with missing parents are treated as root tasks.\n */\nexport function flattenHierarchy<T extends Task>(tasks: T[]): T[] {\n const byId = new Map(tasks.map((task) => [task.id, task]));\n const byParent = new Map<string | undefined, T[]>();\n\n for (const task of tasks) {\n const normalizedParentId = task.parentId && byId.has(task.parentId)\n ? task.parentId\n : undefined;\n const siblings = byParent.get(normalizedParentId) ?? [];\n siblings.push(task);\n byParent.set(normalizedParentId, siblings);\n }\n\n const result: T[] = [];\n const visited = new Set<string>();\n\n const walk = (parentId?: string) => {\n const children = byParent.get(parentId) ?? [];\n for (const task of children) {\n if (visited.has(task.id)) continue;\n visited.add(task.id);\n result.push(task);\n walk(task.id);\n }\n };\n\n walk(undefined);\n\n for (const task of tasks) {\n if (!visited.has(task.id)) {\n result.push(task);\n }\n }\n\n return result;\n}\n\n/**\n * Normalize hierarchy-aware display fields.\n * Parent task dates and progress are always recomputed from children,\n * taking precedence over any hardcoded parent values from the input.\n */\nexport function normalizeHierarchyTasks<T extends Task>(tasks: T[]): T[] {\n const orderedTasks = flattenHierarchy(tasks).map((task) => ({ ...task })) as T[];\n\n for (const task of [...orderedTasks].reverse()) {\n if (!isTaskParent(task.id, orderedTasks)) continue;\n\n const { startDate, endDate } = computeParentDates(task.id, orderedTasks);\n const progress = computeParentProgress(task.id, orderedTasks);\n const normalizedStartDate = startDate.toISOString().split('T')[0];\n const normalizedEndDate = endDate.toISOString().split('T')[0];\n const parentIndex = orderedTasks.findIndex((candidate) => candidate.id === task.id);\n\n if (parentIndex === -1) continue;\n\n orderedTasks[parentIndex] = {\n ...orderedTasks[parentIndex],\n startDate: normalizedStartDate as T['startDate'],\n endDate: normalizedEndDate as T['endDate'],\n progress: progress as T['progress'],\n };\n }\n\n return orderedTasks;\n}\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { format } from 'date-fns';\nimport { ru } from 'date-fns/locale';\nimport { getMonthSpans } from '../../utils/dateUtils';\nimport type { MonthSpan } from '../../types';\nimport './TimeScaleHeader.css';\n\nexport interface TimeScaleHeaderProps {\n /** Array of dates to display (from getMultiMonthDays) */\n days: Date[];\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of the header row in pixels */\n headerHeight: number;\n}\n\n/**\n * TimeScaleHeader component - displays two-row date headers for the Gantt chart\n *\n * Top row: Month names (Russian, left-aligned) spanning multiple day columns\n * Bottom row: Day numbers (centered) in individual columns\n */\nconst TimeScaleHeader: React.FC<TimeScaleHeaderProps> = ({\n days,\n dayWidth,\n headerHeight,\n}) => {\n // Calculate month spans using the utility from dateUtils\n const monthSpans = useMemo(() => getMonthSpans(days), [days]);\n\n // Split header height evenly between two rows\n const rowHeight = headerHeight / 2;\n\n // Calculate grid template for day row\n const dayGridTemplate = useMemo(\n () => `repeat(${days.length}, ${dayWidth}px)`,\n [days.length, dayWidth]\n );\n\n return (\n <div\n className=\"gantt-tsh-header\"\n style={{ height: `${headerHeight}px` }}\n >\n {/* Month row - top */}\n <div\n className=\"gantt-tsh-monthRow\"\n style={{ height: `${rowHeight}px` }}\n >\n {monthSpans.map((span: MonthSpan, index: number) => (\n <div\n key={`month-${index}`}\n className=\"gantt-tsh-monthCell\"\n style={{ width: `${span.days * dayWidth}px` }}\n >\n {format(span.month, 'LLLL yyyy', { locale: ru }).replace(/^./, (c) => c.toUpperCase())}\n </div>\n ))}\n </div>\n\n {/* Day row - bottom */}\n <div\n className=\"gantt-tsh-dayRow\"\n style={{\n height: `${rowHeight}px`,\n gridTemplateColumns: dayGridTemplate,\n }}\n >\n {days.map((day, index) => {\n const isWeekend = day.getDay() === 0 || day.getDay() === 6;\n const prevDay = days[index - 1];\n const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();\n // Use local date comparison for \"today\" (user's current date)\n const now = new Date();\n const isTodayDate =\n day.getUTCFullYear() === now.getFullYear() &&\n day.getUTCMonth() === now.getMonth() &&\n day.getUTCDate() === now.getDate();\n return (\n <div key={`day-${index}`} className={`gantt-tsh-dayCell ${isWeekend ? 'gantt-tsh-weekendDay' : ''} ${isMonthBoundary ? 'gantt-tsh-monthBoundary' : ''} ${isTodayDate ? 'gantt-tsh-today' : ''}`}>\n <span className=\"gantt-tsh-dayLabel\">{format(day, 'd')}</span>\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default TimeScaleHeader;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { parseUTCDate, formatDateLabel } from '../../utils/dateUtils';\nimport { calculateTaskBar, pixelsToDate } from '../../utils/geometry';\nimport { useTaskDrag } from '../../hooks/useTaskDrag';\nimport { isTaskParent, getChildren } from '../../utils/dependencyUtils';\nimport type { Task } from '../GanttChart';\nimport './TaskRow.css';\n\nexport interface TaskRowProps {\n /** Task data to render */\n task: Task;\n /** Start of the month for positioning calculations */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via drag/resize */\n onChange?: (updatedTask: Task) => void;\n /** Callback when task drag state changes (for rendering guide lines) */\n onDragStateChange?: (state: {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n }) => void;\n /** Index of the task row (used for dependency rendering) */\n rowIndex?: number;\n /** All tasks in the chart (used for dependency validation) */\n allTasks?: Task[];\n /** Whether auto-scheduling is enabled */\n enableAutoSchedule?: boolean;\n /** Whether to disable constraint checking during drag */\n disableConstraints?: boolean;\n /** Position override for cascade preview — when set, overrides both static and drag position */\n overridePosition?: { left: number; width: number };\n /** Called each RAF during cascade drag with override positions for non-dragged chain tasks */\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n /** Called when cascade drag completes; receives all shifted tasks including dragged task */\n onCascade?: (tasks: Task[]) => void;\n /** Optional horizontal divider line - renders above or below the task row */\n divider?: 'top' | 'bottom';\n /** Highlight expired/overdue tasks with red background */\n highlightExpiredTasks?: boolean;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Only re-renders if task properties that affect rendering change.\n *\n * NOTE: onChange is intentionally excluded from this comparison because:\n * 1. The parent (GanttChart) wraps onChange in useCallback for referential stability\n * 2. onChange is only called AFTER drag completes (not during drag)\n * 3. During drag, only the dragged TaskRow re-renders due to its internal drag state\n * 4. Other TaskRows don't need to re-render when one task is dragged\n *\n * NOTE: monthStart MUST be included because task positions are calculated relative to it.\n * When the grid expands (e.g., dragging a task left beyond the boundary), monthStart changes\n * and all tasks need to re-render to update their positions.\n *\n * NOTE: onCascadeProgress and onCascade are excluded from comparison (same pattern as onChange —\n * callbacks excluded from comparison because GanttChart wraps them in useCallback).\n *\n * Excluding onChange prevents re-render storms when dragging tasks with ~100 tasks.\n */\nconst arePropsEqual = (prevProps: TaskRowProps, nextProps: TaskRowProps) => {\n return (\n prevProps.task.id === nextProps.task.id &&\n prevProps.task.name === nextProps.task.name &&\n prevProps.task.startDate === nextProps.task.startDate &&\n prevProps.task.endDate === nextProps.task.endDate &&\n prevProps.task.color === nextProps.task.color &&\n prevProps.task.progress === nextProps.task.progress &&\n prevProps.task.accepted === nextProps.task.accepted &&\n prevProps.monthStart.getTime() === nextProps.monthStart.getTime() &&\n prevProps.dayWidth === nextProps.dayWidth &&\n prevProps.rowHeight === nextProps.rowHeight &&\n prevProps.overridePosition?.left === nextProps.overridePosition?.left &&\n prevProps.overridePosition?.width === nextProps.overridePosition?.width &&\n prevProps.allTasks === nextProps.allTasks &&\n prevProps.disableConstraints === nextProps.disableConstraints &&\n prevProps.task.locked === nextProps.task.locked &&\n prevProps.task.divider === nextProps.task.divider &&\n prevProps.highlightExpiredTasks === nextProps.highlightExpiredTasks\n // onChange, onCascadeProgress, onCascade excluded - see note above\n );\n};\n\n/**\n * TaskRow component - renders a single task row with a task bar\n *\n * Uses React.memo for performance optimization (QL-01).\n * The task bar is positioned absolutely based on start/end dates.\n */\nconst TaskRow: React.FC<TaskRowProps> = React.memo(\n ({ task, monthStart, dayWidth, rowHeight, onChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks }) => {\n // Extract divider from task prop\n const { divider: taskDivider } = task;\n\n // Parse dates as UTC\n const taskStartDate = useMemo(() => parseUTCDate(task.startDate), [task.startDate]);\n const taskEndDate = useMemo(() => parseUTCDate(task.endDate), [task.endDate]);\n\n // Hierarchy: compute isParent and childCount\n const isParent = useMemo(() => {\n return allTasks ? isTaskParent(task.id, allTasks) : false;\n }, [allTasks, task.id]);\n\n const childCount = useMemo(() => {\n return allTasks ? getChildren(task.id, allTasks).length : 0;\n }, [allTasks, task.id]);\n\n // Calculate expiration status for overdue tasks\n const isExpired = useMemo(() => {\n if (!highlightExpiredTasks) return false;\n\n // Create today boundary using LOCAL time so the day boundary matches the user's timezone.\n // Using getUTCFullYear/Month/Date here would shift the day boundary by the UTC offset —\n // e.g. for UTC+3 at 00:30 local, getUTCDate() still returns yesterday.\n const now = new Date();\n const today = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));\n\n // Parse task dates as UTC\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n\n // Task must be incomplete (progress < 100%) to be expired\n const actualProgress = task.progress ?? 0;\n if (actualProgress >= 100) {\n return false; // Completed tasks are never expired\n }\n\n // Simple formula:\n // duration = (end - start + 1) days\n // elapsed = min(today - start, duration) days\n // expected = elapsed / duration * 100\n const msPerDay = 1000 * 60 * 60 * 24;\n const duration = taskEnd.getTime() - taskStart.getTime() + msPerDay;\n const elapsedFromToday = today.getTime() - taskStart.getTime();\n const elapsed = Math.min(Math.max(0, elapsedFromToday), duration);\n const expected = (elapsed / duration) * 100;\n\n return actualProgress < expected;\n }, [task.startDate, task.endDate, task.progress, highlightExpiredTasks]);\n\n // Calculate task bar position and dimensions\n const { left, width } = useMemo(\n () => calculateTaskBar(taskStartDate, taskEndDate, monthStart, dayWidth),\n [taskStartDate, taskEndDate, monthStart, dayWidth]\n );\n\n // Determine task bar color\n const barColor = isExpired\n ? 'var(--gantt-expired-color)'\n : (task.color || 'var(--gantt-task-bar-default-color)');\n\n // Parent bar uses gradient background (handled in CSS), override color here\n const parentBarStyle = isParent ? {} : { backgroundColor: barColor };\n\n // Calculate clamped and rounded progress width\n const progressWidth = useMemo(() => {\n if (task.progress === undefined || task.progress <= 0) return 0;\n return Math.min(100, Math.max(0, Math.round(task.progress)));\n }, [task.progress]);\n\n // Determine progress color based on completion status\n const progressColor = useMemo(() => {\n if (isExpired) {\n // Dark red for expired tasks\n return 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)';\n }\n if (progressWidth === 100) {\n return task.accepted\n ? 'var(--gantt-progress-accepted, #22c55e)' // Green for accepted\n : 'var(--gantt-progress-completed, #fbbf24)'; // Yellow for completed (not accepted)\n }\n // Darker shade using color-mix() with task color or default\n const baseColor = task.color || 'var(--gantt-task-bar-default-color)';\n return `color-mix(in srgb, ${baseColor} 40%, black)`;\n }, [isExpired, progressWidth, task.accepted, task.color]);\n\n // Handle drag end - call onChange with updated task\n const handleDragEnd = (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => {\n const updatedTask: Task = {\n ...task,\n startDate: result.startDate.toISOString(),\n endDate: result.endDate.toISOString(),\n ...(result.updatedDependencies !== undefined && { dependencies: result.updatedDependencies }),\n };\n onChange?.(updatedTask);\n };\n\n // Use drag hook for interactive drag/resize\n const {\n isDragging,\n dragMode,\n currentLeft,\n currentWidth,\n dragHandleProps,\n } = useTaskDrag({\n taskId: task.id,\n initialStartDate: taskStartDate,\n initialEndDate: taskEndDate,\n monthStart,\n dayWidth,\n onDragEnd: handleDragEnd,\n onDragStateChange,\n edgeZoneWidth: 20,\n allTasks,\n rowIndex,\n enableAutoSchedule,\n disableConstraints,\n locked: task.locked,\n onCascadeProgress,\n onCascade,\n });\n\n // Use override position (for cascade preview) with fallback to drag or static position\n const displayLeft = overridePosition?.left ?? (isDragging ? currentLeft : left);\n const displayWidth = overridePosition?.width ?? (isDragging ? currentWidth : width);\n\n // Format date labels for display - update in real-time during drag\n const currentStartDate = isDragging\n ? pixelsToDate(displayLeft, monthStart, dayWidth)\n : taskStartDate;\n const currentEndDate = isDragging\n ? pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth)\n : taskEndDate;\n\n const startDateLabel = formatDateLabel(currentStartDate);\n const endDateLabel = formatDateLabel(currentEndDate);\n\n // Calculate duration in days\n const durationDays = Math.round(\n (currentEndDate.getTime() - currentStartDate.getTime()) / (1000 * 60 * 60 * 24)\n ) + 1;\n\n // Format child count label for parent tasks (Russian plural)\n const getChildCountLabel = (count: number): string => {\n if (count === 1) return '1 задача';\n // For 2, 3, 4 tasks use \"задачи\" (genitive singular)\n // For 5+ tasks use \"задач\" (genitive plural)\n const lastTwoDigits = count % 100;\n const lastDigit = count % 10;\n if (lastTwoDigits >= 11 && lastTwoDigits <= 14) return `${count} задач`;\n if (lastDigit === 1) return `${count} задача`;\n if (lastDigit >= 2 && lastDigit <= 4) return `${count} задачи`;\n return `${count} задач`;\n };\n\n // Determine if progress text fits inside the bar\n // Estimate: duration text (~\"15 д\" = ~30px) + progress text (~\"100%\" = ~30px) + padding (~16px)\n const estimatedTextWidth = durationDays >= 10 ? 76 : 62; // \"15 д 100%\" = ~76px, \"1 д 100%\" = ~62px\n const showProgressInside = progressWidth > 0 && displayWidth > estimatedTextWidth;\n\n return (\n <div\n className=\"gantt-tr-row\"\n style={{ height: `${rowHeight}px` }}\n >\n {taskDivider === 'top' && <div className=\"gantt-tr-divider gantt-tr-divider-top\" />}\n <div className=\"gantt-tr-taskContainer\">\n <div\n data-taskbar\n className={`gantt-tr-taskBar ${isDragging ? 'gantt-tr-dragging' : ''} ${task.locked ? 'gantt-tr-locked' : ''} ${isParent ? 'gantt-tr-parentBar' : ''}`}\n style={{\n left: `${displayLeft}px`,\n width: `${displayWidth}px`,\n ...parentBarStyle,\n height: isParent ? 'var(--gantt-parent-bar-height, 14px)' : 'var(--gantt-task-bar-height)',\n cursor: dragHandleProps.style.cursor,\n userSelect: dragHandleProps.style.userSelect,\n }}\n onMouseDown={dragHandleProps.onMouseDown}\n >\n {progressWidth > 0 && (\n <div\n className=\"gantt-tr-progressBar\"\n style={{\n width: `${progressWidth}%`,\n backgroundColor: progressColor,\n }}\n />\n )}\n {!isParent && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleLeft\" />}\n <span className=\"gantt-tr-taskDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n {progressWidth > 0 && showProgressInside && (\n <span className=\"gantt-tr-progressText\">\n {progressWidth}%\n </span>\n )}\n {!isParent && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleRight\" />}\n </div>\n <div\n className={`gantt-tr-leftLabels ${task.locked ? 'gantt-tr-leftLabels-locked' : ''}`}\n style={{\n left: `${displayLeft}px`\n }}\n >\n <span className=\"gantt-tr-dateLabel gantt-tr-dateLabelLeft\">\n {startDateLabel}–{endDateLabel}\n </span>\n </div>\n {task.locked && (\n <svg\n className=\"gantt-tr-lockIcon\"\n style={{\n position: 'absolute',\n left: `${displayLeft - 16}px`,\n top: '50%',\n transform: 'translateY(-50%)',\n width: '12px',\n height: '12px',\n color: '#444',\n pointerEvents: 'none',\n }}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-label=\"Locked\"\n aria-hidden=\"false\"\n >\n <path d=\"M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM12 17c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z\" />\n </svg>\n )}\n <div\n className=\"gantt-tr-rightLabels\"\n style={{\n left: `${displayLeft + displayWidth}px`,\n }}\n >\n {progressWidth > 0 && !showProgressInside && (\n <span className=\"gantt-tr-externalProgress\">\n {progressWidth}%\n </span>\n )}\n <span className=\"gantt-tr-externalTaskName\">\n {task.name}\n </span>\n </div>\n </div>\n {taskDivider === 'bottom' && <div className=\"gantt-tr-divider gantt-tr-divider-bottom\" />}\n </div>\n );\n },\n arePropsEqual\n);\n\nTaskRow.displayName = 'TaskRow';\n\nexport default TaskRow;\n","/**\n * Calculate day difference in UTC\n */\nconst getUTCDayDifference = (date1: Date, date2: Date): number => {\n const ms1 = Date.UTC(\n date1.getUTCFullYear(),\n date1.getUTCMonth(),\n date1.getUTCDate()\n );\n const ms2 = Date.UTC(\n date2.getUTCFullYear(),\n date2.getUTCMonth(),\n date2.getUTCDate()\n );\n return Math.round((ms1 - ms2) / (1000 * 60 * 60 * 24));\n};\n\n/**\n * Calculate task bar positioning and dimensions\n * @param taskStartDate - Start date of the task\n * @param taskEndDate - End date of the task\n * @param monthStart - Start of the month/visible range\n * @param dayWidth - Width of each day in pixels\n * @returns Object with left position and width in pixels\n */\nexport const calculateTaskBar = (\n taskStartDate: Date,\n taskEndDate: Date,\n monthStart: Date,\n dayWidth: number\n): { left: number; width: number } => {\n const startOffset = getUTCDayDifference(taskStartDate, monthStart);\n const duration = getUTCDayDifference(taskEndDate, taskStartDate);\n\n // Round to avoid sub-pixel rendering issues\n const left = Math.round(startOffset * dayWidth);\n const width = Math.round((duration + 1) * dayWidth); // +1 to include end date\n\n return { left, width };\n};\n\n/**\n * Convert pixel position to date (inverse of calculateTaskBar)\n * @param pixels - Position in pixels (left or width)\n * @param monthStart - Start of the month/visible range\n * @param dayWidth - Width of each day in pixels\n * @returns Date calculated from pixel position\n */\nexport const pixelsToDate = (pixels: number, monthStart: Date, dayWidth: number): Date => {\n const days = Math.round(pixels / dayWidth);\n return new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + days\n ));\n};\n\n/**\n * Calculate total width for month grid\n * @param daysInMonth - Number of days in the month\n * @param dayWidth - Width of each day in pixels\n * @returns Total grid width in pixels\n */\nexport const calculateGridWidth = (daysInMonth: number, dayWidth: number): number => {\n return Math.round(daysInMonth * dayWidth);\n};\n\n/**\n * Detect which edge zone the cursor is in on a task bar\n * @param clientX - Mouse X coordinate relative to viewport\n * @param taskBarElement - The task bar DOM element\n * @param edgeZoneWidth - Width of edge zones in pixels (default: 12px)\n * @returns 'left' if in left edge, 'right' if in right edge, 'move' if in middle\n */\nexport const detectEdgeZone = (\n clientX: number,\n taskBarElement: HTMLElement,\n edgeZoneWidth: number = 12\n): 'left' | 'right' | 'move' => {\n const rect = taskBarElement.getBoundingClientRect();\n const relativeX = Math.round(clientX - rect.left);\n const width = Math.round(rect.width);\n\n // When zones overlap (width <= 2 * edgeZoneWidth), prefer the closer edge\n if (width <= 2 * edgeZoneWidth) {\n // Cursor is in overlapping edge zone, return closer edge\n const distanceToLeft = relativeX;\n const distanceToRight = width - relativeX;\n return distanceToLeft <= distanceToRight ? 'left' : 'right';\n }\n\n // Check left edge zone\n if (relativeX >= 0 && relativeX <= edgeZoneWidth) {\n return 'left';\n }\n\n // Check right edge zone\n if (relativeX >= width - edgeZoneWidth && relativeX <= width) {\n return 'right';\n }\n\n // Middle area - move mode\n return 'move';\n};\n\n/**\n * Get appropriate cursor style for drag position\n * @param position - The drag position (left edge, right edge, or move)\n * @returns CSS cursor string for the position\n */\nexport const getCursorForPosition = (position: 'left' | 'right' | 'move'): string => {\n switch (position) {\n case 'left':\n case 'right':\n return 'ew-resize';\n case 'move':\n return 'grab';\n default:\n return 'default';\n }\n};\n\n/**\n * Calculate grid line positions for a date range\n * @param dateRange - Array of Date objects representing the visible range\n * @param dayWidth - Width of each day column in pixels\n * @returns Array of grid line objects with x position and flags\n */\nexport const calculateGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean; isWeekStart: boolean }> => {\n const lines: Array<{ x: number; isMonthStart: boolean; isWeekStart: boolean }> = [];\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const x = Math.round(i * dayWidth);\n const isMonthStart = i === 0 ? false : date.getUTCDate() === 1;\n const isWeekStart = date.getUTCDay() === 1; // Monday\n\n lines.push({ x, isMonthStart, isWeekStart });\n }\n\n // Add final line at the end of the range\n if (dateRange.length > 0) {\n lines.push({\n x: Math.round(dateRange.length * dayWidth),\n isMonthStart: false,\n isWeekStart: false\n });\n }\n\n return lines;\n};\n\n/**\n * Calculate weekend background blocks for a date range\n * @param dateRange - Array of Date objects representing the visible range\n * @param dayWidth - Width of each day column in pixels\n * @returns Array of weekend block objects with left position and width\n */\nexport const calculateWeekendBlocks = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ left: number; width: number }> => {\n const blocks: Array<{ left: number; width: number }> = [];\n let inWeekend = false;\n let weekendStartIndex = -1;\n\n for (let i = 0; i < dateRange.length; i++) {\n const date = dateRange[i];\n const dayOfWeek = date.getUTCDay();\n const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; // Sunday or Saturday\n\n if (isWeekend && !inWeekend) {\n // Start of a weekend block\n inWeekend = true;\n weekendStartIndex = i;\n } else if (!isWeekend && inWeekend) {\n // End of a weekend block\n inWeekend = false;\n const left = Math.round(weekendStartIndex * dayWidth);\n const width = Math.round((i - weekendStartIndex) * dayWidth);\n blocks.push({ left, width });\n }\n }\n\n // Handle case where range ends on a weekend\n if (inWeekend && weekendStartIndex >= 0) {\n const left = Math.round(weekendStartIndex * dayWidth);\n const width = Math.round((dateRange.length - weekendStartIndex) * dayWidth);\n blocks.push({ left, width });\n }\n\n return blocks;\n};\n\n/**\n * Calculate SVG cubic Bezier curve path for dependency lines\n * @param from - Start point {x, y} (right edge of predecessor)\n * @param to - End point {x, y} (left edge of successor)\n * @returns SVG path string for cubic Bezier curve\n */\nexport const calculateBezierPath = (\n from: { x: number; y: number },\n to: { x: number; y: number }\n): string => {\n // Control points create smooth vertical curve\n // Offset is proportional to vertical distance for natural-looking curves\n const verticalDistance = Math.abs(to.y - from.y);\n const cpOffset = Math.max(verticalDistance * 0.5, 20); // Minimum 20px for same-row connections\n\n // For same-row connections, use arc above the task bars\n if (from.y === to.y) {\n const arcHeight = 20;\n const midX = (from.x + to.x) / 2;\n return `M ${from.x} ${from.y} Q ${midX} ${from.y - arcHeight} ${to.x} ${to.y}`;\n }\n\n // Standard cubic Bezier for multi-row connections\n const cp1x = from.x;\n const cp1y = from.y + (to.y > from.y ? cpOffset : -cpOffset);\n const cp2x = to.x;\n const cp2y = to.y - (to.y > from.y ? cpOffset : -cpOffset);\n\n return `M ${Math.round(from.x)} ${Math.round(from.y)} C ${Math.round(cp1x)} ${Math.round(cp1y)}, ${Math.round(cp2x)} ${Math.round(cp2y)}, ${Math.round(to.x)} ${Math.round(to.y)}`;\n};\n\n/**\n * Calculate SVG path for dependency lines based on link type connection semantics.\n *\n * Connection points per link type:\n * - FS: predecessor RIGHT → successor LEFT (arrow points right, enters left edge)\n * - SS: predecessor LEFT → successor LEFT (arrow points right, enters left edge)\n * - FF: predecessor RIGHT → successor RIGHT (arrow points left, enters right edge)\n * - SF: predecessor LEFT → successor RIGHT (arrow points left, enters right edge)\n *\n * @param from - Start point {x, y}\n * @param to - End point {x, y}\n * @param arrivesFromRight - true for FF and SF (arrow enters right edge of successor)\n */\nexport const calculateDependencyPath = (\n from: { x: number; y: number },\n to: { x: number; y: number },\n arrivesFromRight: boolean\n): string => {\n const fx = Math.round(from.x);\n const fy = Math.round(from.y);\n const tx = Math.round(to.x);\n const ty = Math.round(to.y);\n\n // Same row: straight horizontal line\n if (fy === ty) {\n return `M ${fx} ${fy} H ${tx}`;\n }\n\n const C = 2; // chamfer size\n const goingDown = ty > fy;\n const dirY = goingDown ? 1 : -1;\n\n if (arrivesFromRight) {\n // Arrow arrives at the RIGHT edge of successor (FF, SF).\n // Same chamfer formula as the FS/SS branch: stop C short of tx in the direction of travel,\n // then diagonal to tx, then vertical. The endpoints differ (right edge vs left edge),\n // but the path shape — natural inside-corner chamfer — is identical.\n const goingRight = tx >= fx;\n const dirX = goingRight ? 1 : -1;\n\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n } else {\n // Arrow arrives at the LEFT edge of successor (FS, SS) — same as existing calculateOrthogonalPath\n const goingRight = tx >= fx;\n const dirX = goingRight ? 1 : -1;\n\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n }\n};\n\n/**\n * Calculate SVG Г-shaped (L-shaped) path for FS dependency lines.\n * Goes vertically from the right edge of the predecessor bar, then horizontally\n * to the left edge of the successor bar. Supports negative lag (overlap).\n * @param from - Start point {x, y} (right edge of predecessor, vertical center)\n * @param to - End point {x, y} (left edge of successor, vertical center)\n * @returns SVG path string\n */\nexport const calculateOrthogonalPath = (\n from: { x: number; y: number },\n to: { x: number; y: number }\n): string => {\n const fx = Math.round(from.x);\n const fy = Math.round(from.y);\n const tx = Math.round(to.x);\n const ty = Math.round(to.y);\n\n // Same row: straight horizontal line\n if (fy === ty) {\n return `M ${fx} ${fy} H ${tx}`;\n }\n\n const C = 2; // chamfer size\n const goingDown = ty > fy;\n const goingRight = tx >= fx;\n const dirY = goingDown ? 1 : -1;\n const dirX = goingRight ? 1 : -1;\n\n // Shape: horizontal exit → chamfer → vertical arrival (arrow points down/up)\n if (Math.abs(ty - fy) >= C && Math.abs(tx - fx) >= C) {\n return [\n `M ${fx} ${fy}`,\n `H ${tx - dirX * C}`,\n `L ${tx} ${fy + dirY * C}`,\n `V ${ty}`,\n ].join(' ');\n }\n\n // Sharp corner fallback (very short segments)\n return `M ${fx} ${fy} H ${tx} V ${ty}`;\n};\n","'use client';\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport { detectEdgeZone } from '../utils/geometry';\nimport type { Task, TaskDependency, LinkType } from '../types';\nimport { calculateSuccessorDate, getSuccessorChain, getTransitiveCascadeChain, recalculateIncomingLags, getChildren, isTaskParent, cascadeByLinks } from '../utils/dependencyUtils';\n\n/**\n * Get transitive closure of successors for cascading.\n *\n * For proper cascading in mixed link type chains (e.g., A--FS-->B--SS-->C),\n * we need to include cascaded tasks' successors regardless of link type.\n *\n * The chain is:\n * 1. Direct successors of the dragged task, filtered by firstLevelLinkTypes\n * 2. ALL successors (any type) of those tasks, recursively\n *\n * @param draggedTaskId - ID of the task being dragged\n * @param allTasks - All tasks in the chart\n * @param firstLevelLinkTypes - Link types to use for direct successors\n * @returns Array of tasks in the cascade chain (transitive closure)\n */\n/**\n * Global drag manager that persists across HMR\n *\n * This singleton manages active drag operations at the module level,\n * ensuring that drag state survives React Fast Refresh (HMR).\n *\n * The key insight: When HMR occurs during a drag operation:\n * 1. The component unmounts and its useEffect cleanup removes window listeners\n * 2. The component remounts with fresh refs (isDraggingRef = false)\n * 3. But the user is still holding the mouse button!\n * 4. Without module-level state, the drag operation is orphaned\n *\n * Solution: Store active drag state in module-level singleton and\n * use a global cleanup effect to always handle mouseup/mousemove.\n */\ninterface ActiveDragState {\n taskId: string;\n mode: 'move' | 'resize-left' | 'resize-right';\n startX: number;\n initialLeft: number;\n initialWidth: number;\n currentLeft: number;\n currentWidth: number;\n dayWidth: number;\n monthStart: Date;\n onProgress: (left: number, width: number) => void;\n onComplete: (finalLeft: number, finalWidth: number) => void;\n onCancel: () => void;\n allTasks: Task[];\n disableConstraints?: boolean;\n cascadeChain: Task[]; // FS+SS+FF+SF successors of dragged task (Phase 10: added SF)\n cascadeChainFS: Task[]; // FS-only successors (part of resize-right cascade with FF)\n cascadeChainStart: Task[]; // SS+SF successors (resize-left cascade) - Phase 10: renamed from cascadeChainSS\n cascadeChainEnd: Task[]; // FS+FF successors (resize-right cascade) - Phase 9\n hierarchyChain: Task[]; // Phase 19: children of parent task (for cascade drag)\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n}\n\nlet globalActiveDrag: ActiveDragState | null = null;\nlet globalRafId: number | null = null;\n\n/**\n * Complete the active drag operation\n */\nfunction completeDrag() {\n if (globalRafId !== null) {\n cancelAnimationFrame(globalRafId);\n globalRafId = null;\n }\n\n if (globalActiveDrag) {\n // Clear cascade overrides before completing (avoids stale preview positions)\n globalActiveDrag.onCascadeProgress?.(new Map());\n const { onComplete, currentLeft, currentWidth } = globalActiveDrag;\n globalActiveDrag = null;\n onComplete(currentLeft, currentWidth);\n }\n}\n\n/**\n * Cancel the active drag operation\n */\nfunction cancelDrag() {\n if (globalRafId !== null) {\n cancelAnimationFrame(globalRafId);\n globalRafId = null;\n }\n\n if (globalActiveDrag) {\n const { onCancel } = globalActiveDrag;\n globalActiveDrag = null;\n onCancel();\n }\n}\n\n/**\n * Snap pixel value to grid (day boundaries)\n */\nfunction snapToGrid(pixels: number, dayWidth: number): number {\n return Math.round(pixels / dayWidth) * dayWidth;\n}\n\n/**\n * Check if a task move would violate dependency constraints\n * Only blocks move operations, not resize (per requirements)\n */\nfunction canMoveTask(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[]\n): { allowed: boolean; reason?: string } {\n if (!task.dependencies || task.dependencies.length === 0) {\n return { allowed: true };\n }\n\n // For each predecessor, check if the new position respects the constraint\n for (const dep of task.dependencies) {\n const predecessor = allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n\n const predecessorStart = new Date(predecessor.startDate);\n const predecessorEnd = new Date(predecessor.endDate);\n\n // Calculate expected date based on link type (lag ignored, always 0)\n const expectedDate = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n dep.type,\n 0 // lag not used in calculations\n );\n\n // Check constraint based on link type\n const targetIsStart = dep.type.endsWith('S');\n const targetDate = targetIsStart ? newStartDate : newEndDate;\n\n // Allow move if target date is on or after expected date\n // (give 1-day tolerance for rounding)\n const dayDiff = (targetDate.getTime() - expectedDate.getTime()) / (24 * 60 * 60 * 1000);\n\n if (dayDiff < -1) {\n return {\n allowed: false,\n reason: `Would violate ${dep.type} dependency from \"${predecessor.name}\"`\n };\n }\n }\n\n return { allowed: true };\n}\n\n/**\n * Recalculate lag values for incoming dependencies after drag completion.\n *\n * Lag formulas:\n * - FS: lag = startB - endA (can be negative)\n * - SS: lag = startB - startA (floor at 0)\n * - FF: lag = endB - endA (can be negative)\n * - SF: lag = endB - startA (ceiling at 0)\n */\n/**\n * Global mouse move handler - attached once and persists across HMR\n */\nfunction handleGlobalMouseMove(e: MouseEvent) {\n if (!globalActiveDrag || globalRafId !== null) {\n return;\n }\n\n globalRafId = requestAnimationFrame(() => {\n if (!globalActiveDrag) {\n globalRafId = null;\n return;\n }\n\n const activeDrag = globalActiveDrag;\n\n const { startX, initialLeft, initialWidth, mode, dayWidth, onProgress, allTasks } = activeDrag;\n const deltaX = e.clientX - startX;\n\n let newLeft = initialLeft;\n let newWidth = initialWidth;\n\n switch (mode) {\n case 'move':\n newLeft = snapToGrid(initialLeft + deltaX, dayWidth);\n break;\n case 'resize-left':\n const snappedLeft = snapToGrid(initialLeft + deltaX, dayWidth);\n newLeft = snappedLeft;\n const rightEdge = initialLeft + initialWidth;\n newWidth = Math.max(dayWidth, rightEdge - snappedLeft);\n break;\n case 'resize-right':\n const snappedWidth = snapToGrid(initialWidth + deltaX, dayWidth);\n newWidth = Math.max(dayWidth, snappedWidth);\n break;\n }\n\n // Hard mode: check left-move boundary against predecessor.startDate (Phase 7)\n // Child can move left until its startDate would go before predecessor.startDate\n // Also applies to resize-left: the left edge cannot cross the predecessor's start date\n if ((mode === 'move' || mode === 'resize-left') && allTasks.length > 0 && !activeDrag.disableConstraints) {\n const currentTask = allTasks.find(t => t.id === activeDrag.taskId);\n if (currentTask && currentTask.dependencies && currentTask.dependencies.length > 0) {\n let minAllowedLeft = -Infinity; // in pixels from monthStart; -Infinity means no floor unless a real FS/SS predecessor sets one\n for (const dep of currentTask.dependencies) {\n if (dep.type !== 'FS' && dep.type !== 'SS') continue; // Phase 8: FS and SS\n const predecessor = activeDrag.allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n // Boundary: child.startDate >= predecessor.startDate (allows negative lag)\n const predStart = new Date(predecessor.startDate as string);\n const predStartOffset = Math.round(\n (Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const predStartLeft = Math.round(predStartOffset * activeDrag.dayWidth);\n minAllowedLeft = Math.max(minAllowedLeft, predStartLeft);\n }\n // Clamp: don't let task go left of boundary\n newLeft = Math.max(minAllowedLeft, newLeft);\n }\n // For resize-left, after clamping newLeft the right edge is fixed so newWidth must be recomputed\n if (mode === 'resize-left') {\n const rightEdge = activeDrag.initialLeft + activeDrag.initialWidth;\n newWidth = Math.max(activeDrag.dayWidth, rightEdge - newLeft);\n }\n }\n\n // Phase 10: SF constraint: endB <= startA (lag ceiling at 0)\n // Applies when B is moved right or resized-right\n if ((mode === 'move' || mode === 'resize-right') && allTasks.length > 0 && !activeDrag.disableConstraints) {\n const currentTask = allTasks.find(t => t.id === activeDrag.taskId);\n if (currentTask && currentTask.dependencies && currentTask.dependencies.length > 0) {\n for (const dep of currentTask.dependencies) {\n if (dep.type !== 'SF') continue;\n const predecessor = activeDrag.allTasks.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n const predStart = new Date(predecessor.startDate as string);\n const predStartOffset = Math.round(\n (Date.UTC(predStart.getUTCFullYear(), predStart.getUTCMonth(), predStart.getUTCDate()) -\n Date.UTC(activeDrag.monthStart.getUTCFullYear(), activeDrag.monthStart.getUTCMonth(), activeDrag.monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const predStartLeft = Math.round(predStartOffset * activeDrag.dayWidth);\n\n // SF lag=0 boundary: B's visual end = day before A's start (adjacent = lag 0)\n // B.right (exclusive pixel) = predStartLeft at lag=0\n const sfBoundaryRight = predStartLeft;\n if (mode === 'move') {\n // Move mode: when B would hit startA constraint, stop movement entirely\n const proposedEndRight = newLeft + activeDrag.initialWidth;\n if (proposedEndRight > sfBoundaryRight) {\n newLeft = Math.max(activeDrag.initialLeft, sfBoundaryRight - activeDrag.initialWidth);\n }\n } else {\n // Resize-right mode: clamp width so endB = startA (lag=0)\n const currentEndRight = newLeft + newWidth;\n if (currentEndRight > sfBoundaryRight) {\n newWidth = Math.max(activeDrag.dayWidth, sfBoundaryRight - newLeft);\n }\n }\n }\n }\n }\n\n const draggedTask = allTasks.find(t => t.id === activeDrag.taskId);\n const isParentDrag = draggedTask ? isTaskParent(draggedTask.id, allTasks) : false;\n\n // Phase 9: select chain based on drag mode\n // move: all FS+SS+FF+SF successors follow\n // resize-right: FS+FF successors (endA changes, SS/SF unaffected)\n // resize-left: SS+SF successors only (startA changes, FS/FF unaffected)\n // Phase 10: added SF\n // Phase 19: merge hierarchy chain with dependency chain\n let activeChain =\n mode === 'resize-right' ? activeDrag.cascadeChainEnd : // FS + FF\n mode === 'resize-left' ? activeDrag.cascadeChainStart : // SS + SF\n /* move */ activeDrag.cascadeChain; // FS + SS + FF + SF\n\n // Phase 19: Merge hierarchy chain with dependency chain\n // Both systems work together: unique task IDs to prevent duplicates\n if (activeDrag.hierarchyChain.length > 0) {\n const chainIds = new Set(activeChain.map(t => t.id));\n const hierarchyTasks = activeDrag.hierarchyChain.filter(t => !chainIds.has(t.id));\n activeChain = [...activeChain, ...hierarchyTasks];\n }\n\n // Track which tasks are parents in the hierarchy chain (for special positioning)\n const hierarchyParents = new Set<string>();\n activeDrag.hierarchyChain.forEach(t => {\n if (isTaskParent(t.id, allTasks)) {\n hierarchyParents.add(t.id);\n }\n });\n\n // Parent drags need full constraint-based propagation via descendants, not\n // just direct successors of the parent task itself.\n if (isParentDrag &&\n !activeDrag.disableConstraints &&\n activeDrag.onCascadeProgress) {\n const previewStartDate = new Date(Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate() + Math.round(newLeft / activeDrag.dayWidth)\n ));\n const previewDurationDays = Math.round(newWidth / activeDrag.dayWidth) - 1;\n const previewEndDate = new Date(Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate() + Math.round(newLeft / activeDrag.dayWidth) + previewDurationDays\n ));\n\n const cascadedPreviewTasks = cascadeByLinks(\n activeDrag.taskId,\n previewStartDate,\n previewEndDate,\n allTasks\n );\n\n if (cascadedPreviewTasks.length > 0) {\n const overrides = new Map<string, { left: number; width: number }>();\n\n for (const chainTask of cascadedPreviewTasks) {\n const chainStart = new Date(chainTask.startDate as string);\n const chainEnd = new Date(chainTask.endDate as string);\n const chainStartOffset = Math.round(\n (Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainEndOffset = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(\n activeDrag.monthStart.getUTCFullYear(),\n activeDrag.monthStart.getUTCMonth(),\n activeDrag.monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n\n overrides.set(chainTask.id, {\n left: Math.round(chainStartOffset * activeDrag.dayWidth),\n width: Math.round((chainEndOffset - chainStartOffset + 1) * activeDrag.dayWidth),\n });\n }\n\n activeDrag.onCascadeProgress(overrides);\n }\n // Hard mode cascade: emit position overrides for successor chain members\n } else if ((mode === 'move' || mode === 'resize-right' ||\n (mode === 'resize-left' && activeDrag.cascadeChainStart.length > 0)) &&\n !activeDrag.disableConstraints &&\n activeChain.length > 0 &&\n activeDrag.onCascadeProgress) {\n // For move/resize-left: delta from left (startA shift)\n // For resize-right: delta from width (endA shift, startA fixed)\n const deltaDays = mode === 'resize-right'\n ? Math.round((newWidth - activeDrag.initialWidth) / activeDrag.dayWidth)\n : Math.round((newLeft - activeDrag.initialLeft) / activeDrag.dayWidth);\n const overrides = new Map<string, { left: number; width: number }>();\n const draggedTaskId = activeDrag.taskId;\n const dayWidth = activeDrag.dayWidth;\n const monthStart = activeDrag.monthStart;\n\n for (const chainTask of activeChain) {\n // Phase 11: locked tasks cannot be moved by cascade\n if (chainTask.locked) continue;\n\n const chainStart = new Date(chainTask.startDate as string);\n const chainEnd = new Date(chainTask.endDate as string);\n const chainStartOffset = Math.round(\n (Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate()) -\n Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainEndOffset = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate()\n )) / (24 * 60 * 60 * 1000)\n );\n const chainDuration = Math.round(\n (Date.UTC(chainEnd.getUTCFullYear(), chainEnd.getUTCMonth(), chainEnd.getUTCDate()) -\n Date.UTC(chainStart.getUTCFullYear(), chainStart.getUTCMonth(), chainStart.getUTCDate())\n ) / (24 * 60 * 60 * 1000)\n );\n\n // Phase 9: Check if this chainTask has FF dependency on dragged task\n // For FF tasks, calculate position from end offset (not start offset)\n // This fixes negative lag preview where child starts before parent\n // Phase 10: SF tasks also position from end offset (endB constrained to startA)\n const hasFFDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'FF'\n );\n const hasSFDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'SF'\n );\n\n let chainLeft;\n let chainWidth;\n if (hierarchyParents.has(chainTask.id)) {\n // Phase 19 fix: Parent task in hierarchy chain - compute from all children\n // Parent position = min(children.start) to max(children.end)\n const children = getChildren(chainTask.id, allTasks);\n if (children.length > 0) {\n let minChildStart = Infinity;\n let maxChildEnd = -Infinity;\n\n children.forEach(child => {\n let childStartOffset: number;\n let childEndOffset: number;\n\n // If this child is the dragged task, use current drag position (newLeft)\n if (child.id === draggedTaskId) {\n const currentLeftInDays = Math.round(newLeft / dayWidth);\n const currentWidthInDays = Math.round(newWidth / dayWidth) - 1; // -1 for inclusive\n childStartOffset = currentLeftInDays;\n childEndOffset = currentLeftInDays + currentWidthInDays;\n } else if (activeChain.some(c => c.id === child.id)) {\n // Child is being cascaded (moved by same delta)\n const childStart = new Date(child.startDate as string);\n const childEnd = new Date(child.endDate as string);\n const origStartOffset = Math.round(\n (Date.UTC(childStart.getUTCFullYear(), childStart.getUTCMonth(), childStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const origEndOffset = Math.round(\n (Date.UTC(childEnd.getUTCFullYear(), childEnd.getUTCMonth(), childEnd.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n childStartOffset = origStartOffset + deltaDays;\n childEndOffset = origEndOffset + deltaDays;\n } else {\n // Child not being moved - use original position\n const childStart = new Date(child.startDate as string);\n const childEnd = new Date(child.endDate as string);\n childStartOffset = Math.round(\n (Date.UTC(childStart.getUTCFullYear(), childStart.getUTCMonth(), childStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n childEndOffset = Math.round(\n (Date.UTC(childEnd.getUTCFullYear(), childEnd.getUTCMonth(), childEnd.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n }\n\n minChildStart = Math.min(minChildStart, childStartOffset);\n maxChildEnd = Math.max(maxChildEnd, childEndOffset);\n });\n\n chainLeft = Math.round(minChildStart * dayWidth);\n chainWidth = Math.round((maxChildEnd - minChildStart + 1) * dayWidth);\n } else {\n // No children - use original position\n chainLeft = Math.round(chainStartOffset * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n }\n } else if (hasFFDepOnDragged || hasSFDepOnDragged) {\n // FF/SF: position based on end date shift, then back up by duration\n // This works correctly even when child starts before parent (negative lag)\n // For SF: endB shifts with startA, then back up by duration\n chainLeft = Math.round((chainEndOffset + deltaDays - chainDuration) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n } else if (activeDrag.hierarchyChain.some(h => h.id === chainTask.id)) {\n // Phase 19: Hierarchy chain - children move with parent by same delta\n // Position based on start date shift (same as FS/SS move mode)\n chainLeft = Math.round((chainStartOffset + deltaDays) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n } else {\n // FS/SS: position based on start date shift\n chainLeft = Math.round((chainStartOffset + deltaDays) * dayWidth);\n chainWidth = Math.round((chainDuration + 1) * dayWidth);\n }\n\n // SS lag floor: when A moves left, B follows but chainLeft cannot go below A's new position\n // This keeps lag >= 0 (startB >= startA) during live drag preview\n // Phase 9: Only apply floor to SS tasks, not FF (FF allows negative lag)\n // Phase 10: SF uses end-based positioning, no floor needed\n const hasSSDepOnDragged = chainTask.dependencies?.some(\n dep => dep.taskId === draggedTaskId && dep.type === 'SS'\n );\n if (hasSSDepOnDragged && (mode === 'move' || mode === 'resize-left')) {\n chainLeft = Math.max(chainLeft, newLeft);\n }\n\n overrides.set(chainTask.id, { left: chainLeft, width: chainWidth });\n }\n activeDrag.onCascadeProgress(overrides);\n }\n\n // Update current values in global state for completion\n activeDrag.currentLeft = newLeft;\n activeDrag.currentWidth = newWidth;\n\n onProgress(newLeft, newWidth);\n globalRafId = null;\n });\n}\n\n/**\n * Global mouse up handler - attached once and persists across HMR\n */\nfunction handleGlobalMouseUp() {\n if (globalActiveDrag) {\n completeDrag();\n }\n}\n\n/**\n * Track whether global listeners are attached\n */\nlet globalListenersAttached = false;\n\n/**\n * Ensure global listeners are attached (idempotent)\n */\nfunction ensureGlobalListeners() {\n if (!globalListenersAttached) {\n window.addEventListener('mousemove', handleGlobalMouseMove);\n window.addEventListener('mouseup', handleGlobalMouseUp);\n globalListenersAttached = true;\n }\n}\n\n/**\n * Cleanup global listeners - called when no components are using drag\n * Note: In practice with HMR, we keep these attached for safety\n */\nfunction cleanupGlobalListeners() {\n // We keep global listeners attached to handle orphaned drags after HMR\n // They will be cleaned up when the page is refreshed\n}\n\n/**\n * Options for useTaskDrag hook\n */\nexport interface UseTaskDragOptions {\n /** Unique identifier for the task */\n taskId: string;\n /** Initial start date of the task */\n initialStartDate: Date;\n /** Initial end date of the task */\n initialEndDate: Date;\n /** Start of the visible range (e.g., month start) */\n monthStart: Date;\n /** Width of each day in pixels */\n dayWidth: number;\n /** Callback when drag operation completes */\n onDragEnd?: (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => void;\n /** Callback for drag state changes (for parent components to render guide lines) */\n onDragStateChange?: (state: {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n }) => void;\n /** Width of edge zones for resize detection (default: 12px) */\n edgeZoneWidth?: number;\n /** Array of all tasks for dependency validation */\n allTasks?: Task[];\n /** Row index of this task (for task lookup) */\n rowIndex?: number;\n /** Enable automatic scheduling of dependent tasks */\n enableAutoSchedule?: boolean;\n /** When true, dependency constraint checking is skipped during drag (default: false) */\n disableConstraints?: boolean;\n /** Callback for real-time cascade preview — called each RAF with non-dragged chain member positions */\n onCascadeProgress?: (overrides: Map<string, { left: number; width: number }>) => void;\n /** Callback when cascade completes — receives all shifted tasks including dragged task */\n onCascade?: (tasks: Task[]) => void;\n /** When true, all drag and resize interactions are disabled for this task */\n locked?: boolean;\n}\n\n/**\n * Return value from useTaskDrag hook\n */\nexport interface UseTaskDragReturn {\n /** Whether a drag operation is in progress */\n isDragging: boolean;\n /** Current drag mode (null when not dragging) */\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n /** Current left position in pixels (updated during drag) */\n currentLeft: number;\n /** Current width in pixels (updated during drag) */\n currentWidth: number;\n /** Props to spread on the drag handle element */\n dragHandleProps: {\n onMouseDown: (e: React.MouseEvent) => void;\n style: React.CSSProperties;\n };\n}\n\n/**\n * Custom hook for managing task drag interactions\n *\n * HMR-SAFE: Uses module-level singleton to ensure drag state survives\n * React Fast Refresh. Window event listeners are attached once at module\n * level rather than per component instance.\n */\nexport const useTaskDrag = (options: UseTaskDragOptions): UseTaskDragReturn => {\n const {\n taskId,\n initialStartDate,\n initialEndDate,\n monthStart,\n dayWidth,\n onDragEnd,\n onDragStateChange,\n edgeZoneWidth = 12,\n allTasks = [],\n rowIndex,\n enableAutoSchedule = false,\n disableConstraints = false,\n onCascadeProgress,\n onCascade,\n } = options;\n\n // Track if this hook instance owns the current global drag\n const isOwnerRef = useRef<boolean>(false);\n const locked = options.locked ?? false;\n\n // Display state (triggers re-renders only when needed)\n const [isDragging, setIsDragging] = useState<boolean>(false);\n const [dragMode, setDragMode] = useState<'move' | 'resize-left' | 'resize-right' | null>(null);\n const [currentLeft, setCurrentLeft] = useState<number>(0);\n const [currentWidth, setCurrentWidth] = useState<number>(0);\n\n /**\n * Calculate initial pixel position from dates\n */\n const getInitialPosition = useCallback((): { left: number; width: number } => {\n const getUTCDayDifference = (date1: Date, date2: Date): number => {\n const ms1 = Date.UTC(\n date1.getUTCFullYear(),\n date1.getUTCMonth(),\n date1.getUTCDate()\n );\n const ms2 = Date.UTC(\n date2.getUTCFullYear(),\n date2.getUTCMonth(),\n date2.getUTCDate()\n );\n return Math.round((ms1 - ms2) / (1000 * 60 * 60 * 24));\n };\n\n const startOffset = getUTCDayDifference(initialStartDate, monthStart);\n const duration = getUTCDayDifference(initialEndDate, initialStartDate);\n\n const left = Math.round(startOffset * dayWidth);\n const width = Math.round((duration + 1) * dayWidth); // +1 to include end date\n\n return { left, width };\n }, [initialStartDate, initialEndDate, monthStart, dayWidth]);\n\n /**\n * Initialize position when dates or dayWidth changes.\n * Skipped when this instance owns an active drag to avoid overriding drag state.\n */\n useEffect(() => {\n if (isOwnerRef.current && globalActiveDrag) return;\n const { left, width } = getInitialPosition();\n setCurrentLeft(left);\n setCurrentWidth(width);\n }, [getInitialPosition]);\n\n /**\n * When monthStart changes during an active drag (e.g. a month is prepended),\n * the pixel coordinate origin shifts. Adjust globalActiveDrag so that\n * subsequent move calculations stay in the new coordinate space.\n */\n useEffect(() => {\n if (!isOwnerRef.current || !globalActiveDrag) return;\n const oldMonthStart = globalActiveDrag.monthStart;\n if (oldMonthStart === monthStart) return;\n const daysShift = Math.round(\n (Date.UTC(oldMonthStart.getUTCFullYear(), oldMonthStart.getUTCMonth(), oldMonthStart.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate())) /\n (1000 * 60 * 60 * 24)\n );\n const pixelShift = daysShift * dayWidth;\n globalActiveDrag.initialLeft += pixelShift;\n globalActiveDrag.currentLeft += pixelShift;\n globalActiveDrag.monthStart = monthStart;\n }, [monthStart, dayWidth]);\n\n /**\n * Handle drag progress callback from global manager\n */\n const handleProgress = useCallback((left: number, width: number) => {\n setCurrentLeft(left);\n setCurrentWidth(width);\n\n if (onDragStateChange && isOwnerRef.current) {\n const mode = globalActiveDrag?.mode || null;\n onDragStateChange({\n isDragging: true,\n dragMode: mode,\n left,\n width,\n });\n }\n }, [onDragStateChange]);\n\n /**\n * Handle drag completion from global manager\n */\n const handleComplete = useCallback((finalLeft: number, finalWidth: number) => {\n const wasOwner = isOwnerRef.current;\n isOwnerRef.current = false;\n\n // Calculate new dates from final pixel values\n const dayOffset = Math.round(finalLeft / dayWidth);\n const durationDays = Math.round(finalWidth / dayWidth) - 1; // -1 because width includes end date\n\n const newStartDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n ));\n\n const newEndDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset + durationDays\n ));\n\n // Reset local state\n setIsDragging(false);\n setDragMode(null);\n\n // Notify parent of drag end\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: false,\n dragMode: null,\n left: finalLeft,\n width: finalWidth,\n });\n }\n\n if (wasOwner) {\n if (!disableConstraints && onCascade && allTasks.length > 0) {\n // Hard mode with onCascade: compute cascade and call onCascade\n const draggedTaskData = allTasks.find(t => t.id === taskId);\n const parentDragCascade = draggedTaskData && isTaskParent(taskId, allTasks)\n ? cascadeByLinks(taskId, newStartDate, newEndDate, allTasks)\n : null;\n\n if (parentDragCascade && parentDragCascade.length > 0) {\n onCascade([\n {\n ...(draggedTaskData ?? { id: taskId, name: '', startDate: '', endDate: '' }),\n startDate: newStartDate.toISOString(),\n endDate: newEndDate.toISOString(),\n ...(draggedTaskData?.dependencies && {\n dependencies: recalculateIncomingLags(draggedTaskData, newStartDate, newEndDate, allTasks),\n }),\n },\n ...parentDragCascade,\n ]);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n\n // CHANGE C: Dual-delta logic — compute from both start and end date changes\n // Compute delta from startDate change (correct for move and resize-left)\n const origStartMs = Date.UTC(\n initialStartDate.getUTCFullYear(),\n initialStartDate.getUTCMonth(),\n initialStartDate.getUTCDate()\n );\n const newStartMs = Date.UTC(\n newStartDate.getUTCFullYear(),\n newStartDate.getUTCMonth(),\n newStartDate.getUTCDate()\n );\n const deltaFromStart = Math.round((newStartMs - origStartMs) / (24 * 60 * 60 * 1000));\n\n // Compute delta from endDate change (correct for resize-right)\n const origEndMs = Date.UTC(\n initialEndDate.getUTCFullYear(),\n initialEndDate.getUTCMonth(),\n initialEndDate.getUTCDate()\n );\n const newEndMs = Date.UTC(\n newEndDate.getUTCFullYear(),\n newEndDate.getUTCMonth(),\n newEndDate.getUTCDate()\n );\n const deltaFromEnd = Math.round((newEndMs - origEndMs) / (24 * 60 * 60 * 1000));\n\n // For resize-right: startDate unchanged, use endDate delta (FS successors follow end)\n // For move and resize-left: use startDate delta (SS and FS-move successors follow start)\n // Detect resize-right: startDate didn't change\n const deltaDays = deltaFromStart === 0 ? deltaFromEnd : deltaFromStart;\n\n // CHANGE D: Phase 8: get correct chain for completion based on what changed\n // - resize-right (deltaFromStart === 0): only endDate changed → FS successors follow end\n // - resize-left (deltaFromStart !== 0, deltaFromEnd === 0): only startDate changed →\n // SS successors follow start; FS successors are anchored to predecessor's END which\n // is unchanged, so FS successors must NOT cascade on resize-left\n // - move (deltaFromStart !== 0, deltaFromEnd !== 0): both dates shift equally →\n // both FS and SS successors follow\n //\n // FIX: For proper transitive closure in mixed link type chains (e.g., A--FS-->B--SS-->C),\n // we use getTransitiveCascadeChain which includes cascaded tasks' successors regardless of link type.\n // Phase 9: FF included in resize-right and move chains\n const isResizeLeft = deltaFromStart !== 0 && deltaFromEnd === 0;\n let chainForCompletion = deltaFromStart === 0\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'FF']) // resize-right: FS + FF\n : isResizeLeft\n ? getTransitiveCascadeChain(taskId, allTasks, ['SS', 'SF']) // resize-left: SS + SF\n : getTransitiveCascadeChain(taskId, allTasks, ['FS', 'SS', 'FF', 'SF']); // move: all types\n\n // Phase 19: Merge hierarchy chain with dependency chain\n const currentTask = allTasks.find(t => t.id === taskId);\n if (currentTask && (currentTask as any).parentId) {\n // This is a child task - check if parent is being dragged\n // (Hierarchy chain is built when dragging starts, in handleMouseDown)\n }\n // Add hierarchy chain if this is a parent drag\n const hierarchyChildren = currentTask ? getChildren(taskId, allTasks) : [];\n if (hierarchyChildren.length > 0) {\n const chainIds = new Set(chainForCompletion.map(t => t.id));\n const uniqueHierarchyChildren = hierarchyChildren.filter(t => !chainIds.has(t.id));\n chainForCompletion = [...chainForCompletion, ...uniqueHierarchyChildren];\n }\n\n if (chainForCompletion.length > 0) {\n const cascadedTasks: Task[] = [\n {\n ...(draggedTaskData ?? { id: taskId, name: '', startDate: '', endDate: '' }),\n startDate: newStartDate.toISOString(),\n endDate: newEndDate.toISOString(),\n ...(draggedTaskData?.dependencies && {\n dependencies: recalculateIncomingLags(draggedTaskData, newStartDate, newEndDate, allTasks),\n }),\n },\n ...chainForCompletion\n .filter(chainTask => !chainTask.locked) // Phase 11: skip locked tasks in cascade\n .map(chainTask => {\n const origStart = new Date(chainTask.startDate as string);\n const origEnd = new Date(chainTask.endDate as string);\n const newStart = new Date(Date.UTC(\n origStart.getUTCFullYear(), origStart.getUTCMonth(), origStart.getUTCDate() + deltaDays\n ));\n const newEnd = new Date(Date.UTC(\n origEnd.getUTCFullYear(), origEnd.getUTCMonth(), origEnd.getUTCDate() + deltaDays\n ));\n return { ...chainTask, startDate: newStart.toISOString(), endDate: newEnd.toISOString() };\n }),\n ];\n onCascade(cascadedTasks);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n }\n\n // Soft mode OR hard mode with no FS successors: call onDragEnd\n // Always recalculate lag so hard-mode drags (chain.length===0) also persist the new lag\n if (allTasks.length > 0 && onDragEnd) {\n const currentTaskData = allTasks.find(t => t.id === taskId);\n const updatedDependencies = currentTaskData?.dependencies\n ? recalculateIncomingLags(currentTaskData, newStartDate, newEndDate, allTasks)\n : undefined;\n onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate, updatedDependencies });\n } else if (onDragEnd) {\n onDragEnd({ id: taskId, startDate: newStartDate, endDate: newEndDate });\n }\n }\n }, [dayWidth, monthStart, onDragEnd, onDragStateChange, taskId, disableConstraints, onCascade, allTasks, initialStartDate, initialEndDate]);\n\n /**\n * Handle drag cancellation (e.g., if HMR orphaned the drag)\n */\n const handleCancel = useCallback(() => {\n isOwnerRef.current = false;\n setIsDragging(false);\n setDragMode(null);\n\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: false,\n dragMode: null,\n left: currentLeft,\n width: currentWidth,\n });\n }\n }, [onDragStateChange, currentLeft, currentWidth]);\n\n /**\n * Cleanup on unmount - if this instance owns the drag, cancel it\n */\n useEffect(() => {\n return () => {\n if (isOwnerRef.current && globalActiveDrag) {\n // We're unmounting while owning the drag - cancel it\n cancelDrag();\n }\n };\n }, []);\n\n /**\n * Handle mouse down on drag handle\n */\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n // Phase 11: locked tasks cannot be dragged or resized\n if (locked) return;\n\n const target = e.currentTarget as HTMLElement;\n const edgeZone = detectEdgeZone(e.clientX, target, edgeZoneWidth);\n\n // Determine drag mode from edge zone\n let mode: 'move' | 'resize-left' | 'resize-right' | null = null;\n switch (edgeZone) {\n case 'left':\n mode = 'resize-left';\n break;\n case 'right':\n mode = 'resize-right';\n break;\n case 'move':\n mode = 'move';\n break;\n }\n\n // Phase 19: Parent tasks cannot be resized - their dates are computed from children\n // Force move mode for parent tasks to prevent resize operations\n if (mode === 'resize-left' || mode === 'resize-right') {\n const currentTask = allTasks.find(t => t.id === taskId);\n if (currentTask && isTaskParent(taskId, allTasks)) {\n mode = 'move';\n }\n }\n\n if (!mode) {\n return;\n }\n\n // Get current position from state (this is what we see on screen)\n const initialLeft = currentLeft;\n const initialWidth = currentWidth;\n\n // Mark this instance as the drag owner\n isOwnerRef.current = true;\n\n // Update display state\n setIsDragging(true);\n setDragMode(mode);\n\n // Notify parent of drag start\n if (onDragStateChange) {\n onDragStateChange({\n isDragging: true,\n dragMode: mode,\n left: initialLeft,\n width: initialWidth,\n });\n }\n\n // Ensure global listeners are attached (idempotent)\n ensureGlobalListeners();\n\n // Phase 19: Build hierarchy chain for real-time parent movement\n // When dragging a child: include parent so it moves with children\n // When dragging a parent: include all children so they move with parent\n const currentTask = allTasks.find(t => t.id === taskId);\n let hierarchyChain: Task[] = [];\n\n if (currentTask) {\n const taskParentId = (currentTask as any).parentId;\n if (taskParentId) {\n // Dragging a child - include parent for real-time updates\n const parentTask = allTasks.find(t => t.id === taskParentId);\n if (parentTask) {\n hierarchyChain.push(parentTask);\n }\n } else {\n // Dragging a parent - include all children\n hierarchyChain = getChildren(taskId, allTasks);\n }\n }\n\n // Store drag state in global singleton\n globalActiveDrag = {\n taskId,\n mode,\n startX: e.clientX,\n initialLeft,\n initialWidth,\n currentLeft: initialLeft, // Initially same as initial\n currentWidth: initialWidth, // Initially same as initial\n dayWidth,\n monthStart,\n onProgress: handleProgress,\n onComplete: handleComplete,\n onCancel: handleCancel,\n allTasks,\n disableConstraints,\n cascadeChain: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'SS', 'FF', 'SF']) // all successors, used for move (Phase 10: added SF)\n : [],\n cascadeChainFS: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS']) // FS + transitive, used for resize-right\n : [],\n cascadeChainStart: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['SS', 'SF']) // SS + SF for resize-left cascade (Phase 10: renamed from cascadeChainSS)\n : [],\n cascadeChainEnd: !disableConstraints\n ? getTransitiveCascadeChain(taskId, allTasks, ['FS', 'FF']) // FS + FF for resize-right cascade (Phase 9)\n : [],\n hierarchyChain, // Phase 19: children of parent task\n onCascadeProgress,\n };\n }, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade, locked]);\n\n /**\n * Get cursor style based on current position\n */\n const getCursorStyle = useCallback((): string => {\n if (locked) return 'not-allowed';\n if (isDragging) {\n return 'grabbing';\n }\n return 'grab';\n }, [locked, isDragging]);\n\n return {\n isDragging,\n dragMode,\n currentLeft,\n currentWidth,\n dragHandleProps: {\n onMouseDown: handleMouseDown,\n style: {\n cursor: getCursorStyle(),\n userSelect: 'none',\n } as React.CSSProperties,\n },\n };\n};\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { getDayOffset } from '../../utils/dateUtils';\nimport './TodayIndicator.css';\n\nexport interface TodayIndicatorProps {\n /** Start of the month for positioning calculations */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n}\n\n/**\n * TodayIndicator component - displays a vertical line at the current date\n *\n * Only renders when the current date is within the visible month range.\n * Satisfies REND-04 requirement for visual today indicator.\n */\nconst TodayIndicator: React.FC<TodayIndicatorProps> = ({ monthStart, dayWidth }) => {\n // Use local date for \"today\" (not UTC) - user's current date matters\n const today = new Date();\n const todayLocal = new Date(Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate()\n ));\n\n // Calculate position based on offset from monthStart\n // The parent GanttChart component handles the date range check via todayInRange\n const position = useMemo(() => {\n const offset = getDayOffset(todayLocal, monthStart);\n return Math.round(offset * dayWidth);\n }, [monthStart, dayWidth, todayLocal]);\n\n // Allow negative positions (today before monthStart) - parent handles visibility\n if (isNaN(position)) {\n return null;\n }\n\n return (\n <div\n className=\"gantt-ti-indicator\"\n style={{\n left: `${position}px`,\n width: 'var(--gantt-today-indicator-width)',\n backgroundColor: 'var(--gantt-today-indicator-color)',\n }}\n aria-label=\"Today\"\n />\n );\n};\n\nexport default TodayIndicator;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { calculateGridLines, calculateWeekendBlocks } from '../../utils/geometry';\nimport type { GridLine } from '../../types';\nimport './GridBackground.css';\n\nexport interface GridBackgroundProps {\n /** Array of dates to display (from getMultiMonthDays) */\n dateRange: Date[];\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Total height of the grid area in pixels */\n totalHeight: number;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Re-renders when dateRange length, dayWidth, or totalHeight change.\n * Returns true (skip re-render) only when all three are unchanged.\n */\nconst arePropsEqual = (prevProps: GridBackgroundProps, nextProps: GridBackgroundProps) => {\n return (\n prevProps.dayWidth === nextProps.dayWidth &&\n prevProps.dateRange.length === nextProps.dateRange.length &&\n prevProps.totalHeight === nextProps.totalHeight // skip re-render only when totalHeight unchanged\n );\n};\n\n/**\n * GridBackground component - renders vertical grid lines and weekend background highlighting\n *\n * This component provides the visual grid structure that runs behind task rows.\n * It separates grid rendering from task rendering for better performance and cleaner code.\n *\n * Features:\n * - Vertical grid lines at month/week/day boundaries\n * - Pink background highlighting for weekend days\n * - React.memo optimization for performance\n * - Pointer events disabled (clicks pass through to tasks)\n */\nconst GridBackground: React.FC<GridBackgroundProps> = React.memo(\n ({ dateRange, dayWidth, totalHeight }) => {\n // Calculate grid line positions\n const gridLines = useMemo<GridLine[]>(() => {\n return calculateGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth]);\n\n // Calculate weekend background blocks\n const weekendBlocks = useMemo(() => {\n return calculateWeekendBlocks(dateRange, dayWidth);\n }, [dateRange, dayWidth]);\n\n // Calculate total grid width\n const gridWidth = useMemo(() => {\n return Math.round(dateRange.length * dayWidth);\n }, [dateRange.length, dayWidth]);\n\n return (\n <div\n className=\"gantt-gb-gridBackground\"\n style={{\n width: `${gridWidth}px`,\n height: `${totalHeight}px`,\n }}\n >\n {/* Weekend backgrounds (rendered first, behind lines) */}\n {weekendBlocks.map((block, index) => (\n <div\n key={`weekend-${index}`}\n className=\"gantt-gb-weekendBlock\"\n style={{\n left: `${block.left}px`,\n width: `${block.width}px`,\n }}\n />\n ))}\n\n {/* Vertical grid lines */}\n {gridLines.map((line, index) => {\n // Determine line type class based on flags\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : line.isWeekStart\n ? 'gantt-gb-weekSeparator'\n : 'gantt-gb-dayLine';\n\n return (\n <div\n key={`gridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{\n left: `${line.x}px`,\n }}\n />\n );\n })}\n </div>\n );\n },\n arePropsEqual\n);\n\nGridBackground.displayName = 'GridBackground';\n\nexport default GridBackground;\n","'use client';\n\nimport React from 'react';\nimport './DragGuideLines.css';\n\nexport interface DragGuideLinesProps {\n isDragging: boolean;\n dragMode: 'move' | 'resize-left' | 'resize-right' | null;\n left: number;\n width: number;\n totalHeight: number;\n}\n\nconst DragGuideLines: React.FC<DragGuideLinesProps> = ({\n isDragging,\n dragMode,\n left,\n width,\n totalHeight,\n}) => {\n if (!isDragging || !dragMode) {\n return null;\n }\n\n // Determine which lines to show based on drag mode\n const showLeftLine = dragMode === 'move' || dragMode === 'resize-left';\n const showRightLine = dragMode === 'move' || dragMode === 'resize-right';\n\n return (\n <>\n {showLeftLine && (\n <div\n className=\"gantt-dgl-guideLine\"\n style={{\n left: `${left}px`,\n height: `${totalHeight}px`,\n }}\n />\n )}\n {showRightLine && (\n <div\n className=\"gantt-dgl-guideLine\"\n style={{\n left: `${left + width}px`,\n height: `${totalHeight}px`,\n }}\n />\n )}\n </>\n );\n};\n\nexport default DragGuideLines;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { Task } from '../../types';\nimport { calculateTaskBar, calculateDependencyPath, pixelsToDate } from '../../utils/geometry';\nimport { getAllDependencyEdges, detectCycles, computeLagFromDates } from '../../utils/dependencyUtils';\nimport type { LinkType } from '../../types';\nimport './DependencyLines.css';\n\n/**\n * Calculate effective lag based on current task pixel positions.\n * Delegates to computeLagFromDates for consistent semantics.\n */\nfunction calculateEffectiveLag(\n edge: { type: string },\n predPosition: { left: number; right: number },\n succPosition: { left: number; right: number },\n monthStart: Date,\n dayWidth: number\n): number {\n const predStart = pixelsToDate(predPosition.left, monthStart, dayWidth);\n const predEnd = pixelsToDate(predPosition.right - dayWidth, monthStart, dayWidth);\n const succStart = pixelsToDate(succPosition.left, monthStart, dayWidth);\n const succEnd = pixelsToDate(succPosition.right - dayWidth, monthStart, dayWidth);\n return computeLagFromDates(edge.type as LinkType, predStart, predEnd, succStart, succEnd);\n}\n\n/**\n * Check if a task is hidden inside a collapsed parent.\n */\nfunction isTaskHidden(taskId: string, collapsedParentIds: Set<string>, taskMap: Map<string, Task>): boolean {\n const task = taskMap.get(taskId);\n if (!task || !task.parentId) return false;\n return collapsedParentIds.has(task.parentId);\n}\n\n/**\n * Find the nearest visible ancestor of a hidden task.\n * Returns the ancestor task or null if the task is visible.\n */\nfunction findVisibleAncestor(\n task: Task,\n collapsedParentIds: Set<string>,\n taskMap: Map<string, Task>\n): Task | null {\n if (!task.parentId) return null;\n if (collapsedParentIds.has(task.parentId)) {\n const parent = taskMap.get(task.parentId);\n if (!parent) return null;\n // Check if parent is also hidden\n if (parent.parentId && collapsedParentIds.has(parent.parentId)) {\n return findVisibleAncestor(parent, collapsedParentIds, taskMap);\n }\n return parent;\n }\n return null;\n}\n\n/**\n * Check if two tasks share the same collapsed parent ancestor.\n * If both predecessor and successor are hidden inside the same parent,\n * the dependency line should NOT be rendered (it's internal to the collapsed group).\n */\nfunction areBothHiddenInSameParent(\n predecessorId: string,\n successorId: string,\n collapsedParentIds: Set<string>,\n taskMap: Map<string, Task>\n): boolean {\n const predTask = taskMap.get(predecessorId);\n const succTask = taskMap.get(successorId);\n\n if (!predTask || !succTask) return false;\n\n // Both must have parentIds\n if (!predTask.parentId || !succTask.parentId) return false;\n\n // Find the visible ancestor (collapsed parent) for each\n const predVisibleAncestor = findVisibleAncestor(predTask, collapsedParentIds, taskMap);\n const succVisibleAncestor = findVisibleAncestor(succTask, collapsedParentIds, taskMap);\n\n // Both must be hidden (have visible ancestors)\n if (!predVisibleAncestor || !succVisibleAncestor) return false;\n\n // Check if they share the same collapsed parent\n return predVisibleAncestor.id === succVisibleAncestor.id;\n}\n\nexport interface DependencyLinesProps {\n /** Visible tasks only (for row calculation) */\n tasks: Task[];\n /** All tasks including hidden children (for virtual position calculation) */\n allTasks?: Task[];\n /** Set of collapsed parent IDs */\n collapsedParentIds?: Set<string>;\n /** Start of the visible range (e.g., month start) */\n monthStart: Date;\n /** Width of each day column in pixels */\n dayWidth: number;\n /** Height of each task row in pixels */\n rowHeight: number;\n /** Total width of the grid in pixels */\n gridWidth: number;\n /** Real-time pixel overrides for task positions during drag (taskId -> {left, width}) */\n dragOverrides?: Map<string, { left: number; width: number }>;\n /** Currently selected dep chip — highlights the matching arrow in red */\n selectedDep?: { predecessorId: string; successorId: string; linkType: string } | null;\n}\n\n/**\n * SVG overlay component rendering dependency lines as orthogonal paths with rounded corners\n *\n * Lines connect from the right edge of predecessor tasks to the left edge\n * of successor tasks using horizontal/vertical lines with arc rounded corners.\n * Circular dependencies are highlighted in red.\n *\n * Virtual dependency links: When a task is hidden inside a collapsed parent,\n * its dependency lines render at \"virtual positions\" using the parent's row.\n * These virtual lines are styled with dashed strokes to indicate the hidden status.\n *\n * Performance: Uses React.memo to prevent re-renders when dependencies haven't changed.\n */\nexport const DependencyLines: React.FC<DependencyLinesProps> = React.memo(({\n tasks,\n allTasks,\n collapsedParentIds = new Set(),\n monthStart,\n dayWidth,\n rowHeight,\n gridWidth,\n dragOverrides,\n selectedDep,\n}) => {\n // Use allTasks for virtual position calculation if provided, otherwise use tasks\n const tasksForPositions = allTasks ?? tasks;\n\n // Create a lookup map for task positions and their indices\n const { taskPositions, taskIndices, hiddenTaskIds } = useMemo(() => {\n const positions = new Map<string, { left: number; right: number; rowTop: number; isVirtual: boolean }>();\n const indices = new Map<string, number>();\n const hidden = new Set<string>();\n const taskMap = new Map(tasksForPositions.map(t => [t.id, t]));\n const visibleTaskMap = new Map(tasks.map(t => [t.id, t]));\n\n // First pass: Calculate positions for visible tasks (existing logic)\n tasks.forEach((task, index) => {\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n\n // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const resolvedLeft = override?.left ?? computed.left;\n const resolvedWidth = override?.width ?? computed.width;\n\n indices.set(task.id, index);\n positions.set(task.id, {\n left: resolvedLeft,\n right: resolvedLeft + resolvedWidth,\n rowTop: index * rowHeight,\n isVirtual: false,\n });\n });\n\n // Second pass: Calculate virtual positions for hidden tasks\n if (allTasks && collapsedParentIds.size > 0) {\n for (const task of allTasks) {\n // Skip if already processed (visible task)\n if (positions.has(task.id)) continue;\n\n // Check if task is hidden inside a collapsed parent\n if (!isTaskHidden(task.id, collapsedParentIds, taskMap)) continue;\n\n hidden.add(task.id);\n\n // Find the visible ancestor (collapsed parent)\n const visibleAncestor = findVisibleAncestor(task, collapsedParentIds, taskMap);\n if (!visibleAncestor) continue;\n\n // Get the ancestor's row position\n const ancestorPosition = positions.get(visibleAncestor.id);\n if (!ancestorPosition) continue;\n\n // Calculate horizontal position from task's dates\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n const computed = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n\n // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const resolvedLeft = override?.left ?? computed.left;\n const resolvedWidth = override?.width ?? computed.width;\n\n // Store virtual position using ancestor's rowTop\n positions.set(task.id, {\n left: resolvedLeft,\n right: resolvedLeft + resolvedWidth,\n rowTop: ancestorPosition.rowTop,\n isVirtual: true,\n });\n }\n }\n\n return { taskPositions: positions, taskIndices: indices, hiddenTaskIds: hidden };\n }, [tasks, tasksForPositions, allTasks, collapsedParentIds, monthStart, dayWidth, rowHeight, dragOverrides]);\n\n // Detect cycles for highlighting (use allTasks for accurate cycle detection)\n const cycleInfo = useMemo(() => {\n const tasksForCycleDetection = allTasks ?? tasks;\n const result = detectCycles(tasksForCycleDetection);\n const cycleTaskIds = new Set(result.cyclePath || []);\n return cycleTaskIds;\n }, [tasks, allTasks]);\n\n // Calculate all dependency line paths (use allTasks if available)\n const lines = useMemo(() => {\n const tasksForEdges = allTasks ?? tasks;\n const edges = getAllDependencyEdges(tasksForEdges);\n const lines: Array<{\n id: string;\n path: string;\n hasCycle: boolean;\n lag: number;\n fromX: number;\n toX: number;\n fromY: number;\n reverseOrder: boolean;\n isVirtual: boolean;\n }> = [];\n\n for (const edge of edges) {\n const predecessor = taskPositions.get(edge.predecessorId);\n const successor = taskPositions.get(edge.successorId);\n const predecessorIndex = taskIndices.get(edge.predecessorId);\n const successorIndex = taskIndices.get(edge.successorId);\n\n if (!predecessor || !successor) {\n continue; // Skip if task not found (shouldn't happen with validation)\n }\n\n // Check if both tasks are hidden inside the same collapsed parent\n // If so, skip rendering this line (it's internal to the collapsed group)\n if (allTasks && collapsedParentIds.size > 0) {\n const taskMap = new Map(allTasks.map(t => [t.id, t]));\n if (areBothHiddenInSameParent(edge.predecessorId, edge.successorId, collapsedParentIds, taskMap)) {\n continue;\n }\n }\n\n // Check if either endpoint is virtual (hidden task)\n const isVirtual = predecessor.isVirtual || successor.isVirtual;\n\n // Determine if tasks are in reverse order (predecessor appears below successor)\n // For virtual tasks, use the predecessor's rowTop for comparison\n let reverseOrder = false;\n if (predecessorIndex !== undefined && successorIndex !== undefined) {\n reverseOrder = predecessorIndex > successorIndex;\n } else {\n // One or both are virtual - use rowTop for comparison\n reverseOrder = predecessor.rowTop > successor.rowTop;\n }\n\n // Calculate direction-specific Y coordinates\n let fromY: number;\n let toY: number;\n\n if (reverseOrder) {\n // Arrow goes UP: exit from top of parent bar, enter at bottom of child bar\n fromY = predecessor.rowTop + 10; // 8px from top of parent bar\n toY = successor.rowTop + rowHeight - 6; // 8px from bottom of child bar\n } else {\n // Arrow goes DOWN: exit from bottom of parent bar, enter at top of child bar\n fromY = predecessor.rowTop + rowHeight - 10; // 8px from bottom of parent bar\n toY = successor.rowTop + 6; // 8px from top of child bar\n }\n\n // Determine connection points based on link type:\n // FS: right → left\n // SS: left → left\n // FF: right → right\n // SF: left → right\n const fromX = (edge.type === 'SS' || edge.type === 'SF')\n ? predecessor.left\n : predecessor.right;\n\n const toX = (edge.type === 'FF' || edge.type === 'SF')\n ? successor.right\n : successor.left;\n\n const arrivesFromRight = edge.type === 'FF' || edge.type === 'SF';\n\n const from = { x: fromX, y: fromY };\n const to = { x: toX, y: toY };\n\n const path = calculateDependencyPath(from, to, arrivesFromRight);\n\n // Check if this edge is part of a cycle\n const hasCycle = cycleInfo.has(edge.predecessorId) || cycleInfo.has(edge.successorId);\n\n // Calculate effective lag from actual positions (always, not just during drag)\n const lag = calculateEffectiveLag(edge, predecessor, successor, monthStart, dayWidth);\n\n lines.push({\n id: `${edge.predecessorId}-${edge.successorId}-${edge.type}`,\n path,\n hasCycle,\n lag,\n fromX,\n toX,\n fromY,\n reverseOrder,\n isVirtual,\n });\n }\n\n return lines;\n }, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, monthStart, dayWidth, dragOverrides]);\n\n // Calculate SVG height based on visible tasks (not all tasks)\n const svgHeight = tasks.length * rowHeight;\n\n return (\n <svg\n className=\"gantt-dependencies-svg\"\n width={gridWidth}\n height={svgHeight}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n {/* Arrow marker for dependency lines */}\n <marker\n id=\"arrowhead\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"var(--gantt-dependency-line-color, #666666)\"\n />\n </marker>\n\n {/* Red arrow marker for circular dependencies */}\n <marker\n id=\"arrowhead-cycle\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"var(--gantt-dependency-cycle-color, #ef4444)\"\n />\n </marker>\n\n {/* Red arrow marker for selected dependency */}\n <marker\n id=\"arrowhead-selected\"\n markerWidth=\"8\"\n markerHeight=\"6\"\n markerUnits=\"userSpaceOnUse\"\n refX=\"7\"\n refY=\"3\"\n orient=\"auto\"\n >\n <polygon\n points=\"0 0, 8 3, 0 6\"\n fill=\"#ef4444\"\n />\n </marker>\n </defs>\n\n {lines.map(({ id, path, hasCycle, lag, fromX, toX, fromY, reverseOrder, isVirtual }) => {\n const isSelected =\n selectedDep != null &&\n id === `${selectedDep.predecessorId}-${selectedDep.successorId}-${selectedDep.linkType}`;\n\n let pathClassName = 'gantt-dependency-path';\n if (isSelected) pathClassName += ' gantt-dependency-selected';\n else if (hasCycle) pathClassName += ' gantt-dependency-cycle';\n if (isVirtual && !isSelected) pathClassName += ' gantt-dependency-virtual';\n\n let markerEnd: string;\n if (isSelected) markerEnd = 'url(#arrowhead-selected)';\n else if (hasCycle) markerEnd = 'url(#arrowhead-cycle)';\n else markerEnd = 'url(#arrowhead)';\n\n const lagColor = isSelected\n ? '#ef4444'\n : hasCycle\n ? 'var(--gantt-dependency-cycle-color, #ef4444)'\n : 'var(--gantt-dependency-line-color, #666666)';\n\n return (\n <React.Fragment key={id}>\n <path\n d={path}\n className={pathClassName}\n markerEnd={markerEnd}\n />\n {lag !== 0 && (\n <text\n className=\"gantt-dependency-lag-label\"\n x={lag < 0 ? toX + 14 : toX - 14}\n y={reverseOrder ? fromY - 4 : fromY + 12}\n textAnchor=\"middle\"\n fontSize=\"10\"\n fill={lagColor}\n >\n {lag > 0 ? `+${lag}` : `${lag}`}\n </text>\n )}\n </React.Fragment>\n );\n })}\n </svg>\n );\n});\n\nDependencyLines.displayName = 'DependencyLines';\n\nexport default DependencyLines;\n","'use client';\n\nimport React, { useMemo, useCallback, useState, useEffect, useRef } from 'react';\nimport type { Task, TaskDependency } from '../GanttChart';\nimport type { LinkType } from '../../types';\nimport { validateDependencies, calculateSuccessorDate, isTaskParent } from '../../utils/dependencyUtils';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/Popover';\nimport { TaskListRow } from './TaskListRow';\nimport { NewTaskRow } from './NewTaskRow';\nimport { LINK_TYPE_ICONS, LINK_TYPE_LABELS } from './DepIcons';\nimport './TaskList.css';\n\nexport { LINK_TYPE_ICONS };\n\nconst LINK_TYPE_ORDER: LinkType[] = ['FS', 'SS', 'FF', 'SF'];\n\nexport interface TaskListProps {\n /** Array of tasks to display */\n tasks: Task[];\n /** Height of each row in pixels (must match Gantt chart's rowHeight) */\n rowHeight: number;\n /** Height of the header row in pixels (must match Gantt chart's headerHeight) */\n headerHeight: number;\n /** Width of the task list overlay in pixels (default: 400) */\n taskListWidth?: number;\n /** Callback when task is modified via inline edit */\n onTaskChange?: (task: Task) => void;\n /** ID of currently selected task */\n selectedTaskId?: string;\n /** Callback when task row is clicked */\n onTaskSelect?: (taskId: string | null) => void;\n /** Show or hide the task list (default: true) */\n show?: boolean;\n /** Disable task name editing in the task list (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing (hides +, ×, and type menu; read-only column) (default: false) */\n disableDependencyEditing?: boolean;\n /** Callback to scroll the chart grid to a task (wired to № cell click) */\n onScrollToTask?: (taskId: string) => void;\n /** Callback when selected chip changes (used by GanttChart to highlight the corresponding arrow) */\n onSelectedChipChange?: (chip: { successorId: string; predecessorId: string; linkType: string } | null) => void;\n /** Callback when a new task is added (called with full Task object including generated id) */\n onAdd?: (task: Task) => void;\n /** Callback when a task is deleted (called with taskId) */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted after a specific task */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void;\n /** ID of task that should enter edit mode on mount (for auto-edit after insert) */\n editingTaskId?: string | null;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n /** Set of collapsed parent task IDs */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked */\n onToggleCollapse?: (parentId: string) => void;\n /** Callback when task is promoted (parentId removed) */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when task is demoted (parentId set to previous task) */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n}\n\n/**\n * TaskList component - displays tasks in a table format as an overlay\n *\n * Renders a table with columns: № (number), Name, Start Date, End Date, Dependencies\n * Uses position: sticky for synchronized vertical scrolling with the chart.\n */\nexport const TaskList: React.FC<TaskListProps> = ({\n tasks,\n rowHeight,\n headerHeight,\n taskListWidth = 542,\n onTaskChange,\n selectedTaskId,\n onTaskSelect,\n show = true,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n onScrollToTask,\n onSelectedChipChange,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n editingTaskId: propEditingTaskId,\n enableAddTask = true,\n collapsedParentIds: externalCollapsedParentIds,\n onToggleCollapse: externalOnToggleCollapse,\n onPromoteTask,\n onDemoteTask,\n}) => {\n // Hierarchy state: collapsed parent IDs (uncontrolled mode - internal state)\n const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState<Set<string>>(new Set());\n\n // Use external collapsedParentIds if provided (controlled mode), otherwise use internal state\n const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;\n\n // Use external onToggleCollapse if provided (controlled mode), otherwise use internal handler\n const handleToggleCollapse = externalOnToggleCollapse ?? useCallback((parentId: string) => {\n setInternalCollapsedParentIds(prev => {\n const next = new Set(prev);\n if (next.has(parentId)) {\n next.delete(parentId);\n } else {\n next.add(parentId);\n }\n return next;\n });\n }, []);\n\n const orderedTasks = useMemo(() => normalizeHierarchyTasks(tasks), [tasks]);\n\n // Filter tasks to hide children of collapsed parents\n const visibleTasks = useMemo(() => {\n return orderedTasks.filter(task => {\n // Root-level tasks (no parentId) are always visible\n if (!task.parentId) return true;\n // Child tasks are visible only if their parent is not collapsed\n const parentCollapsed = collapsedParentIds.has(task.parentId);\n return !parentCollapsed;\n });\n }, [orderedTasks, collapsedParentIds]);\n\n const totalHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.length, rowHeight]\n );\n\n const handleRowClick = useCallback((taskId: string) => {\n onTaskSelect?.(taskId);\n }, [onTaskSelect]);\n\n // Dependency state\n const [activeLinkType, setActiveLinkType] = useState<LinkType>('FS');\n const [selectingPredecessorFor, setSelectingPredecessorFor] = useState<string | null>(null);\n const [typeMenuOpen, setTypeMenuOpen] = useState(false);\n const [cycleError, setCycleError] = useState(false);\n const overlayRef = useRef<HTMLDivElement>(null);\n\n // Selected chip state: clicking a chip on a successor row selects it,\n // causing the predecessor row to show a \"Удалить\" button\n const [selectedChip, setSelectedChip] = useState<{\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null>(null);\n\n const handleChipSelect = useCallback((chip: {\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null) => {\n setSelectedChip(chip);\n onSelectedChipChange?.(chip);\n }, [onSelectedChipChange]);\n\n // Escape / outside-click cancel for picker mode and chip selection\n useEffect(() => {\n if (!selectingPredecessorFor && !selectedChip) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n }\n };\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as Element;\n if (overlayRef.current?.contains(target)) return;\n // Don't clear when clicking inside a floating portal (popover, date picker, etc.)\n if (target.closest?.('.gantt-popover')) return;\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n };\n document.addEventListener('keydown', handleKeyDown);\n document.addEventListener('mousedown', handleMouseDown, true);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleMouseDown, true);\n };\n }, [selectingPredecessorFor, selectedChip, onSelectedChipChange]);\n\n const handleAddDependency = useCallback((\n successorTaskId: string,\n predecessorTaskId: string,\n linkType: LinkType\n ) => {\n // Guard: no self-links\n if (successorTaskId === predecessorTaskId) return;\n\n // Guard: no duplicate (same taskId + type)\n const successor = tasks.find(t => t.id === successorTaskId);\n if (!successor) return;\n const alreadyExists = (successor.dependencies ?? []).some(\n d => d.taskId === predecessorTaskId && d.type === linkType\n );\n if (alreadyExists) {\n setSelectingPredecessorFor(null);\n return;\n }\n\n // Build hypothetical tasks array to validate for cycles\n const newDep: TaskDependency = { taskId: predecessorTaskId, type: linkType, lag: 0 };\n const hypothetical = tasks.map(t =>\n t.id === successorTaskId\n ? { ...t, dependencies: [...(t.dependencies ?? []), newDep] }\n : t\n );\n const validation = validateDependencies(hypothetical);\n if (!validation.isValid) {\n setCycleError(true);\n setTimeout(() => setCycleError(false), 3000);\n return;\n }\n\n const updatedTask = hypothetical.find(t => t.id === successorTaskId)!;\n\n // Snap successor dates to the predecessor position (lag=0)\n const predecessor = tasks.find(t => t.id === predecessorTaskId);\n if (predecessor) {\n const predStart = new Date(predecessor.startDate as string);\n const predEnd = new Date(predecessor.endDate as string);\n const constraintDate = calculateSuccessorDate(predStart, predEnd, linkType, 0);\n\n const origSuccessor = tasks.find(t => t.id === successorTaskId)!;\n const durationMs =\n new Date(origSuccessor.endDate as string).getTime() -\n new Date(origSuccessor.startDate as string).getTime();\n\n let newStart: Date;\n let newEnd: Date;\n\n if (linkType === 'FS' || linkType === 'SS') {\n newStart = constraintDate;\n newEnd = new Date(constraintDate.getTime() + durationMs);\n } else {\n newEnd = constraintDate;\n newStart = new Date(constraintDate.getTime() - durationMs);\n }\n\n const snappedTask: Task = {\n ...updatedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n };\n onTaskChange?.(snappedTask);\n } else {\n // Predecessor not found — emit without snap (graceful fallback)\n onTaskChange?.(updatedTask);\n }\n\n setSelectingPredecessorFor(null);\n }, [tasks, onTaskChange]);\n\n const handleRemoveDependency = useCallback((\n taskId: string,\n predecessorTaskId: string,\n linkType: LinkType\n ) => {\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n const updatedDeps = (task.dependencies ?? []).filter(\n d => !(d.taskId === predecessorTaskId && d.type === linkType)\n );\n onTaskChange?.({ ...task, dependencies: updatedDeps });\n }, [tasks, onTaskChange]);\n\n // New task creation state\n const [isCreating, setIsCreating] = useState(false);\n\n // Drag-to-reorder state\n const [draggingIndex, setDraggingIndex] = useState<number | null>(null);\n const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);\n const dragOriginIndexRef = useRef<number | null>(null);\n\n const handleDragStart = useCallback((index: number, e: React.DragEvent) => {\n e.dataTransfer.effectAllowed = 'move';\n setDraggingIndex(index);\n dragOriginIndexRef.current = index;\n }, []);\n\n const handleDragOver = useCallback((index: number, e: React.DragEvent) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(index);\n }, []);\n\n const handleDrop = useCallback((dropIndex: number, e: React.DragEvent) => {\n e.preventDefault();\n const originIndex = dragOriginIndexRef.current;\n // No-op: same position (line is already where the row is)\n if (originIndex === null || originIndex === dropIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n return;\n }\n const reordered = [...orderedTasks];\n const [moved] = reordered.splice(originIndex, 1);\n\n // Blue line appears ABOVE row at dropIndex\n // So dropIndex=0 means insert at 0 (before first row)\n // dropIndex=1 means insert at 1 (between row 0 and row 1)\n // dropIndex=tasks.length means insert at the end (after last row)\n // When dragging down (originIndex < dropIndex), after splice the indices shift by 1\n // So we need to insert at dropIndex - 1\n const insertIndex = dropIndex === visibleTasks.length\n ? visibleTasks.length - 1 // After last means position at last\n : originIndex < dropIndex ? dropIndex - 1 : dropIndex;\n\n // ============================================\n // COMPREHENSIVE LOGGING - START\n // ============================================\n const isChild = !!moved.parentId;\n const isParent = tasks.some(t => t.parentId === moved.id);\n const taskType = isParent ? 'PARENT' : (isChild ? 'CHILD' : 'ROOT');\n\n console.log('=== DRAG & DROP START ===');\n console.log('[MOVED TASK]', {\n id: moved.id,\n name: moved.name,\n type: taskType,\n parentId: moved.parentId,\n originIndex: originIndex,\n dropIndex: dropIndex,\n insertIndex: insertIndex,\n direction: originIndex < dropIndex ? 'DOWN' : 'UP'\n });\n console.log('[TASKS ARRAY LENGTH]', orderedTasks.length);\n // ============================================\n\n // parentId inference: determine if task should be in a group\n // IMPORTANT: Calculate this BEFORE splicing moved task back into reordered\n // because we need to find the parent's position in the array WITHOUT the moved task\n let inferredParentId: string | undefined;\n\n if (moved.parentId) {\n // Task is currently a child - check if it's staying in or leaving its group\n // Find parent position in the array WITHOUT the moved task (reordered after first splice)\n const parentIndex = reordered.findIndex(t => t.id === moved.parentId);\n\n console.log('[CHILD TASK - CHECKING GROUP POSITION]', {\n currentParentId: moved.parentId,\n parentIndex: parentIndex,\n parentFound: parentIndex !== -1\n });\n\n if (parentIndex === -1) {\n // Parent not found - should not happen, but handle gracefully\n console.log('[PARENT NOT FOUND] - Setting parentId to undefined');\n inferredParentId = undefined;\n } else {\n // Calculate where the moved task will end up AFTER we splice it in\n // The key question: is insertIndex outside the range [parentIndex, parentIndex + numSiblings]?\n const numSiblings = reordered.filter(t => t.parentId === moved.parentId).length;\n const groupEnd = parentIndex + numSiblings;\n\n console.log('[GROUP RANGE CALCULATION]', {\n parentIndex: parentIndex,\n numSiblings: numSiblings,\n groupEnd: groupEnd,\n groupRange: `[${parentIndex}, ${groupEnd}]`,\n insertIndex: insertIndex,\n condition1_atOrAboveParent: insertIndex <= parentIndex,\n condition2_belowAllSiblings: insertIndex > groupEnd\n });\n\n // If insertIndex is <= parent (at or above parent position) or > groupEnd (below all siblings)\n // Note: insertIndex == parentIndex means child will be inserted at parent's position,\n // which after splicing puts child above parent (parent shifts down by 1)\n if (insertIndex <= parentIndex || insertIndex > groupEnd) {\n console.log('[DECISION] EXIT GROUP - insertIndex is outside group range');\n console.log(' -> Reason:', insertIndex <= parentIndex ? 'At or above parent position' : 'Below all siblings');\n console.log(' -> Setting inferredParentId = undefined');\n inferredParentId = undefined; // Exit group - become root\n } else {\n console.log('[DECISION] STAY IN GROUP - insertIndex is within group range');\n console.log(' -> Keeping original parentId:', moved.parentId);\n // Staying within group - keep original parentId\n inferredParentId = moved.parentId;\n }\n }\n } else {\n // Task is currently root - check if it should join a group\n console.log('[ROOT TASK] - Will check if it should join a group after splicing');\n // This needs to be calculated AFTER splicing, so we do it below\n }\n\n // Now splice the moved task into its final position\n reordered.splice(insertIndex, 0, moved);\n\n console.log('[AFTER SPLICE]', {\n movedTaskFinalPosition: insertIndex,\n totalTasks: reordered.length\n });\n\n // For root tasks, check if they should join a group (need reordered for this)\n if (!moved.parentId) {\n // Prefer taskAbove if it has a parent (joining that group)\n if (insertIndex > 0) {\n const taskAbove = reordered[insertIndex - 1];\n console.log('[ROOT TASK - CHECK TASK ABOVE]', {\n taskAboveId: taskAbove.id,\n taskAboveName: taskAbove.name,\n taskAboveParentId: taskAbove.parentId\n });\n if (taskAbove.parentId) {\n console.log(' -> Joining group from taskAbove:', taskAbove.parentId);\n inferredParentId = taskAbove.parentId;\n }\n }\n\n // Otherwise check taskBelow\n if (inferredParentId === undefined && insertIndex < reordered.length - 1) {\n const taskBelow = reordered[insertIndex + 1];\n console.log('[ROOT TASK - CHECK TASK BELOW]', {\n taskBelowId: taskBelow.id,\n taskBelowName: taskBelow.name,\n taskBelowParentId: taskBelow.parentId\n });\n if (taskBelow.parentId) {\n console.log(' -> Joining group from taskBelow:', taskBelow.parentId);\n inferredParentId = taskBelow.parentId;\n }\n }\n\n if (!inferredParentId) {\n console.log('[ROOT TASK] - Staying as root (no group to join)');\n }\n }\n\n console.log('[FINAL RESULT]', {\n inferredParentId: inferredParentId,\n willExitGroup: moved.parentId && !inferredParentId,\n willJoinGroup: !moved.parentId && !!inferredParentId,\n willStayInGroup: moved.parentId && inferredParentId === moved.parentId,\n willStayRoot: !moved.parentId && !inferredParentId\n });\n console.log('=== DRAG & DROP END ===\\n');\n\n onReorder?.(reordered, moved.id, inferredParentId);\n onTaskSelect?.(moved.id);\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n }, [orderedTasks, visibleTasks.length, onReorder, onTaskSelect]);\n\n const handleDragEnd = useCallback(() => {\n // Called when drag ends without a valid drop (Escape, or dropped outside)\n // handleDrop already clears state on successful drop, so this is only the cancel path\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n }, []);\n\n const handleConfirmNewTask = useCallback((name: string) => {\n const now = new Date();\n const todayISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()\n )).toISOString().split('T')[0];\n const endISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 7\n )).toISOString().split('T')[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name,\n startDate: todayISO,\n endDate: endISO,\n };\n onAdd?.(newTask);\n setIsCreating(false);\n }, [onAdd]);\n\n const handleCancelNewTask = useCallback(() => setIsCreating(false), []);\n\n return (\n <div\n ref={overlayRef}\n className={`gantt-tl-overlay${show ? '' : ' gantt-tl-hidden'}`}\n style={{ width: `${taskListWidth}px` }}\n >\n <div className=\"gantt-tl-table\">\n {/* Header row - aligns with TimeScaleHeader, 1px taller for row alignment */}\n <div className=\"gantt-tl-header\" style={{ height: `${headerHeight + 0.5}px` }}>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-number\">№</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-name\">Имя</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-date\">Начало</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-date\">Окончание</div>\n <div className=\"gantt-tl-headerCell gantt-tl-cell-progress\">%</div>\n {/* Dependencies column header with type switcher */}\n <div className=\"gantt-tl-headerCell gantt-tl-cell-deps\" style={{ position: 'relative' }}>\n <Popover open={typeMenuOpen} onOpenChange={setTypeMenuOpen}>\n <PopoverTrigger asChild>\n <button\n className=\"gantt-tl-dep-type-trigger\"\n disabled={disableDependencyEditing}\n onClick={(e) => e.stopPropagation()}\n >\n Связи {React.createElement(LINK_TYPE_ICONS[activeLinkType])} &#9662;\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div className=\"gantt-tl-dep-type-menu\">\n {LINK_TYPE_ORDER.map(lt => (\n <button\n key={lt}\n className={`gantt-tl-dep-type-option${activeLinkType === lt ? ' active' : ''}`}\n onClick={() => { setActiveLinkType(lt); setTypeMenuOpen(false); }}\n >\n {React.createElement(LINK_TYPE_ICONS[lt])}\n <span>{LINK_TYPE_LABELS[lt]}</span>\n </button>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n {cycleError && (\n <div className=\"gantt-tl-dep-error\">Цикл зависимостей!</div>\n )}\n </div>\n </div>\n\n {/* Data rows */}\n <div className=\"gantt-tl-body\" style={{ height: `${totalHeight}px` }}>\n {visibleTasks.map((task, index) => (\n <TaskListRow\n key={task.id}\n task={task}\n rowIndex={index}\n rowHeight={rowHeight}\n onTaskChange={onTaskChange}\n selectedTaskId={selectedTaskId}\n onRowClick={handleRowClick}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n allTasks={tasks}\n activeLinkType={activeLinkType}\n selectingPredecessorFor={selectingPredecessorFor}\n onSetSelectingPredecessorFor={setSelectingPredecessorFor}\n onAddDependency={handleAddDependency}\n onRemoveDependency={handleRemoveDependency}\n selectedChip={selectedChip}\n onChipSelect={handleChipSelect}\n onScrollToTask={onScrollToTask}\n onDelete={onDelete}\n onAdd={onAdd}\n onInsertAfter={onInsertAfter}\n editingTaskId={propEditingTaskId}\n isDragging={draggingIndex === index}\n isDragOver={dragOverIndex === index}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onDragEnd={handleDragEnd}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={onPromoteTask}\n onDemoteTask={onDemoteTask}\n />\n ))}\n </div>\n\n {/* Ghost row for new task creation — positioned OUTSIDE body div to avoid height desync */}\n {isCreating && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmNewTask}\n onCancel={handleCancelNewTask}\n />\n )}\n\n {/* Add task button - also serves as drop target for moving tasks to end */}\n {enableAddTask && onAdd && !isCreating && (\n <button\n className={`gantt-tl-add-btn${dragOverIndex === visibleTasks.length ? ' gantt-tl-add-btn-drag-over' : ''}`}\n onClick={() => setIsCreating(true)}\n onDragEnter={(e) => {\n e.preventDefault();\n setDragOverIndex(visibleTasks.length);\n }}\n onDragOver={(e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(visibleTasks.length);\n }}\n onDragLeave={(e) => {\n e.preventDefault();\n setDragOverIndex(null);\n }}\n onDrop={(e) => {\n e.preventDefault();\n handleDrop(visibleTasks.length, e);\n }}\n type=\"button\"\n >\n + Добавить задачу\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default TaskList;\n","'use client';\n\nimport React from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\n\nexport interface PopoverProps {\n /** Whether the popover is open */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** The trigger element */\n children: React.ReactNode;\n}\n\nexport interface PopoverContentProps {\n /** Content to display inside the popover */\n children: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Alignment relative to trigger */\n align?: 'start' | 'center' | 'end';\n /** Side to render the popover */\n side?: 'top' | 'right' | 'bottom' | 'left';\n /** Whether to use a portal for rendering */\n portal?: boolean;\n /** Collision padding */\n collisionPadding?: number;\n /** Callback when user interacts outside the popover */\n onInteractOutside?: (event: CustomEvent) => void;\n}\n\n/**\n * Popover root component wrapping Radix UI Popover\n */\nexport const Popover: React.FC<PopoverProps> = ({ open, onOpenChange, children }) => {\n return (\n <RadixPopover.Root open={open} onOpenChange={onOpenChange}>\n {children}\n </RadixPopover.Root>\n );\n};\n\n/**\n * Popover trigger — wraps the element that opens the popover\n */\nexport const PopoverTrigger = RadixPopover.Trigger;\n\n/**\n * Popover content — the floating panel\n */\nexport const PopoverContent: React.FC<PopoverContentProps> = ({\n children,\n className,\n align = 'start',\n side = 'bottom',\n portal = true,\n collisionPadding = 8,\n onInteractOutside,\n}) => {\n const content = (\n <RadixPopover.Content\n className={`gantt-popover${className ? ` ${className}` : ''}`}\n align={align}\n side={side}\n collisionPadding={collisionPadding}\n sideOffset={4}\n onInteractOutside={onInteractOutside}\n >\n {children}\n </RadixPopover.Content>\n );\n\n if (portal) {\n return <RadixPopover.Portal>{content}</RadixPopover.Portal>;\n }\n\n return content;\n};\n\nexport default Popover;\n","'use client';\n\nimport React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';\nimport type { Task } from '../GanttChart';\nimport type { LinkType } from '../../types';\nimport { parseUTCDate } from '../../utils/dateUtils';\nimport { computeLagFromDates, isTaskParent, findParentId } from '../../utils/dependencyUtils';\nimport { Input } from '../ui/Input';\nimport { DatePicker } from '../ui/DatePicker';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/Popover';\nimport { LINK_TYPE_ICONS } from './DepIcons';\n\n// ---------------------------------------------------------------------------\n// DepChip — local unified component used in both single-chip cell and popover\n// ---------------------------------------------------------------------------\ninterface DepChipProps {\n lag?: number;\n dep: { taskId: string; type: LinkType };\n taskId: string;\n predecessorName?: string;\n selectedChip: TaskListRowProps['selectedChip'];\n disableDependencyEditing: boolean;\n onChipSelect: TaskListRowProps['onChipSelect'];\n onRowClick: TaskListRowProps['onRowClick'];\n onScrollToTask: TaskListRowProps['onScrollToTask'];\n onRemoveDependency: TaskListRowProps['onRemoveDependency'];\n onChipSelectClear: () => void;\n}\n\nconst TrashIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n);\n\nconst PlusIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n);\n\nconst DragHandleIcon = () => (\n <svg width=\"10\" height=\"14\" viewBox=\"0 0 10 14\" fill=\"currentColor\">\n <circle cx=\"2\" cy=\"2\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"2\" r=\"1.5\" />\n <circle cx=\"2\" cy=\"7\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"7\" r=\"1.5\" />\n <circle cx=\"2\" cy=\"12\" r=\"1.5\" />\n <circle cx=\"8\" cy=\"12\" r=\"1.5\" />\n </svg>\n);\n\n// ---------------------------------------------------------------------------\n// HierarchyButton — Single button with left/right arrows for hierarchy navigation\n// ---------------------------------------------------------------------------\ninterface HierarchyButtonProps {\n /** Whether the task is a child (can be promoted) */\n isChild: boolean;\n /** Whether the task is a parent (has children) */\n isParent: boolean;\n /** Row index - first row cannot demote */\n rowIndex: number;\n /** Callback when promote is clicked (left arrow) */\n onPromote?: (e: React.MouseEvent) => void;\n /** Callback when demote is clicked (right arrow) */\n onDemote?: (e: React.MouseEvent) => void;\n}\n\nconst HierarchyButton: React.FC<HierarchyButtonProps> = ({\n isChild,\n isParent,\n rowIndex,\n onPromote,\n onDemote,\n}) => {\n // Can promote if task is a child\n const canPromote = isChild && onPromote;\n // Can demote if not a parent and not first row\n const canDemote = !isParent && onDemote && rowIndex > 0;\n\n // If neither action available, don't render\n if (!canPromote && !canDemote) {\n return null;\n }\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (canPromote) {\n onPromote!(e);\n } else if (canDemote) {\n onDemote!(e);\n }\n };\n\n const title = canPromote\n ? 'Повысить (сделать корневой)'\n : 'Понизить (сделать подчиненной)';\n\n const ArrowLeft = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m12 19-7-7 7-7\"/>\n <path d=\"M19 12H5\"/>\n </svg>\n );\n\n const ArrowRight = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M5 12h14\"/>\n <path d=\"m12 5 7 7-7 7\"/>\n </svg>\n );\n\n return (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={handleClick}\n title={title}\n >\n {canPromote ? <ArrowLeft /> : <ArrowRight />}\n </button>\n );\n};\n\nfunction formatDepDescription(type: LinkType, lag: number | undefined): string {\n const effectiveLag = lag ?? 0;\n\n if (type === 'FS') {\n if (effectiveLag > 0) return `Начать через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0) return `Начать за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Начать сразу после окончания`;\n }\n if (type === 'FF') {\n if (effectiveLag > 0) return `Завершить через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0) return `Завершить за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Завершить после окончания`;\n }\n if (type === 'SS') {\n if (effectiveLag > 0) return `Начать через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0) return `Начать за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Начать вместе с началом`;\n }\n if (type === 'SF') {\n if (effectiveLag > 0) return `Завершить через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0) return `Завершить за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Завершить до начала`;\n }\n return '';\n}\n\nconst DepChip: React.FC<DepChipProps> = ({\n lag,\n dep,\n taskId,\n predecessorName,\n selectedChip,\n disableDependencyEditing,\n onChipSelect,\n onRowClick,\n onScrollToTask,\n onRemoveDependency,\n onChipSelectClear,\n}) => {\n const isSelected =\n selectedChip?.successorId === taskId &&\n selectedChip?.predecessorId === dep.taskId &&\n selectedChip?.linkType === dep.type;\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (disableDependencyEditing) return;\n // When clicking on an already selected chip, prevent the PopoverTrigger from toggling\n if (isSelected) {\n e.preventDefault();\n onChipSelect?.(null);\n return;\n }\n onChipSelect?.({ successorId: taskId, predecessorId: dep.taskId, linkType: dep.type });\n onScrollToTask?.(dep.taskId);\n };\n\n const handleOpenChange = useCallback((open: boolean) => {\n if (!open) {\n onChipSelect?.(null);\n }\n }, [onChipSelect]);\n\n const handleTrashClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemoveDependency?.(taskId, dep.taskId, dep.type);\n onChipSelectClear();\n };\n\n const Icon = LINK_TYPE_ICONS[dep.type];\n const depPrefix = formatDepDescription(dep.type, lag);\n const depName = predecessorName ?? dep.taskId;\n\n // TEMP: render without Popover to test click handler\n return (\n <span className=\"gantt-tl-dep-chip-wrapper\">\n <span\n className={`gantt-tl-dep-chip${isSelected ? ' gantt-tl-dep-chip-selected' : ''}`}\n onClick={handleClick}\n >\n <><Icon />{lag != null && lag !== 0 ? (lag > 0 ? `+${lag}` : `${lag}`) : ''}</>\n </span>\n {!disableDependencyEditing && (\n <button\n type=\"button\"\n className=\"gantt-tl-dep-chip-trash\"\n aria-label=\"Удалить связь\"\n onClick={handleTrashClick}\n >\n <TrashIcon />\n </button>\n )}\n </span>\n );\n};\n\nexport interface TaskListRowProps {\n /** Task data to render */\n task: Task;\n /** Index of the task row (for display in № column) */\n rowIndex: number;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via inline edit */\n onTaskChange?: (task: Task) => void;\n /** ID of currently selected task */\n selectedTaskId?: string;\n /** Callback when task row is clicked */\n onRowClick?: (taskId: string) => void;\n /** Disable task name editing (default: false) */\n disableTaskNameEditing?: boolean;\n /** Disable dependency editing (default: false) */\n disableDependencyEditing?: boolean;\n /** All tasks (for dependency picker) */\n allTasks?: Task[];\n /** Currently active link type for new dependencies */\n activeLinkType?: LinkType;\n /** Task ID currently in predecessor-picking mode (null if not picking) */\n selectingPredecessorFor?: string | null;\n /** Callback to set the task currently in predecessor-picking mode */\n onSetSelectingPredecessorFor?: (taskId: string | null) => void;\n /** Callback to add a dependency link */\n onAddDependency?: (successorTaskId: string, predecessorTaskId: string, linkType: LinkType) => void;\n /** Callback to remove a dependency link */\n onRemoveDependency?: (taskId: string, predecessorTaskId: string, linkType: LinkType) => void;\n /** Currently selected chip (for predecessor-side delete) */\n selectedChip?: { successorId: string; predecessorId: string; linkType: string } | null;\n /** Callback when a chip is clicked (selects it) */\n onChipSelect?: (chip: { successorId: string; predecessorId: string; linkType: LinkType } | null) => void;\n /** Callback to scroll the chart grid to center this task (called when task name is clicked) */\n onScrollToTask?: (taskId: string) => void;\n /** Callback when task is deleted */\n onDelete?: (taskId: string) => void;\n /** Callback when a new task is inserted below this row */\n onAdd?: (task: Task) => void;\n /** Callback when a new task is inserted after this task */\n onInsertAfter?: (taskId: string, newTask: Task) => void;\n /** ID of task that should enter edit mode on mount (for auto-edit after insert) */\n editingTaskId?: string | null;\n /** Whether this row is currently being dragged (shows semi-transparent) */\n isDragging?: boolean;\n /** Whether this row is the current drag-over target (shows top border indicator) */\n isDragOver?: boolean;\n /** Called when drag starts on the handle for this row */\n onDragStart?: (index: number, e: React.DragEvent) => void;\n /** Called when something is dragged over this row */\n onDragOver?: (index: number, e: React.DragEvent) => void;\n /** Called when something is dropped on this row */\n onDrop?: (index: number, e: React.DragEvent) => void;\n /** Called when drag ends (drop or Escape) */\n onDragEnd?: (e: React.DragEvent) => void;\n /** Set of collapsed parent task IDs */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked */\n onToggleCollapse?: (parentId: string) => void;\n /** Callback when task is promoted (parentId removed) */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when task is demoted (parentId set to previous task) */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n}\n\nconst toISODate = (value: string | Date): string => {\n if (value instanceof Date) return value.toISOString().split('T')[0];\n // Handle full ISO strings like \"2026-02-12T00:00:00.000Z\"\n if (typeof value === 'string' && value.includes('T')) return value.split('T')[0];\n return value as string;\n};\n\nexport const TaskListRow: React.FC<TaskListRowProps> = React.memo(\n ({\n task,\n rowIndex,\n rowHeight,\n onTaskChange,\n selectedTaskId,\n onRowClick,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n allTasks = [],\n activeLinkType,\n selectingPredecessorFor,\n onSetSelectingPredecessorFor,\n onAddDependency,\n onRemoveDependency,\n selectedChip,\n onChipSelect,\n onScrollToTask,\n onDelete,\n onAdd,\n onInsertAfter,\n editingTaskId,\n isDragging = false,\n isDragOver = false,\n onDragStart,\n onDragOver,\n onDrop,\n onDragEnd,\n collapsedParentIds = new Set(),\n onToggleCollapse,\n onPromoteTask,\n onDemoteTask,\n }) => {\n const [editingName, setEditingName] = useState(false);\n const [nameValue, setNameValue] = useState('');\n const nameInputRef = useRef<HTMLInputElement>(null);\n const [editingProgress, setEditingProgress] = useState(false);\n const [progressValue, setProgressValue] = useState(0);\n const progressInputRef = useRef<HTMLInputElement>(null);\n const [overflowOpen, setOverflowOpen] = useState(false);\n const confirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const autoEditedForRef = useRef<string | null>(null); // Track which editingTaskId we already auto-entered for\n const editTriggerRef = useRef<'keypress' | 'doubleclick' | 'autoedit'>('doubleclick'); // How editing was started\n const [deletePending, setDeletePending] = useState(false);\n const deleteButtonRef = useRef<HTMLButtonElement>(null);\n\n const isSelected = selectedTaskId === task.id;\n\n // Hierarchy computed values\n const isParent = useMemo(() => isTaskParent(task.id, allTasks), [task.id, allTasks]);\n const isChild = task.parentId !== undefined;\n const isCollapsed = collapsedParentIds.has(task.id);\n\n // Picker mode flags for this row\n const isPicking = selectingPredecessorFor != null;\n const isSourceRow = isPicking && selectingPredecessorFor === task.id;\n\n // Chip data: compute effective lag from actual dates (always correct, even on initial load)\n const chips = useMemo(() => {\n const succStart = new Date(task.startDate as string);\n const succEnd = new Date(task.endDate as string);\n const taskById = new Map((allTasks ?? []).map(t => [t.id, t]));\n return (task.dependencies ?? []).map(dep => {\n const pred = taskById.get(dep.taskId);\n const lag = pred\n ? computeLagFromDates(\n dep.type,\n new Date(pred.startDate as string),\n new Date(pred.endDate as string),\n succStart,\n succEnd\n )\n : (dep.lag ?? 0);\n return { dep, lag, predecessorName: pred?.name ?? dep.taskId };\n });\n }, [task.dependencies, task.startDate, task.endDate, allTasks]);\n\n const linkWord = chips.length <= 4 ? 'связи' : 'связей';\n\n useEffect(() => {\n if (editingName && nameInputRef.current) {\n nameInputRef.current.focus();\n if (editTriggerRef.current === 'keypress') {\n // Cursor to end — the typed char is already in the input, don't select it\n const len = nameInputRef.current.value.length;\n nameInputRef.current.setSelectionRange(len, len);\n } else {\n // Double-click or auto-edit-on-insert: select all for easy replacement\n nameInputRef.current.select();\n }\n }\n }, [editingName]);\n\n // Reset delete confirmation when clicking elsewhere\n useEffect(() => {\n const handleMouseDownOutside = (event: MouseEvent) => {\n if (deletePending && deleteButtonRef.current && !deleteButtonRef.current.contains(event.target as Node)) {\n setDeletePending(false);\n }\n };\n\n if (deletePending) {\n document.addEventListener('mousedown', handleMouseDownOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleMouseDownOutside);\n };\n }, [deletePending]);\n\n // Auto-enter edit mode when this task is created via insert.\n // We track which editingTaskId we already reacted to (autoEditedForRef) so that\n // subsequent re-renders caused by saving the name (which changes task.name) do NOT\n // re-trigger edit mode. Without this guard, saving the name → onTaskChange → new task.name\n // → re-render → effect fires again → edit mode re-entered → user must press Enter twice.\n useEffect(() => {\n if (\n editingTaskId === task.id &&\n !disableTaskNameEditing &&\n autoEditedForRef.current !== editingTaskId\n ) {\n autoEditedForRef.current = editingTaskId;\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'autoedit';\n setNameValue(task.name);\n setEditingName(true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editingTaskId, task.id, disableTaskNameEditing]);\n\n const handleNameClick = useCallback((e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n onRowClick?.(task.id);\n onScrollToTask?.(task.id);\n }, [task.id, disableTaskNameEditing, onRowClick, onScrollToTask]);\n\n const handleNameDoubleClick = useCallback((e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'doubleclick';\n setNameValue(task.name);\n setEditingName(true);\n }, [task.name, disableTaskNameEditing]);\n\n const handleRowKeyDown = useCallback((e: React.KeyboardEvent) => {\n // Don't handle row keyboard events when editing progress\n if (editingProgress) return;\n // F2: enter edit mode with cursor at end of existing name\n if (!editingName && !disableTaskNameEditing && e.key === 'F2') {\n e.preventDefault();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'keypress'; // 'keypress' trigger = cursor at end (not select-all)\n setNameValue(task.name);\n setEditingName(true);\n return;\n }\n // If not editing and a printable key is pressed, start editing\n if (!editingName && !disableTaskNameEditing && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n confirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = 'keypress';\n setNameValue(e.key);\n setEditingName(true);\n // Input will be focused by existing useEffect; cursor placed at end (not select-all)\n }\n }, [editingName, disableTaskNameEditing, task.name]);\n\n const handleNameSave = useCallback(() => {\n if (confirmedRef.current) {\n // Already saved via Enter key, skip blur handler\n confirmedRef.current = false;\n return;\n }\n if (nameValue.trim()) {\n onTaskChange?.({ ...task, name: nameValue.trim() });\n }\n setEditingName(false);\n }, [nameValue, task, onTaskChange]);\n\n const handleNameCancel = useCallback(() => {\n setEditingName(false);\n }, []);\n\n const handleNameKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n confirmedRef.current = true; // Mark as saved to prevent blur from triggering again\n if (nameValue.trim()) {\n onTaskChange?.({ ...task, name: nameValue.trim() });\n }\n setEditingName(false);\n } else if (e.key === 'Escape') {\n handleNameCancel();\n }\n }, [nameValue, task, onTaskChange, handleNameCancel]);\n\n const handleProgressClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n confirmedRef.current = false;\n setProgressValue(task.progress ?? 0);\n setEditingProgress(true);\n }, [task.progress]);\n\n const handleProgressSave = useCallback(() => {\n if (confirmedRef.current) {\n confirmedRef.current = false;\n return;\n }\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n onTaskChange?.({ ...task, progress: clampedValue });\n setEditingProgress(false);\n }, [progressValue, task, onTaskChange]);\n\n const handleProgressCancel = useCallback(() => {\n setEditingProgress(false);\n }, []);\n\n const handleProgressKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation(); // Prevent row-level keyboard handler from interfering\n if (e.key === 'Enter') {\n confirmedRef.current = true;\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n onTaskChange?.({ ...task, progress: clampedValue });\n setEditingProgress(false);\n } else if (e.key === 'Escape') {\n handleProgressCancel();\n }\n }, [progressValue, task, onTaskChange, handleProgressCancel]);\n\n useEffect(() => {\n if (editingProgress && progressInputRef.current) {\n progressInputRef.current.focus();\n progressInputRef.current.select();\n }\n }, [editingProgress]);\n\n // Both date pickers shift the whole task (preserving duration), same as drag-move\n const handleStartDateChange = useCallback((newDateISO: string) => {\n if (!newDateISO) return;\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const newStart = new Date(newDateISO + 'T00:00:00Z');\n const newEnd = new Date(newStart.getTime() + durationMs);\n onTaskChange?.({ ...task, startDate: newDateISO, endDate: newEnd.toISOString().split('T')[0] });\n }, [task, onTaskChange]);\n\n const handleEndDateChange = useCallback((newDateISO: string) => {\n if (!newDateISO) return;\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const newEnd = new Date(newDateISO + 'T00:00:00Z');\n const newStart = new Date(newEnd.getTime() - durationMs);\n onTaskChange?.({ ...task, startDate: newStart.toISOString().split('T')[0], endDate: newDateISO });\n }, [task, onTaskChange]);\n\n const handleRowClickInternal = useCallback(() => {\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleNumberClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleToggleCollapse = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleCollapse?.(task.id);\n }, [task.id, onToggleCollapse]);\n\n // Hierarchy handlers - promote/demote\n const handlePromote = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onPromoteTask?.(task.id);\n }, [task.id, onPromoteTask]);\n\n const handleDemote = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n // Find previous task in allTasks\n const currentIndex = allTasks.findIndex(t => t.id === task.id);\n if (currentIndex > 0) {\n const previousTask = allTasks[currentIndex - 1];\n // Smart demote: if previous task has a parent, use that parent (sibling behavior)\n // Otherwise, use previous task as parent (child behavior)\n const targetParentId = previousTask.parentId || previousTask.id;\n onDemoteTask?.(task.id, targetParentId);\n }\n }, [task.id, allTasks, onDemoteTask]);\n\n // Dependency handlers\n const handleAddClick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(task.id);\n }, [task.id, onSetSelectingPredecessorFor]);\n\n const handlePredecessorPick = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (!isPicking || isSourceRow) return;\n if (!selectingPredecessorFor || !activeLinkType) return;\n onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);\n }, [isPicking, isSourceRow, selectingPredecessorFor, task.id, activeLinkType, onAddDependency]);\n\n const handleCancelPicking = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(null);\n }, [onSetSelectingPredecessorFor]);\n\n // True when this row is the predecessor for the currently selected chip\n const isSelectedPredecessor = selectedChip != null && selectedChip.predecessorId === task.id;\n\n // Delete the selected dependency from the predecessor row's \"Удалить\" button\n const handleDeleteSelected = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (!selectedChip) return;\n onRemoveDependency?.(selectedChip.successorId, selectedChip.predecessorId, selectedChip.linkType as LinkType);\n onChipSelect?.(null);\n }, [selectedChip, onRemoveDependency, onChipSelect]);\n\n const startDateISO = toISODate(task.startDate);\n const endDateISO = toISODate(task.endDate);\n\n return (\n <div\n className={[\n 'gantt-tl-row',\n isSelected ? 'gantt-tl-row-selected' : '',\n isPicking && !isSourceRow ? 'gantt-tl-row-picking' : '',\n isSourceRow ? 'gantt-tl-row-picking-self' : '',\n isDragging ? 'gantt-tl-row-dragging' : '',\n isDragOver ? 'gantt-tl-row-drag-over' : '',\n isChild ? 'gantt-tl-row-child' : '',\n isParent ? 'gantt-tl-row-parent' : '',\n ].filter(Boolean).join(' ')}\n style={{ minHeight: `${rowHeight}px`, position: 'relative' }}\n onClick={handleRowClickInternal}\n onKeyDown={handleRowKeyDown}\n onDragOver={(e) => onDragOver?.(rowIndex, e)}\n onDrop={(e) => onDrop?.(rowIndex, e)}\n onMouseLeave={() => {\n if (deletePending) {\n setDeletePending(false);\n }\n }}\n tabIndex={isSelected ? 0 : -1}\n >\n {/* Number column — click selects the row */}\n <div\n className=\"gantt-tl-cell gantt-tl-cell-number\"\n onClick={handleNumberClick}\n >\n {isParent ? (\n <button\n type=\"button\"\n className=\"gantt-tl-collapse-btn\"\n onClick={handleToggleCollapse}\n aria-label={isCollapsed ? 'Развернуть' : 'Свернуть'}\n >\n {isCollapsed ? '+' : '-'}\n </button>\n ) : (\n <>\n <span\n className=\"gantt-tl-drag-handle\"\n draggable={true}\n onDragStart={(e) => {\n e.stopPropagation();\n onDragStart?.(rowIndex, e);\n }}\n onDragEnd={(e) => onDragEnd?.(e)}\n onClick={(e) => e.stopPropagation()}\n >\n <DragHandleIcon />\n </span>\n <span className=\"gantt-tl-num-label\">{rowIndex + 1}</span>\n </>\n )}\n </div>\n\n {/* Name column — styled Input overlay on edit */}\n <div className=\"gantt-tl-cell gantt-tl-cell-name\">\n {editingName && (\n <Input\n ref={nameInputRef}\n type=\"text\"\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n onBlur={handleNameSave}\n onKeyDown={handleNameKeyDown}\n className=\"gantt-tl-name-input\"\n onClick={(e) => e.stopPropagation()}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-name-trigger ${disableTaskNameEditing ? 'gantt-tl-name-locked' : ''}`}\n onClick={handleNameClick}\n onDoubleClick={handleNameDoubleClick}\n style={editingName ? { visibility: 'hidden', pointerEvents: 'none' } : undefined}\n >\n {task.name}\n </button>\n {!editingName && (\n <div className=\"gantt-tl-name-actions\">\n {onInsertAfter && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-insert\"\n onClick={(e) => {\n e.stopPropagation();\n const now = new Date();\n const todayISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()\n )).toISOString().split('T')[0];\n const endISO = new Date(Date.UTC(\n now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 7\n )).toISOString().split('T')[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name: 'Новая задача',\n startDate: todayISO,\n endDate: endISO,\n };\n onInsertAfter(task.id, newTask);\n }}\n aria-label=\"Вставить задачу после этой\"\n >\n <PlusIcon />\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n ref={deleteButtonRef}\n className={`gantt-tl-name-action-btn gantt-tl-action-delete${deletePending ? ' gantt-tl-action-delete-confirm' : ''}`}\n onClick={(e) => {\n e.stopPropagation();\n if (!deletePending) {\n setDeletePending(true);\n } else {\n setDeletePending(false);\n onDelete(task.id);\n }\n }}\n aria-label=\"Удалить задачу\"\n >\n {deletePending ? 'Удалить?' : <TrashIcon />}\n </button>\n )}\n <HierarchyButton\n isChild={isChild}\n isParent={isParent}\n rowIndex={rowIndex}\n onPromote={onPromoteTask ? handlePromote : undefined}\n onDemote={onDemoteTask ? handleDemote : undefined}\n />\n </div>\n )}\n </div>\n\n {/* Start Date — DatePicker component */}\n <div className=\"gantt-tl-cell gantt-tl-cell-date\" onClick={(e) => e.stopPropagation()}>\n <DatePicker\n value={startDateISO}\n onChange={handleStartDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n />\n </div>\n\n {/* End Date — DatePicker component */}\n <div className=\"gantt-tl-cell gantt-tl-cell-date\" onClick={(e) => e.stopPropagation()}>\n <DatePicker\n value={endDateISO}\n onChange={handleEndDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n />\n </div>\n\n {/* Progress column */}\n <div className=\"gantt-tl-cell gantt-tl-cell-progress\" onClick={handleProgressClick}>\n {editingProgress && (\n <Input\n ref={progressInputRef}\n type=\"number\"\n min={0}\n max={100}\n value={progressValue}\n onChange={(e) => setProgressValue(parseInt(e.target.value) || 0)}\n onBlur={handleProgressSave}\n onKeyDown={handleProgressKeyDown}\n className=\"gantt-tl-progress-input\"\n onClick={(e) => e.stopPropagation()}\n />\n )}\n <span style={editingProgress ? { visibility: 'hidden', pointerEvents: 'none' } : undefined}>\n {task.progress ? `${Math.round(task.progress)}%` : '0%'}\n </span>\n </div>\n\n {/* Dependencies column */}\n <div\n className=\"gantt-tl-cell gantt-tl-cell-deps\"\n onClick={isSourceRow ? handleCancelPicking : (isPicking ? handlePredecessorPick : undefined)}\n >\n {isSourceRow ? (\n <span className=\"gantt-tl-dep-source-hint\">Выберите задачу</span>\n ) : isSelectedPredecessor && !disableDependencyEditing ? (\n /* Full-replacement: \"Зависит от [name]\" → hover → \"Удалить\" */\n <button\n type=\"button\"\n className=\"gantt-tl-dep-delete-label\"\n onClick={handleDeleteSelected}\n aria-label=\"Удалить связь\"\n >\n <span className=\"gantt-tl-dep-delete-label-default\">Связано с</span>\n <span className=\"gantt-tl-dep-delete-label-hover\">Удалить связь</span>\n </button>\n ) : (\n <>\n {chips.length >= 2 ? (\n /* 2+ deps — show only \"N связей\" summary chip that opens a popover */\n <Popover open={overflowOpen} onOpenChange={setOverflowOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-summary-chip\"\n onClick={(e) => { e.stopPropagation(); setOverflowOpen(v => !v); }}\n >\n {chips.length} {linkWord}\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div className=\"gantt-tl-dep-overflow-list\" onClick={(e) => e.stopPropagation()}>\n {chips.map(({ dep, lag, predecessorName }) => (\n <DepChip\n key={`${dep.taskId}-${dep.type}`}\n lag={lag}\n dep={dep}\n taskId={task.id}\n predecessorName={predecessorName}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n />\n ))}\n </div>\n </PopoverContent>\n </Popover>\n ) : chips.length === 1 ? (\n /* Single chip — unified DepChip */\n <DepChip\n lag={chips[0].lag}\n dep={chips[0].dep}\n taskId={task.id}\n predecessorName={chips[0].predecessorName}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n />\n ) : null}\n\n {/* \"+\" add dependency button — hidden in picker mode and when editing disabled, hover-reveal */}\n {!disableDependencyEditing && !isPicking && (\n <button\n type=\"button\"\n className={`gantt-tl-dep-add gantt-tl-dep-add-hover${selectedChip ? ' gantt-tl-dep-add-hidden' : ''}`}\n onClick={handleAddClick}\n aria-label=\"Добавить связь\"\n >\n +\n </button>\n )}\n </>\n )}\n </div>\n </div>\n );\n }\n);\n\nTaskListRow.displayName = 'TaskListRow';\nexport default TaskListRow;\n","'use client';\n\nimport React from 'react';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Additional CSS class names */\n className?: string;\n}\n\n/**\n * Styled text input component using gantt-lib CSS variables\n */\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => {\n return (\n <input\n ref={ref}\n className={`gantt-input${className ? ` ${className}` : ''}`}\n {...props}\n />\n );\n }\n);\n\nInput.displayName = 'Input';\nexport default Input;\n","'use client';\n\nimport React, { useState, useCallback } from 'react';\nimport { format, isValid } from 'date-fns';\nimport { Calendar } from './Calendar';\nimport { Popover, PopoverTrigger, PopoverContent } from './Popover';\n\nexport interface DatePickerProps {\n /** Current date value as ISO string (YYYY-MM-DD) */\n value?: string;\n /** Callback with new ISO date string (YYYY-MM-DD) when date is selected */\n onChange?: (isoDate: string) => void;\n /** Display format for the input (default: dd.MM.yyyy) */\n format?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Whether to use portal for popover (default: true) */\n portal?: boolean;\n /** Additional CSS class names for the trigger button */\n className?: string;\n /** Whether the picker is disabled */\n disabled?: boolean;\n}\n\n/**\n * DatePicker component — shows formatted date as a button, opens calendar popup on click\n * Accepts and returns ISO date strings (YYYY-MM-DD)\n */\nexport const DatePicker: React.FC<DatePickerProps> = ({\n value,\n onChange,\n format: displayFormat = 'dd.MM.yyyy',\n placeholder = 'Pick a date',\n portal = true,\n className,\n disabled = false,\n}) => {\n const [open, setOpen] = useState(false);\n\n // Parse ISO string to Date for calendar\n const selectedDate: Date | undefined = (() => {\n if (!value) return undefined;\n const d = new Date(value + 'T00:00:00Z');\n return isValid(d) ? d : undefined;\n })();\n\n // Format Date for display\n const displayValue = selectedDate\n ? format(selectedDate, displayFormat)\n : placeholder;\n\n const handleSelect = useCallback(\n (day: Date) => {\n // Convert to ISO string using local date parts to avoid timezone shift\n const iso = [\n day.getFullYear(),\n String(day.getMonth() + 1).padStart(2, '0'),\n String(day.getDate()).padStart(2, '0'),\n ].join('-');\n onChange?.(iso);\n setOpen(false);\n },\n [onChange]\n );\n\n return (\n <Popover open={open} onOpenChange={disabled ? undefined : setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className={`gantt-datepicker-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n {displayValue}\n </button>\n </PopoverTrigger>\n <PopoverContent\n portal={portal}\n align=\"start\"\n side=\"bottom\"\n >\n <Calendar\n mode=\"single\"\n selected={selectedDate}\n onSelect={handleSelect}\n initialDate={selectedDate}\n />\n </PopoverContent>\n </Popover>\n );\n};\n\nDatePicker.displayName = 'DatePicker';\nexport default DatePicker;\n","'use client';\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useMemo,\n} from 'react';\nimport {\n startOfMonth,\n getDaysInMonth,\n format,\n addMonths,\n subMonths,\n addDays,\n subDays,\n isSameDay,\n getDay,\n isToday,\n isWeekend,\n isBefore,\n startOfDay,\n} from 'date-fns';\nimport { ru } from 'date-fns/locale';\n\nexport interface CalendarProps {\n selected?: Date;\n onSelect?: (date: Date) => void;\n initialDate?: Date;\n mode?: 'single' | 'range';\n disabled?: boolean;\n}\n\nfunction getDayClassName(day: Date, selected: Date | undefined): string {\n const classes: string[] = ['gantt-day-btn'];\n\n if (selected && isSameDay(day, selected)) classes.push('selected');\n if (isToday(day)) classes.push('today');\n if (isWeekend(day)) classes.push('weekend');\n if (isBefore(day, startOfDay(new Date())) && !isToday(day)) classes.push('past');\n\n return classes.join(' ');\n}\n\nexport const Calendar: React.FC<CalendarProps> = ({\n selected,\n onSelect,\n initialDate,\n mode = 'single',\n disabled = false,\n}) => {\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const initialMonth = useMemo(\n () => startOfMonth(initialDate ?? selected ?? new Date()),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n const [months, setMonths] = useState<Date[]>(() => [\n subMonths(initialMonth, 1),\n initialMonth,\n addMonths(initialMonth, 1),\n ]);\n\n const loadMoreMonths = useCallback((direction: 'up' | 'down') => {\n setMonths((prev) => {\n if (direction === 'up') {\n return [subMonths(prev[0], 1), ...prev];\n } else {\n return [...prev, addMonths(prev[prev.length - 1], 1)];\n }\n });\n }, []);\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n if (container.scrollTop <= 100) {\n const prevScrollHeight = container.scrollHeight;\n const prevScrollTop = container.scrollTop;\n loadMoreMonths('up');\n setTimeout(() => {\n container.scrollTop =\n container.scrollHeight - prevScrollHeight + prevScrollTop;\n }, 0);\n } else if (\n container.scrollTop + container.clientHeight >=\n container.scrollHeight - 100\n ) {\n loadMoreMonths('down');\n }\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, [loadMoreMonths]);\n\n // Scroll to the selected/initial month on mount\n useEffect(() => {\n if (!scrollRef.current) return;\n const target = selected ?? initialDate ?? new Date();\n const monthKey = format(startOfMonth(target), 'yyyy-MM');\n const el = scrollRef.current.querySelector(`[data-month=\"${monthKey}\"]`);\n if (el) {\n (el as HTMLElement).scrollIntoView({ behavior: 'auto', block: 'start' });\n }\n // Run once on mount only\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const renderMonth = useCallback(\n (month: Date) => {\n const firstDay = startOfMonth(month);\n const totalDays = getDaysInMonth(month);\n // Monday-first: Sunday (0) -> 6, Monday (1) -> 0, ...\n const emptyDays = (getDay(firstDay) + 6) % 7;\n const monthKey = format(month, 'yyyy-MM');\n const monthLabel = format(month, 'LLLL yyyy', { locale: ru });\n\n const emptyCells = Array.from({ length: emptyDays }, (_, i) => (\n <div key={`e-${i}`} className=\"gantt-cal-empty-day\" />\n ));\n\n const dayCells = Array.from({ length: totalDays }, (_, i) => {\n const dayNum = i + 1;\n const day = new Date(month.getFullYear(), month.getMonth(), dayNum);\n const className = getDayClassName(day, selected);\n return (\n <button\n key={dayNum}\n type=\"button\"\n className={className}\n disabled={disabled}\n onClick={() => {\n if (!disabled && onSelect) {\n onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));\n }\n }}\n >\n {dayNum}\n </button>\n );\n });\n\n return (\n <div key={monthKey} className=\"gantt-cal-month\" data-month={monthKey}>\n <div className=\"gantt-cal-month-header\">{monthLabel}</div>\n <div className=\"gantt-cal-month-days\">\n {emptyCells}\n {dayCells}\n </div>\n </div>\n );\n },\n [selected, onSelect, disabled]\n );\n\n const renderedMonths = useMemo(\n () => months.map(renderMonth),\n [months, renderMonth]\n );\n\n const handleDayShift = useCallback(\n (deltaDays: number) => {\n if (!onSelect || disabled) return;\n const baseDate = selected ?? new Date();\n onSelect(addDays(baseDate, deltaDays));\n },\n [onSelect, selected, disabled]\n );\n\n const handleToday = useCallback(() => {\n if (!onSelect || disabled) return;\n onSelect(new Date());\n }, [onSelect, disabled]);\n\n return (\n <div ref={scrollRef} className=\"gantt-cal-container\">\n {renderedMonths}\n <div className=\"gantt-cal-nav\">\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(-7)}\n disabled={disabled}\n >\n -7\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(-1)}\n disabled={disabled}\n >\n -1\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={handleToday}\n disabled={disabled}\n >\n Сегодня\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(1)}\n disabled={disabled}\n >\n +1\n </button>\n <button\n type=\"button\"\n className=\"gantt-btn gantt-btn-sm\"\n onClick={() => handleDayShift(7)}\n disabled={disabled}\n >\n +7\n </button>\n </div>\n </div>\n );\n};\n\nCalendar.displayName = 'Calendar';\nexport default Calendar;\n","import React from 'react';\nimport type { LinkType } from '../../types';\n\nconst DepIconFS = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m10 15 5 5 5-5\" /><path d=\"M4 4h7a4 4 0 0 1 4 4v12\" />\n </svg>\n);\n\nconst DepIconSS = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 5v14\" /><path d=\"M21 12H7\" /><path d=\"m15 18 6-6-6-6\" />\n </svg>\n);\n\nconst DepIconFF = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M17 12H3\" /><path d=\"m11 18 6-6-6-6\" /><path d=\"M21 5v14\" />\n </svg>\n);\n\nconst DepIconSF = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"m14 15-5 5-5-5\" /><path d=\"M20 4h-7a4 4 0 0 0-4 4v12\" />\n </svg>\n);\n\nexport const LINK_TYPE_ICONS: Record<LinkType, React.FC> = {\n FS: DepIconFS,\n SS: DepIconSS,\n FF: DepIconFF,\n SF: DepIconSF,\n};\n\nexport const LINK_TYPE_LABELS: Record<LinkType, string> = {\n FS: 'Окончание-начало',\n SS: 'Начало-начало',\n FF: 'Окончание-окончание',\n SF: 'Начало-окончание',\n};\n","'use client';\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport { Input } from '../ui/Input';\n\ninterface NewTaskRowProps {\n rowHeight: number;\n onConfirm: (name: string) => void;\n onCancel: () => void;\n}\n\nexport const NewTaskRow: React.FC<NewTaskRowProps> = ({ rowHeight, onConfirm, onCancel }) => {\n const [nameValue, setNameValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n const confirmedRef = useRef(false);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, []);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n if (nameValue.trim()) {\n confirmedRef.current = true;\n onConfirm(nameValue.trim());\n } else {\n onCancel();\n }\n } else if (e.key === 'Escape') {\n onCancel();\n }\n };\n\n const handleBlur = () => {\n if (confirmedRef.current) return; // already confirmed via Enter\n if (nameValue.trim()) {\n confirmedRef.current = true;\n onConfirm(nameValue.trim());\n } else {\n onCancel();\n }\n };\n\n return (\n <div className=\"gantt-tl-row gantt-tl-row-new\" style={{ minHeight: `${rowHeight}px` }}>\n <div className=\"gantt-tl-cell gantt-tl-cell-number\" />\n <div className=\"gantt-tl-cell gantt-tl-cell-name gantt-tl-cell-new-name\">\n <Input\n ref={inputRef}\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n placeholder=\"Название\"\n className=\"gantt-tl-name-input\"\n />\n </div>\n <div className=\"gantt-tl-cell\" />\n <div className=\"gantt-tl-cell\" />\n <div className=\"gantt-tl-cell\" />\n </div>\n );\n};\n\nexport default NewTaskRow;\n","'use client';\n\nimport React from 'react';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual variant */\n variant?: 'default' | 'ghost' | 'outline';\n /** Size variant */\n size?: 'default' | 'sm' | 'icon';\n /** Additional CSS class names */\n className?: string;\n}\n\n/**\n * Simple button component for calendar navigation and UI actions\n */\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'default', size = 'default', children, ...props }, ref) => {\n const classes = [\n 'gantt-btn',\n variant !== 'default' ? `gantt-btn-${variant}` : '',\n size !== 'default' ? `gantt-btn-${size}` : '',\n className || '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button ref={ref} className={classes} {...props}>\n {children}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\nexport default Button;\n"],"mappings":"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","names":["import_react","startOfMonth","isWeekend","import_react","isWeekend","import_react","dayWidth","getUTCDayDifference","currentTask","import_jsx_runtime","React","import_react","import_jsx_runtime","import_react","import_jsx_runtime","arePropsEqual","React","import_jsx_runtime","import_react","import_jsx_runtime","React","lines","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","React","import_react","import_date_fns","import_react","import_date_fns","import_locale","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","newProgress","filteredTasks","tasks","import_react","import_jsx_runtime","React"]}