gantt-lib 0.71.1 → 0.71.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/core/scheduling/dateMath.ts","../src/utils/dateUtils.ts","../src/index.ts","../src/components/GanttChart/GanttChart.tsx","../src/core/scheduling/index.ts","../src/core/scheduling/dependencies.ts","../src/core/scheduling/cascade.ts","../src/core/scheduling/hierarchy.ts","../src/core/scheduling/commands.ts","../src/core/scheduling/execute.ts","../src/core/scheduling/validation.ts","../src/utils/hierarchyOrder.ts","../src/components/TimeScaleHeader/TimeScaleHeader.tsx","../src/components/TaskRow/TaskRow.tsx","../src/utils/geometry.ts","../src/utils/expired.ts","../src/utils/taskType.ts","../src/hooks/useTaskDrag.ts","../src/adapters/scheduling/drag.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/utils/taskListReorder.ts","../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/TaskList/columns/createBuiltInColumns.tsx","../src/components/TaskList/columns/resolveTaskListColumns.ts","../src/components/ui/Button.tsx","../src/utils/index.ts","../src/filters/index.ts"],"sourcesContent":["/**\n * Pure date math utilities for the core scheduling module.\n * Zero React/DOM/date-fns dependencies.\n *\n * Functions moved from:\n * - dependencyUtils.ts: normalizeUTCDate, parseDateOnly, getBusinessDayOffset, shiftBusinessDayOffset, DAY_MS\n * - dateUtils.ts: getBusinessDaysCount, addBusinessDays, subtractBusinessDays\n */\n\nexport const DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Normalize a Date to UTC midnight (hours/minutes/seconds zeroed).\n */\nexport function normalizeUTCDate(date: Date): Date {\n return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));\n}\n\n/**\n * Parse a date string or Date object to a UTC midnight Date.\n * Handles ISO strings like \"2025-01-15\" by appending T00:00:00.000Z.\n */\nexport function parseDateOnly(date: string | Date): Date {\n const parsed = typeof date === 'string'\n ? new Date(`${date.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(date);\n return normalizeUTCDate(parsed);\n}\n\n/**\n * Compute the business-day offset between two dates.\n * Steps through each calendar day, counting only non-weekend days.\n * Returns a positive number if toDate > fromDate, negative if toDate < fromDate.\n */\nexport function getBusinessDayOffset(\n fromDate: Date,\n toDate: Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n const from = normalizeUTCDate(fromDate);\n const to = normalizeUTCDate(toDate);\n\n if (from.getTime() === to.getTime()) {\n return 0;\n }\n\n const step = to.getTime() > from.getTime() ? 1 : -1;\n const current = new Date(from);\n let offset = 0;\n\n while (current.getTime() !== to.getTime()) {\n current.setUTCDate(current.getUTCDate() + step);\n if (!weekendPredicate(current)) {\n offset += step;\n }\n }\n\n return offset;\n}\n\n/**\n * Shift a date by a business-day offset, skipping weekends.\n */\nexport function shiftBusinessDayOffset(\n date: Date,\n offset: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const current = normalizeUTCDate(date);\n\n if (offset === 0) {\n return current;\n }\n\n const step = offset > 0 ? 1 : -1;\n let remaining = Math.abs(offset);\n\n while (remaining > 0) {\n current.setUTCDate(current.getUTCDate() + step);\n if (!weekendPredicate(current)) {\n remaining--;\n }\n }\n\n return current;\n}\n\n/**\n * Count business days between two dates (inclusive), excluding weekends.\n * Returns minimum 1.\n */\nexport function getBusinessDaysCount(\n startDate: string | Date,\n endDate: string | Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n const start = typeof startDate === 'string'\n ? new Date(`${startDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(startDate);\n const end = typeof endDate === 'string'\n ? new Date(`${endDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(endDate);\n\n let count = 0;\n const current = new Date(start);\n\n while (current.getTime() <= end.getTime()) {\n if (!weekendPredicate(current)) {\n count++;\n }\n current.setUTCDate(current.getUTCDate() + 1);\n }\n\n return Math.max(1, count);\n}\n\n/**\n * Calculate end date by adding N business days to start date.\n * Returns a Date object.\n */\nexport function addBusinessDays(\n startDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const start = typeof startDate === 'string'\n ? new Date(`${startDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(startDate);\n const current = new Date(start);\n let targetDays = Math.max(1, businessDays);\n let businessDaysCounted = 0;\n\n while (businessDaysCounted < targetDays) {\n if (!weekendPredicate(current)) {\n businessDaysCounted++;\n }\n if (businessDaysCounted < targetDays) {\n current.setUTCDate(current.getUTCDate() + 1);\n }\n }\n\n return current;\n}\n\n/**\n * Calculate start date by subtracting N business days from end date.\n * Returns a Date object.\n */\nexport function subtractBusinessDays(\n endDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const end = typeof endDate === 'string'\n ? new Date(`${endDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(endDate);\n const current = new Date(end);\n let targetDays = Math.max(1, businessDays);\n let businessDaysCounted = 0;\n\n while (businessDaysCounted < targetDays) {\n if (!weekendPredicate(current)) {\n businessDaysCounted++;\n }\n if (businessDaysCounted < targetDays) {\n current.setUTCDate(current.getUTCDate() - 1);\n }\n }\n\n return current;\n}\n\n/**\n * Snap a date to the nearest working day in the given direction.\n */\nexport function alignToWorkingDay(\n date: Date,\n direction: 1 | -1,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const current = normalizeUTCDate(date);\n\n while (weekendPredicate(current)) {\n current.setUTCDate(current.getUTCDate() + direction);\n }\n\n return current;\n}\n\n/**\n * Get task duration in days (inclusive).\n * If businessDays mode, counts business days using weekendPredicate.\n * Otherwise, counts calendar days.\n */\nexport function getTaskDuration(\n startDate: string | Date,\n endDate: string | Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\n const start = parseDateOnly(startDate);\n const end = parseDateOnly(endDate);\n\n if (businessDays && weekendPredicate) {\n return getBusinessDaysCount(start, end, weekendPredicate);\n }\n\n return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1);\n}\n","import { parseISO, isValid } from 'date-fns';\nimport {\n getBusinessDaysCount as coreGetBusinessDaysCount,\n addBusinessDays as coreAddBusinessDays,\n subtractBusinessDays as coreSubtractBusinessDays,\n} from '../core/scheduling/dateMath';\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 * Create a UTC-safe key for Set-based date lookup\n * @param date - Date object to create key from\n * @returns String key in \"YYYY-M-D\" format using UTC date components\n *\n * Example:\n * createDateKey(new Date(Date.UTC(2026, 2, 15))) // \"2026-2-15\"\n *\n * Note: Uses UTC methods to prevent DST and timezone issues.\n * Month is 0-indexed (0=January, 11=December) per JavaScript Date convention.\n */\nexport const createDateKey = (date: Date): string => {\n return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;\n};\n\n/**\n * Configuration for a single custom day\n */\nexport interface CustomDayConfig {\n /** The date to customize */\n date: Date;\n /** Type of day: 'weekend' marks as weekend, 'workday' marks as workday */\n type: 'weekend' | 'workday';\n}\n\n/**\n * Configuration for custom day predicate\n */\nexport interface CustomDayPredicateConfig {\n /** Array of custom day configurations with explicit types */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate (checked before customDays overrides) */\n isWeekend?: (date: Date) => boolean;\n}\n\n/**\n * Create a weekend predicate with unified custom day support\n *\n * Precedence order (highest to lowest):\n * 1. customDays.type='workday' - explicit workday (highest override)\n * 2. customDays.type='weekend' - explicit weekend (override)\n * 3. isWeekend (base predicate) - custom base logic\n * 4. default - Saturday (6) and Sunday (0)\n *\n * @param config - Custom day configuration with array and optional predicate\n * @returns Predicate function (date: Date) => boolean\n *\n * Example:\n * // Simple holidays + working Saturdays\n * const predicate = createCustomDayPredicate({\n * customDays: [\n * { date: new Date(Date.UTC(2026, 2, 15)), type: 'workday' }, // working Saturday\n * { date: new Date(Date.UTC(2026, 0, 1)), type: 'weekend' } // holiday Tuesday\n * ]\n * });\n *\n * // 4-day work week + occasional overrides\n * const predicate2 = createCustomDayPredicate({\n * isWeekend: (date) => {\n * const day = date.getUTCDay();\n * return day === 0 || day === 6 || day === 5; // Sun+Sat+Fri\n * },\n * customDays: [\n * { date: new Date(Date.UTC(2026, 2, 10)), type: 'workday' } // working Friday\n * ]\n * });\n */\nexport const createCustomDayPredicate = (\n config: CustomDayPredicateConfig\n): ((date: Date) => boolean) => {\n const { customDays, isWeekend: basePredicate } = config;\n\n // Build Set-based lookups for O(1) performance\n const workdaySet = new Set<string>();\n const weekendSet = new Set<string>();\n\n if (customDays && customDays.length > 0) {\n for (const item of customDays) {\n const key = createDateKey(item.date);\n if (item.type === 'workday') {\n workdaySet.add(key);\n } else { // weekend\n weekendSet.add(key);\n }\n }\n }\n\n return (date: Date): boolean => {\n const key = createDateKey(date);\n\n // Priority 1: customDays workdays (highest override)\n if (workdaySet.has(key)) {\n return false; // Explicitly a workday\n }\n\n // Priority 2: customDays weekends (override)\n if (weekendSet.has(key)) {\n return true; // Explicitly a weekend\n }\n\n // Priority 3: base predicate (if provided)\n if (basePredicate) {\n return basePredicate(date);\n }\n\n // Priority 4: default Saturday/Sunday\n const dayOfWeek = date.getUTCDay();\n return dayOfWeek === 0 || dayOfWeek === 6;\n };\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\n/**\n * Russian month abbreviations (genitive case for dates)\n */\nconst MONTH_ABBR = [\n 'янв', 'фев', 'мар', 'апр', 'мая', 'июн',\n 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'\n];\n\n/**\n * Format date range smartly in Russian.\n * Examples:\n * - Same month: \"1-3 мая\"\n * - Different months same year: \"15 апр - 7 июн\"\n * - Different years: \"15 дек 2025 - 7 янв 2026\"\n *\n * @param startDate - Start date\n * @param endDate - End date\n * @returns Formatted date range string\n */\nexport const formatDateRangeLabel = (\n startDate: Date | string,\n endDate: Date | string\n): string => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n\n const startDay = start.getUTCDate();\n const endDay = end.getUTCDate();\n const startMonth = start.getUTCMonth();\n const endMonth = end.getUTCMonth();\n const startYear = start.getUTCFullYear();\n const endYear = end.getUTCFullYear();\n\n // Same month and year: \"1-3 мая\"\n if (startMonth === endMonth && startYear === endYear) {\n if (startDay === endDay) {\n return `${startDay} ${MONTH_ABBR[startMonth]}`;\n }\n return `${startDay}–${endDay} ${MONTH_ABBR[startMonth]}`;\n }\n\n // Same year: \"15 апр–7 июн\"\n if (startYear === endYear) {\n return `${startDay} ${MONTH_ABBR[startMonth]}–${endDay} ${MONTH_ABBR[endMonth]}`;\n }\n\n // Different years: \"15 дек 2025–7 янв 2026\"\n return `${startDay} ${MONTH_ABBR[startMonth]} ${startYear}–${endDay} ${MONTH_ABBR[endMonth]} ${endYear}`;\n};\n\n/**\n * Return block boundaries for week-view, splitting on month boundaries.\n * Each block represents a column in the week-view header.\n * Blocks are typically 7 days, but split on month boundaries so\n * the first/last block of a month may be smaller.\n *\n * @param days - Array of dates from getMultiMonthDays\n * @returns Array of start dates for each block, with actual block sizes\n */\nexport interface WeekBlock {\n /** Start date of this block */\n startDate: Date;\n /** Number of days in this block (≤7, splits on month boundaries) */\n days: number;\n}\n\n/**\n * Split the date range into blocks, primarily 7-day weeks,\n * but splitting blocks on month boundaries for accurate month spans.\n */\nexport const getWeekBlocks = (days: Date[]): WeekBlock[] => {\n if (days.length === 0) return [];\n\n const blocks: WeekBlock[] = [];\n let blockStart = 0;\n\n while (blockStart < days.length) {\n // Target: 7-day block, but check for month boundary within\n const maxBlockEnd = Math.min(blockStart + 7, days.length);\n const startMonthYear = `${days[blockStart].getUTCFullYear()}-${days[blockStart].getUTCMonth()}`;\n\n let actualBlockEnd = blockStart + 7; // Default to full week\n if (actualBlockEnd > days.length) {\n actualBlockEnd = days.length;\n }\n\n // Check if month boundary falls within the 7-day window\n for (let i = blockStart + 1; i < maxBlockEnd; i++) {\n const monthYear = `${days[i].getUTCFullYear()}-${days[i].getUTCMonth()}`;\n if (monthYear !== startMonthYear) {\n // Split at month boundary\n actualBlockEnd = i;\n break;\n }\n }\n\n blocks.push({\n startDate: days[blockStart],\n days: actualBlockEnd - blockStart,\n });\n\n blockStart = actualBlockEnd;\n }\n\n return blocks;\n};\n\n/**\n * Represents a month span in week-view header row 1.\n * In week-view, the width is calculated from actual day counts,\n * not from a fixed column count.\n */\nexport interface WeekSpan {\n /** First day of the calendar month (UTC) */\n month: Date;\n /** Total number of days this month occupies across all blocks */\n days: number;\n /** Start index in the blocks array */\n startIndex: number;\n}\n\n/**\n * Calculate month spans based on week-block boundaries.\n * Groups consecutive blocks that belong to the same month.\n */\nexport const getWeekSpans = (days: Date[]): WeekSpan[] => {\n const blocks = getWeekBlocks(days);\n if (blocks.length === 0) return [];\n\n const spans: WeekSpan[] = [];\n let currentMonthYear = `${blocks[0].startDate.getUTCFullYear()}-${blocks[0].startDate.getUTCMonth()}`;\n let startIndex = 0;\n let totalDays = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const monthYear = `${block.startDate.getUTCFullYear()}-${block.startDate.getUTCMonth()}`;\n\n if (monthYear !== currentMonthYear) {\n // Finalize previous month span\n spans.push({\n month: new Date(Date.UTC(\n blocks[startIndex].startDate.getUTCFullYear(),\n blocks[startIndex].startDate.getUTCMonth(),\n 1\n )),\n days: totalDays,\n startIndex,\n });\n currentMonthYear = monthYear;\n startIndex = i;\n totalDays = 0;\n }\n\n totalDays += block.days;\n\n if (i === blocks.length - 1) {\n spans.push({\n month: new Date(Date.UTC(\n block.startDate.getUTCFullYear(),\n block.startDate.getUTCMonth(),\n 1\n )),\n days: totalDays,\n startIndex,\n });\n }\n }\n\n return spans;\n};\n\nexport interface MonthBlock {\n /** Первый день месяца (UTC) */\n startDate: Date;\n /** Количество дней в этом месяце внутри dateRange (может быть меньше при обрезке) */\n days: number;\n}\n\n/**\n * Разбивает dateRange на блоки по месяцам.\n * Каждый блок = один месяц (колонка в строке 2 month-view шапки).\n * Блок на краях может быть неполным если dateRange начинается/заканчивается не с 1-го числа.\n */\nexport const getMonthBlocks = (days: Date[]): MonthBlock[] => {\n if (days.length === 0) return [];\n // Переиспользуем getMonthSpans — его структура совпадает с MonthBlock\n return getMonthSpans(days).map(span => ({\n startDate: span.month,\n days: span.days,\n }));\n};\n\nexport interface YearSpan {\n /** 1 января года (UTC) */\n year: Date;\n /** Суммарное кол-во дней этого года внутри dateRange */\n days: number;\n /** Начальный индекс в массиве monthBlocks */\n startIndex: number;\n}\n\n/**\n * Группирует month-блоки по годам.\n * Используется в строке 1 month-view шапки (year label).\n */\nexport const getYearSpans = (days: Date[]): YearSpan[] => {\n const blocks = getMonthBlocks(days);\n if (blocks.length === 0) return [];\n\n const spans: YearSpan[] = [];\n let currentYear = blocks[0].startDate.getUTCFullYear();\n let startIndex = 0;\n let totalDays = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const blockYear = blocks[i].startDate.getUTCFullYear();\n if (blockYear !== currentYear) {\n spans.push({\n year: new Date(Date.UTC(currentYear, 0, 1)),\n days: totalDays,\n startIndex,\n });\n currentYear = blockYear;\n startIndex = i;\n totalDays = 0;\n }\n totalDays += blocks[i].days;\n if (i === blocks.length - 1) {\n spans.push({\n year: new Date(Date.UTC(currentYear, 0, 1)),\n days: totalDays,\n startIndex,\n });\n }\n }\n\n return spans;\n};\n\n/**\n * Normalize task dates to ensure startDate is always before or equal to endDate.\n * If dates are swapped (endDate < startDate), they are automatically swapped.\n * @param startDate - Task start date (string or Date)\n * @param endDate - Task end date (string or Date)\n * @returns Object with normalized startDate and endDate as ISO date strings (YYYY-MM-DD)\n */\nexport const normalizeTaskDates = (\n startDate: string | Date,\n endDate: string | Date\n): { startDate: string; endDate: string } => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n\n // If dates are swapped, return them in correct order\n if (end.getTime() < start.getTime()) {\n return {\n startDate: end.toISOString().split('T')[0],\n endDate: start.toISOString().split('T')[0],\n };\n }\n\n // Dates are already in correct order\n return {\n startDate: start.toISOString().split('T')[0],\n endDate: end.toISOString().split('T')[0],\n };\n};\n\n/**\n * Count business days between two dates (inclusive), excluding weekends\n * Delegates to core/scheduling/dateMath for implementation.\n * @param startDate - Start date (string or Date)\n * @param endDate - End date (string or Date)\n * @param weekendPredicate - Function that returns true for weekends\n * @returns Number of business days (minimum 1)\n */\nexport function getBusinessDaysCount(\n startDate: string | Date,\n endDate: string | Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n return coreGetBusinessDaysCount(startDate, endDate, weekendPredicate);\n}\n\n/**\n * Calculate end date by adding business days to start date.\n * Delegates to core/scheduling/dateMath, converts Date result to string.\n * @returns End date as YYYY-MM-DD string\n */\nexport function addBusinessDays(\n startDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): string {\n const result = coreAddBusinessDays(startDate, businessDays, weekendPredicate);\n return result.toISOString().split('T')[0];\n}\n\n/**\n * Subtract business days from a date (inverse of addBusinessDays).\n * Delegates to core/scheduling/dateMath, converts Date result to string.\n * @returns Start date as YYYY-MM-DD string\n */\nexport function subtractBusinessDays(\n endDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): string {\n const result = coreSubtractBusinessDays(endDate, businessDays, weekendPredicate);\n return result.toISOString().split('T')[0];\n}\n","'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// Filters\nexport * from './filters';\n\n// TaskList Column API\nexport type {\n BuiltInTaskListColumnId,\n TaskListColumn,\n TaskListColumnContext,\n} from './components/TaskList/columns/types';\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, createCustomDayPredicate, type CustomDayConfig, type CustomDayPredicateConfig } from '../../utils/dateUtils';\nimport { calculateGridWidth } from '../../utils/geometry';\nimport { validateDependencies, cascadeByLinks, universalCascade, computeParentDates, computeParentProgress, getChildren, removeDependenciesBetweenTasks, isTaskParent } from '../../core/scheduling';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport type { ValidationResult } from '../../types';\nimport { TaskPredicate } from '../../filters';\nimport type { TaskListColumn } from '../TaskList/columns/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\nconst SCROLL_TO_ROW_CONTEXT_ROWS = 2;\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 /**\n * Optional task subtype. Milestones are single-date tasks and default to\n * regular 'task' behavior when omitted.\n */\n type?: 'task' | 'milestone';\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 required (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 /** Lag in days */\n lag: number;\n}\n\nexport interface GanttChartProps<TTask extends Task = Task> {\n /** Array of tasks to display */\n tasks: TTask[];\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. Receives ONLY the changed tasks as full objects with all properties. */\n onTasksChange?: (tasks: TTask[]) => 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: TTask[]) => 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: TTask) => 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: TTask) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: TTask[], movedTaskId?: string, inferredParentId?: string) => void;\n /** Callback when a task is promoted (parentId removed). If not provided, default internal logic is used. */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n /** View mode: 'day' renders one column per day, 'week' renders one column per 7 days, 'month' renders one column per month (default: 'day') */\n viewMode?: 'day' | 'week' | 'month';\n /** Custom day configurations with explicit type (weekend or workday) */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate (checked before customDays overrides) */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях, исключая выходные (default: true) */\n businessDays?: boolean;\n /**\n * Optional predicate to mark tasks in the current view.\n * Matching tasks stay visible and are highlighted in the chart and task list.\n * Dependencies are still computed on ALL tasks (normalizedTasks).\n */\n taskFilter?: TaskPredicate;\n /** Filter mode: 'highlight' shows all tasks with yellow highlight on matches, 'hide' hides non-matching tasks (default: 'highlight') */\n filterMode?: 'highlight' | 'hide';\n /** Set of collapsed parent task IDs for controlled mode */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked (controlled mode) */\n onToggleCollapse?: (parentId: string) => void;\n /** Task IDs to highlight in the task list (for search results) */\n highlightedTaskIds?: Set<string>;\n /** Disable task drag and resize on the calendar grid (default: false) */\n disableTaskDrag?: boolean;\n /** Show calendar chart area (default: true) */\n showChart?: boolean;\n /** Additional custom columns to render in the TaskList after built-in columns */\n additionalColumns?: TaskListColumn<TTask>[];\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 scrollToRow: (taskId: string) => void;\n collapseAll: () => void;\n expandAll: () => 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 */\nfunction GanttChartInner<TTask extends Task = Task>(\n props: GanttChartProps<TTask>,\n ref: React.ForwardedRef<GanttChartHandle>\n) {\n const {\n tasks,\n dayWidth = 40,\n rowHeight = 40,\n headerHeight = 40,\n containerHeight,\n onTasksChange,\n onValidateDependencies,\n enableAutoSchedule,\n disableConstraints,\n onCascade,\n showTaskList = false,\n taskListWidth = 660,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n highlightExpiredTasks = false,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n onPromoteTask,\n onDemoteTask,\n enableAddTask = true,\n viewMode = 'day',\n customDays,\n isWeekend,\n businessDays = true,\n taskFilter,\n filterMode = 'highlight',\n collapsedParentIds: externalCollapsedParentIds,\n onToggleCollapse: externalOnToggleCollapse,\n highlightedTaskIds,\n disableTaskDrag = false,\n showChart = true,\n additionalColumns,\n } = props;\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 const [taskListHasRightShadow, setTaskListHasRightShadow] = useState(false);\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 (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 // 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 // Create custom weekend predicate from props (memoized for performance)\n const isCustomWeekend = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\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 // Visible tasks are determined by collapsed parent state and optionally by filter mode.\n // Checks the full ancestor chain so grandchildren are hidden when any ancestor is collapsed.\n const visibleTasks = useMemo(() => {\n const parentMap = new Map(normalizedTasks.map(t => [t.id, t.parentId]));\n\n function isAnyAncestorCollapsed(parentId: string | undefined): boolean {\n let current = parentId;\n while (current) {\n if (collapsedParentIds.has(current)) return true;\n current = parentMap.get(current);\n }\n return false;\n }\n\n let tasks = normalizedTasks.filter(task => !isAnyAncestorCollapsed(task.parentId));\n\n // In 'hide' mode with active filter, only show matching tasks\n if (filterMode === 'hide' && taskFilter) {\n tasks = tasks.filter(taskFilter);\n }\n\n return tasks;\n }, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);\n\n const matchedTaskIds = useMemo(() => {\n if (!taskFilter) return new Set<string>();\n return new Set(visibleTasks.filter(taskFilter).map(task => task!.id));\n }, [visibleTasks, taskFilter]);\n\n const taskListHighlightedTaskIds = useMemo(() => {\n // In hide mode, no highlighting needed - all visible tasks already match the filter\n if (filterMode === 'hide') {\n return new Set<string>();\n }\n if ((!highlightedTaskIds || highlightedTaskIds.size === 0) && matchedTaskIds.size === 0) {\n return new Set<string>();\n }\n\n const mergedHighlightedTaskIds = new Set(highlightedTaskIds ?? []);\n matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));\n return mergedHighlightedTaskIds;\n }, [filterMode, highlightedTaskIds, matchedTaskIds]);\n\n // Calculate total grid height from currently visible rows.\n const totalGridHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.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 // Position today at ~30% of visible area (closer to task list side)\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset + (dayWidth / 2) - containerWidth * 0.3);\n\n container.scrollLeft = Math.max(0, scrollLeft);\n }, []); // Empty deps array - run only on mount\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const updateShadow = () => {\n setTaskListHasRightShadow(container.scrollLeft > 0);\n };\n\n updateShadow();\n container.addEventListener('scroll', updateShadow, { passive: true });\n return () => {\n container.removeEventListener('scroll', updateShadow);\n };\n }, []);\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 // Position today at ~30% of visible area (closer to task list side)\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset + (dayWidth / 2) - containerWidth * 0.3);\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 const scrollToRow = useCallback((taskId: string) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n\n const rowIndex = visibleTasks.findIndex(visibleTask => visibleTask.id === task.id);\n if (rowIndex === -1) return;\n\n const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);\n const scrollTop = Math.max(0, rowHeight * paddedRowIndex);\n setSelectedTaskId(taskId);\n container.scrollTo({ top: scrollTop, behavior: 'smooth' });\n }, [tasks, visibleTasks, rowHeight]);\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 const [previewTasksById, setPreviewTasksById] = useState<Map<string, Task>>(new Map());\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 * Callback when tasks are modified.\n * Always receives ONLY the changed tasks as full objects with all properties.\n * Single task = array of 1 element (batch of size 1).\n */\n const handleTaskChange = useCallback((updatedTasks: Task[]) => {\n const updatedTask = updatedTasks[0];\n if (!updatedTask) return;\n const originalTask = tasks.find(t => t.id === updatedTask.id);\n if (!originalTask) {\n // New task or task not found - pass all tasks as-is\n onTasksChange?.(updatedTasks as TTask[]);\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 // Special case: parent progress cascade (multiple tasks, no date changes)\n if (updatedTasks.length > 1) {\n onTasksChange?.(updatedTasks as TTask[]);\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n // Single task without date changes - compute parent progress if needed\n const taskParentId = (updatedTask as any).parentId;\n if (taskParentId) {\n const parentProgress = computeParentProgress(taskParentId, tasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n const parentTask = tasks.find(t => t.id === taskParentId);\n if (parentTask) {\n const updatedParent = { ...parentTask, progress: parentProgress };\n onTasksChange?.([updatedTask, updatedParent] as TTask[]);\n } else {\n onTasksChange?.([updatedTask] as TTask[]);\n }\n } else {\n onTasksChange?.([updatedTask] as TTask[]);\n }\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n // Date edits should behave the same across chart drag and task-list picker:\n // moving a parent shifts its descendants, and parent dates are then re-derived\n // from the shifted children inside universalCascade.\n const sourceTasks = tasks.map((task) => (\n task.id === updatedTask.id ? updatedTask : task\n ));\n\n const cascadedTasks = disableConstraints\n ? [updatedTask]\n : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);\n\n onTasksChange?.(cascadedTasks as TTask[]);\n }, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);\n\n /**\n * Handle task deletion: collect all changed tasks (with cleaned dependencies),\n * emit onTasksChange with them, then emit onDelete for each deleted task ID\n * (original + all descendants) so the consumer can remove all of them.\n * For parent tasks, cascade delete to all children.\n */\n const handleDelete = useCallback((taskId: string) => {\n const toDelete = new Set<string>([taskId]);\n\n function collectDescendants(parentId: string) {\n const children = getChildren(parentId, tasks);\n children.forEach(child => {\n toDelete.add(child.id);\n collectDescendants(child.id);\n });\n }\n\n collectDescendants(taskId);\n\n const changedTasks: Task[] = [];\n tasks.forEach(task => {\n if (toDelete.has(task.id)) return;\n\n if (task.dependencies && task.dependencies.some(dep => toDelete.has(dep.taskId))) {\n changedTasks.push({\n ...task,\n dependencies: task.dependencies.filter(dep => !toDelete.has(dep.taskId))\n });\n }\n });\n\n if (changedTasks.length > 0) {\n onTasksChange?.(changedTasks as TTask[]);\n }\n\n // Call onDelete for each task in the cascade set (original + all descendants)\n // so the consumer removes all of them, not just the root.\n toDelete.forEach(id => onDelete?.(id));\n }, [tasks, onTasksChange, onDelete]);\n\n /**\n * Handle task insertion after inline draft confirmation.\n * The task name is already confirmed inside TaskList, so no auto-edit is needed here.\n */\n const handleInsertAfter = useCallback((taskId: string, newTask: Task) => {\n onInsertAfter?.(taskId, newTask as TTask);\n }, [onInsertAfter]);\n\n /**\n * Handle task reordering.\n *\n * Preferred path: emit a single onReorder callback with the full normalized task array.\n * Backward-compatibility path: if onReorder is not provided, fall back to onTasksChange.\n *\n * This avoids duplicate reorder notifications for consumers that already opted into\n * the dedicated reorder API while preserving legacy consumers that only listen to\n * onTasksChange.\n */\n const handleReorder = useCallback((reorderedTasks: Task[], movedTaskId?: string, inferredParentId?: string) => {\n let updated = reorderedTasks;\n if (movedTaskId) {\n updated = updated.map(t => {\n if (t.id === movedTaskId) {\n return { ...t, parentId: inferredParentId || undefined };\n }\n return t;\n });\n }\n\n const normalized = normalizeHierarchyTasks(updated);\n if (onReorder) {\n onReorder(normalized as TTask[], movedTaskId, inferredParentId);\n return;\n }\n\n onTasksChange?.(normalized as TTask[]);\n }, [onTasksChange, 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((\n overrides: Map<string, { left: number; width: number }>,\n previewTasks: Task[] = []\n ) => {\n setCascadeOverrides(new Map(overrides));\n setPreviewTasksById(new Map(previewTasks.map(task => [task.id, task])));\n }, []);\n\n const previewNormalizedTasks = useMemo(() => {\n if (previewTasksById.size === 0) return normalizedTasks;\n return normalizedTasks.map(task => previewTasksById.get(task.id) ?? task);\n }, [normalizedTasks, previewTasksById]);\n\n const previewVisibleTasks = useMemo(() => {\n if (previewTasksById.size === 0) return visibleTasks;\n return visibleTasks.map(task => previewTasksById.get(task.id) ?? task);\n }, [visibleTasks, previewTasksById]);\n\n /**\n * Handle cascade completion — emit all changed tasks.\n * Parent tasks are computed from children - don't send them in batch.\n */\n const handleCascade = useCallback((cascadedTasks: Task[]) => {\n // Backend should compute parent dates from children\n onTasksChange?.(cascadedTasks as TTask[]);\n }, [tasks, onTasksChange]);\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 // 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 // Get all parent task IDs (tasks that have children)\n const allParentIds = useMemo(() => {\n return new Set(\n normalizedTasks\n .filter(t => isTaskParent(t.id, normalizedTasks))\n .map(t => t.id)\n );\n }, [normalizedTasks]);\n\n const handleCollapseAll = useCallback(() => {\n if (externalCollapsedParentIds) return; // Don't modify external state\n setInternalCollapsedParentIds(allParentIds);\n }, [allParentIds, externalCollapsedParentIds]);\n\n const handleExpandAll = useCallback(() => {\n if (externalCollapsedParentIds) return; // Don't modify external state\n setInternalCollapsedParentIds(new Set());\n }, [externalCollapsedParentIds]);\n\n // Expose collapse/expand methods via ref (must be after handlers are defined)\n useImperativeHandle(\n ref,\n () => ({\n scrollToToday,\n scrollToTask,\n scrollToRow,\n collapseAll: handleCollapseAll,\n expandAll: handleExpandAll,\n }),\n [scrollToToday, scrollToTask, scrollToRow, handleCollapseAll, handleExpandAll]\n );\n\n /**\n * Calculate the depth of a task in the hierarchy.\n * Root tasks have depth 0, their children have depth 1, etc.\n */\n function getTaskDepth(taskId: string, tasks: Task[]): number {\n let depth = 0;\n let current: Task | undefined = tasks.find(t => t.id === taskId);\n while (current) {\n if (!current.parentId) break;\n depth++;\n const parentId: string = current.parentId;\n current = tasks.find(t => t.id === parentId);\n }\n return depth;\n }\n\n const handlePromoteTask = useCallback((taskId: string) => {\n // If consumer provided custom callback, use it\n if (onPromoteTask) {\n onPromoteTask(taskId);\n return;\n }\n\n // Default internal logic\n const taskToPromote = tasks.find(t => t.id === taskId);\n if (!taskToPromote || !taskToPromote.parentId) {\n return;\n }\n\n // Calculate current depth and determine new parent for single-level promotion\n const depth = getTaskDepth(taskId, tasks);\n const grandparentId = depth > 1\n ? tasks.find(t => t.id === taskToPromote.parentId)?.parentId\n : undefined;\n\n const currentParentId = taskToPromote.parentId;\n const siblings = tasks.filter(t => t.parentId === currentParentId);\n\n const promotedTask = { ...taskToPromote, parentId: grandparentId };\n\n if (siblings.length <= 1) {\n onTasksChange?.([promotedTask] as TTask[]);\n return;\n }\n\n // Reorder: place after last sibling of the old parent group\n const lastSiblingIndex = tasks\n .map((t, i) => ({ task: t, index: i }))\n .filter(({ task }) => task.parentId === currentParentId)\n .sort((a, b) => b.index - a.index)[0];\n\n if (!lastSiblingIndex) {\n onTasksChange?.([promotedTask] as TTask[]);\n return;\n }\n\n const reorderedTasks = normalizeHierarchyTasks([\n ...tasks.filter(t => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),\n promotedTask,\n ...tasks.filter(t => t.id !== taskId).slice(lastSiblingIndex.index + 1)\n ]);\n\n onTasksChange?.(reorderedTasks as TTask[]);\n }, [tasks, onTasksChange, onPromoteTask]);\n\n const handleDemoteTask = useCallback((taskId: string, newParentId: string) => {\n // If consumer provided custom callback, use it\n if (onDemoteTask) {\n onDemoteTask(taskId, newParentId);\n return;\n }\n\n // Default internal logic\n const wouldCreateCircular = (targetId: string, parentId: string, tasks: Task[]): boolean => {\n if (targetId === parentId) return true;\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, tasks)) {\n return;\n }\n\n let updatedTasks = removeDependenciesBetweenTasks(taskId, newParentId, tasks);\n\n const demotedTask = updatedTasks.find(t => t.id === taskId);\n if (!demotedTask) return;\n\n // If task was a parent (had children), save computed dates as its own dates\n // These become the task's \"own\" dates after demotion\n const wasParent = getChildren(taskId, tasks).length > 0;\n let taskDates = { startDate: demotedTask.startDate, endDate: demotedTask.endDate };\n\n if (wasParent) {\n const computedDates = computeParentDates(taskId, tasks);\n taskDates = {\n startDate: computedDates.startDate.toISOString().split('T')[0],\n endDate: computedDates.endDate.toISOString().split('T')[0]\n };\n }\n\n const updatedDemotedTask = {\n ...demotedTask,\n parentId: newParentId,\n startDate: taskDates.startDate,\n endDate: taskDates.endDate\n };\n\n // Only send the demoted task - parent dates are computed from children\n onTasksChange?.([updatedDemotedTask] as TTask[]);\n }, [tasks, onTasksChange, onDemoteTask]);\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 onTasksChange={handleTaskChange}\n selectedTaskId={selectedTaskId ?? undefined}\n onTaskSelect={handleTaskSelect}\n show={showTaskList}\n hasRightShadow={taskListHasRightShadow}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n onScrollToTask={scrollToTask}\n onSelectedChipChange={setSelectedChip}\n onAdd={onAdd as ((task: Task) => void) | undefined}\n onDelete={handleDelete}\n onInsertAfter={handleInsertAfter as ((taskId: string, newTask: Task) => void) | undefined}\n onReorder={handleReorder as ((tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void) | undefined}\n editingTaskId={editingTaskId}\n enableAddTask={enableAddTask}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={onPromoteTask ?? handlePromoteTask}\n onDemoteTask={onDemoteTask ?? handleDemoteTask}\n highlightedTaskIds={taskListHighlightedTaskIds}\n customDays={customDays}\n isWeekend={isWeekend}\n businessDays={businessDays}\n filterMode={filterMode}\n filteredTaskIds={matchedTaskIds}\n isFilterActive={!!taskFilter}\n additionalColumns={additionalColumns}\n />\n\n {/* Chart area */}\n <div className={showChart ? '' : 'gantt-chart-hidden'} 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 viewMode={viewMode}\n isCustomWeekend={isCustomWeekend}\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 viewMode={viewMode}\n isCustomWeekend={isCustomWeekend}\n />\n\n {todayInRange && <TodayIndicator monthStart={monthStart} dayWidth={dayWidth} />}\n\n {/* Dependency lines SVG overlay */}\n <DependencyLines\n tasks={previewVisibleTasks}\n allTasks={previewNormalizedTasks}\n collapsedParentIds={collapsedParentIds}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n gridWidth={gridWidth}\n dragOverrides={dependencyOverrides}\n selectedDep={selectedChip}\n businessDays={businessDays}\n weekendPredicate={isCustomWeekend}\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 {visibleTasks.map((task, index) => (\n <TaskRow\n key={task.id}\n task={task}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n onTasksChange={handleTaskChange as (tasks: Task[]) => void}\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 as (overrides: Map<string, { left: number; width: number }>, previewTasks?: Task[]) => void}\n onCascade={handleCascade as (cascadedTasks: Task[]) => void}\n highlightExpiredTasks={highlightExpiredTasks}\n isFilterMatch={filterMode === 'highlight' ? matchedTaskIds.has(task.id) : false}\n businessDays={businessDays}\n customDays={customDays}\n isWeekend={isWeekend}\n disableTaskDrag={disableTaskDrag}\n />\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport const GanttChart = forwardRef(GanttChartInner) as <TTask extends Task = Task>(\n props: GanttChartProps<TTask> & { ref?: React.Ref<GanttChartHandle> }\n) => React.ReactElement;\n\n(GanttChart as React.FC).displayName = 'GanttChart';\n\nexport default GanttChart;\n","/**\n * Core scheduling module — runtime-agnostic scheduling logic.\n * Zero React/DOM/date-fns dependencies.\n */\nexport * from './types';\nexport * from './dateMath';\nexport * from './dependencies';\nexport * from './cascade';\nexport * from './commands';\nexport * from './execute';\nexport * from './validation';\nexport * from './hierarchy';\n","/**\n * Dependency calculation functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { LinkType, TaskDependency, Task } from './types';\nimport {\n getBusinessDayOffset,\n shiftBusinessDayOffset,\n DAY_MS,\n getTaskDuration,\n} from './dateMath';\n\n/**\n * Normalize predecessor dates for scheduling calculations.\n * For milestone tasks, the scheduling \"finish\" anchor is treated as the day\n * before startDate. This preserves the standard inclusive FS formula\n * (`predEnd + lag + 1`) while making milestone FS lag=0 land on the same day.\n */\nexport function normalizePredecessorDates(\n predecessor: Pick<Task, 'startDate' | 'endDate' | 'type'>,\n parseDateFn: (d: string | Date) => Date\n): { predStart: Date; predEnd: Date } {\n const predStart = parseDateFn(predecessor.startDate);\n const isMilestone = predecessor.type === 'milestone';\n const predEnd = isMilestone\n ? new Date(predStart.getTime() - DAY_MS)\n : parseDateFn(predecessor.endDate);\n return { predStart, predEnd };\n}\n\n/**\n * Get lag value from dependency, defaulting to 0.\n */\nexport function getDependencyLag(dep: Pick<TaskDependency, 'lag'>): number {\n return Number.isFinite(dep.lag) ? dep.lag : 0;\n}\n\n/**\n * Normalize lag for FS links — clamp to >= -predecessorDuration.\n */\nexport function normalizeDependencyLag(\n linkType: LinkType,\n lag: number,\n predecessorStart: Date,\n predecessorEnd: Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\n if (linkType !== 'FS') {\n return lag;\n }\n\n const predecessorDuration = getTaskDuration(\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n\n return Math.max(-predecessorDuration, lag);\n}\n\n/**\n * Compute lag (in days) from actual predecessor/successor dates.\n * This is the single source of truth for lag semantics.\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 businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\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\n // Calendar days (original logic)\n if (!businessDays || !weekendPredicate) {\n switch (linkType) {\n case 'FS':\n return normalizeDependencyLag(\n linkType,\n Math.round((sS - pE) / DAY_MS) - 1,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate\n );\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 const anchorDate = linkType === 'SS' || linkType === 'SF' ? predStart : predEnd;\n const targetDate = linkType === 'FS' || linkType === 'SS' ? succStart : succEnd;\n const businessOffset = getBusinessDayOffset(anchorDate, targetDate, weekendPredicate);\n\n switch (linkType) {\n case 'FS':\n return normalizeDependencyLag(\n linkType,\n businessOffset - 1,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate\n );\n case 'SS': return businessOffset;\n case 'FF': return businessOffset;\n case 'SF': return businessOffset + 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 businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): Date {\n const normalizedLag = normalizeDependencyLag(\n linkType,\n lag,\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n\n // Calendar days (original logic)\n if (!businessDays || !weekendPredicate) {\n switch (linkType) {\n case 'FS':\n return new Date(predecessorEnd.getTime() + (normalizedLag + 1) * DAY_MS);\n case 'SS':\n return new Date(predecessorStart.getTime() + normalizedLag * DAY_MS);\n case 'FF':\n return new Date(predecessorEnd.getTime() + normalizedLag * DAY_MS);\n case 'SF':\n return new Date(predecessorStart.getTime() + (normalizedLag - 1) * DAY_MS);\n }\n }\n\n const anchorDate = (linkType === 'FS' || linkType === 'FF') ? predecessorEnd : predecessorStart;\n let offset: number;\n switch (linkType) {\n case 'FS':\n offset = normalizedLag + 1;\n break;\n case 'SS':\n offset = normalizedLag;\n break;\n case 'FF':\n offset = normalizedLag;\n break;\n case 'SF':\n offset = normalizedLag - 1;\n break;\n }\n return shiftBusinessDayOffset(anchorDate, offset, weekendPredicate);\n}\n","/**\n * Cascade engine functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, LinkType } from './types';\nimport {\n normalizeUTCDate,\n getTaskDuration,\n alignToWorkingDay,\n} from './dateMath';\nimport {\n calculateSuccessorDate,\n getDependencyLag,\n normalizePredecessorDates,\n} from './dependencies';\nimport {\n getChildren,\n isTaskParent,\n computeParentDates,\n} from './hierarchy';\nimport {\n buildTaskRangeFromStart,\n buildTaskRangeFromEnd,\n moveTaskRange,\n} from './commands';\n\nfunction parseCascadeDateInput(date: string | Date): Date {\n if (date instanceof Date) {\n return normalizeUTCDate(date);\n }\n return normalizeUTCDate(new Date(`${date.split('T')[0]}T00:00:00.000Z`));\n}\n\n/**\n * Get successor tasks of a dragged task using BFS, filtered by link type(s).\n */\nexport function getSuccessorChain(\n draggedTaskId: string,\n allTasks: Task[],\n linkTypes: LinkType[] = ['FS']\n): Task[] {\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);\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;\n}\n\n/**\n * Cascade successors by actual link constraints (BFS, constraint-based).\n */\nexport function cascadeByLinks(\n movedTaskId: string,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[],\n skipChildCascade: boolean = false\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\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 if (!skipChildCascade) {\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (visited.has(child.id) || child.locked) continue;\n\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 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\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 duration = getTaskDuration(origStart, origEnd);\n const currentTask = taskById.get(currentId)!;\n const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(\n {\n startDate: predStart,\n endDate: predEnd,\n type: currentTask.type,\n },\n parseCascadeDateInput\n );\n const constraintDate = calculateSuccessorDate(\n normalizedPredStart,\n normalizedPredEnd,\n dep.type,\n getDependencyLag(dep)\n );\n\n let newSuccStart: Date;\n let newSuccEnd: Date;\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n ({ start: newSuccStart, end: newSuccEnd } = buildTaskRangeFromStart(constraintDate, duration));\n } else {\n ({ start: newSuccStart, end: newSuccEnd } = buildTaskRangeFromEnd(constraintDate, duration));\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;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get transitive closure of successors for cascading.\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 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 * Arrival mode for universal cascade BFS entries.\n */\ntype ArrivalMode = 'direct' | 'child-delta' | 'parent-recalc' | 'dependency';\n\n/**\n * Universal cascade engine that propagates a moved task's new position through\n * the entire dependency+hierarchy graph using BFS with change detection.\n */\nexport function universalCascade(\n movedTask: Task,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n const updatedDates = new Map<string, { start: Date; end: Date }>();\n updatedDates.set(movedTask.id, { start: newStart, end: newEnd });\n\n const resultMap = new Map<string, Task>();\n resultMap.set(movedTask.id, {\n ...movedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n });\n\n const queue: Array<[string, ArrivalMode]> = [[movedTask.id, 'direct']];\n\n const childShifted = new Set<string>();\n\n let iterations = 0;\n const MAX_ITERATIONS = allTasks.length * 3;\n\n while (queue.length > 0 && iterations < MAX_ITERATIONS) {\n iterations++;\n const [currentId, arrivalMode] = queue.shift()!;\n const { start: currStart, end: currEnd } = updatedDates.get(currentId)!;\n const currentOriginal = taskById.get(currentId)!;\n\n // RULE 1: Hierarchy children follow their parent\n if (arrivalMode !== 'parent-recalc') {\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (childShifted.has(child.id) || child.locked) continue;\n\n const parentOrigStart = new Date(currentOriginal.startDate as string);\n const parentOrigEnd = new Date(currentOriginal.endDate as string);\n\n const childOrigStart = new Date(child.startDate as string);\n const childOrigEnd = new Date(child.endDate as string);\n\n const startDeltaMs = currStart.getTime() - parentOrigStart.getTime();\n const endDeltaMs = currEnd.getTime() - parentOrigEnd.getTime();\n\n let childNewStart: Date;\n let childNewEnd: Date;\n\n if (businessDays && weekendPredicate) {\n const proposedStart = new Date(childOrigStart.getTime() + startDeltaMs);\n const snapDirection: 1 | -1 = currStart.getTime() >= parentOrigStart.getTime() ? 1 : -1;\n const movedRange = moveTaskRange(\n child.startDate,\n child.endDate,\n proposedStart,\n true,\n weekendPredicate,\n snapDirection\n );\n childNewStart = movedRange.start;\n childNewEnd = movedRange.end;\n } else {\n childNewStart = new Date(childOrigStart.getTime() + startDeltaMs);\n childNewEnd = new Date(childOrigEnd.getTime() + endDeltaMs);\n }\n\n const prev = updatedDates.get(child.id);\n if (prev && prev.start.getTime() === childNewStart.getTime() && prev.end.getTime() === childNewEnd.getTime()) {\n continue;\n }\n\n updatedDates.set(child.id, { start: childNewStart, end: childNewEnd });\n childShifted.add(child.id);\n queue.push([child.id, 'child-delta']);\n resultMap.set(child.id, {\n ...child,\n startDate: childNewStart.toISOString().split('T')[0],\n endDate: childNewEnd.toISOString().split('T')[0],\n });\n }\n }\n\n // RULE 2: Parent task is recomputed from its children\n const parentId = (currentOriginal as any).parentId as string | undefined;\n if (parentId) {\n const parent = taskById.get(parentId);\n if (parent && !parent.locked) {\n const siblings = getChildren(parentId, allTasks);\n\n const siblingPositions = siblings.map(sib => {\n if (updatedDates.has(sib.id)) return updatedDates.get(sib.id)!;\n return { start: new Date(sib.startDate as string), end: new Date(sib.endDate as string) };\n });\n\n const minStart = new Date(Math.min(...siblingPositions.map(p => p.start.getTime())));\n const maxEnd = new Date(Math.max(...siblingPositions.map(p => p.end.getTime())));\n\n const prev = updatedDates.get(parentId);\n if (!prev || prev.start.getTime() !== minStart.getTime() || prev.end.getTime() !== maxEnd.getTime()) {\n updatedDates.set(parentId, { start: minStart, end: maxEnd });\n queue.push([parentId, 'parent-recalc']);\n resultMap.set(parentId, {\n ...parent,\n startDate: minStart.toISOString().split('T')[0],\n endDate: maxEnd.toISOString().split('T')[0],\n });\n }\n }\n }\n\n // RULE 3: Dependency successors are repositioned\n for (const task of allTasks) {\n if (task.locked || !task.dependencies) continue;\n\n const dep = task.dependencies.find(d => d.taskId === currentId);\n if (!dep) continue;\n\n const origStart = new Date(task.startDate as string);\n const origEnd = new Date(task.endDate as string);\n const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(\n {\n startDate: currStart,\n endDate: currEnd,\n type: currentOriginal.type,\n },\n parseCascadeDateInput\n );\n const constraintDate = calculateSuccessorDate(\n normalizedPredStart, normalizedPredEnd, dep.type, getDependencyLag(dep),\n businessDays, weekendPredicate\n );\n\n let succNewStart: Date;\n let succNewEnd: Date;\n const duration = getTaskDuration(origStart, origEnd, businessDays, weekendPredicate);\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n ({ start: succNewStart, end: succNewEnd } = buildTaskRangeFromStart(\n constraintDate,\n duration,\n businessDays,\n weekendPredicate\n ));\n } else {\n ({ start: succNewStart, end: succNewEnd } = buildTaskRangeFromEnd(\n constraintDate,\n duration,\n businessDays,\n weekendPredicate\n ));\n }\n\n const prev = updatedDates.get(task.id);\n if (prev && prev.start.getTime() === succNewStart.getTime() && prev.end.getTime() === succNewEnd.getTime()) {\n continue;\n }\n\n updatedDates.set(task.id, { start: succNewStart, end: succNewEnd });\n queue.push([task.id, 'dependency']);\n resultMap.set(task.id, {\n ...task,\n startDate: succNewStart.toISOString().split('T')[0],\n endDate: succNewEnd.toISOString().split('T')[0],\n });\n }\n }\n\n return Array.from(resultMap.values());\n}\n\n/**\n * Recalculate all task dates when switching between business/calendar day modes.\n */\nexport function reflowTasksOnModeSwitch(\n sourceTasks: Task[],\n toBusinessDays: boolean,\n weekendPredicate: (date: Date) => boolean\n): Task[] {\n const fromBusinessDays = !toBusinessDays;\n let tasks: Task[] = sourceTasks.map(t => ({ ...t }));\n\n const toISO = (d: Date) => d.toISOString().split('T')[0];\n\n for (const task of tasks) {\n if (isTaskParent(task.id, tasks)) continue;\n\n const start = normalizeUTCDate(new Date(`${task.startDate}T00:00:00.000Z`));\n const duration = getTaskDuration(task.startDate, task.endDate, fromBusinessDays, weekendPredicate);\n\n let range: { start: Date; end: Date };\n if (toBusinessDays) {\n const alignedStart = alignToWorkingDay(start, 1, weekendPredicate);\n range = buildTaskRangeFromStart(alignedStart, duration, true, weekendPredicate);\n } else {\n range = buildTaskRangeFromStart(start, duration, false);\n }\n\n task.startDate = toISO(range.start);\n task.endDate = toISO(range.end);\n }\n\n for (const task of tasks) {\n if (!isTaskParent(task.id, tasks)) continue;\n const { startDate, endDate } = computeParentDates(task.id, tasks);\n task.startDate = toISO(startDate);\n task.endDate = toISO(endDate);\n }\n\n if (toBusinessDays) {\n const rootSeeds = tasks.filter(\n t => !(t as any).parentId && (!t.dependencies || t.dependencies.length === 0)\n );\n\n for (const seed of rootSeeds) {\n const current = tasks.find(t => t.id === seed.id)!;\n const start = new Date(`${current.startDate}T00:00:00.000Z`);\n const end = new Date(`${current.endDate}T00:00:00.000Z`);\n\n const cascaded = universalCascade(current, start, end, tasks, toBusinessDays, weekendPredicate);\n const updates = new Map(cascaded.map((t): [string, Task] => [t.id, t]));\n tasks = tasks.map(t => updates.get(t.id) ?? t);\n }\n }\n\n return tasks;\n}\n","/**\n * Hierarchy scheduling functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task } from './types';\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 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 * Get all descendant tasks of a parent task (transitive closure of children).\n * Returns all tasks where task.parentId is in the hierarchy of the parent.\n */\nexport function getAllDescendants(parentId: string, tasks: Task[]): Task[] {\n const descendants: Task[] = [];\n const visited = new Set<string>();\n\n function collectChildren(taskId: string) {\n if (visited.has(taskId)) return;\n visited.add(taskId);\n\n const children = getChildren(taskId, tasks);\n for (const child of children) {\n descendants.push(child);\n collectChildren(child.id);\n }\n }\n\n collectChildren(parentId);\n return descendants;\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: 'FS' | 'SS' | 'FF' | 'SF';\n lag: number;\n}> {\n const edges: Array<{ predecessorId: string; successorId: string; type: 'FS' | 'SS' | 'FF' | 'SF'; 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 * Remove dependencies between two tasks in both directions.\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 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 */\nexport function findParentId(taskId: string, tasks: Task[]): string | undefined {\n const task = tasks.find(t => t.id === taskId);\n return task?.parentId;\n}\n\n/**\n * Returns true when ancestorId is an ancestor of taskId in the current hierarchy.\n */\nexport function isAncestorTask(ancestorId: string, taskId: string, tasks: Task[]): boolean {\n const taskById = new Map(tasks.map(task => [task.id, task]));\n const visited = new Set<string>();\n let current = taskById.get(taskId);\n\n while (current?.parentId) {\n if (current.parentId === ancestorId) {\n return true;\n }\n\n if (visited.has(current.parentId)) {\n return false;\n }\n\n visited.add(current.parentId);\n current = taskById.get(current.parentId);\n }\n\n return false;\n}\n\n/**\n * Returns true when tasks are in the same ancestry chain.\n */\nexport function areTasksHierarchicallyRelated(taskId1: string, taskId2: string, tasks: Task[]): boolean {\n if (taskId1 === taskId2) {\n return true;\n }\n\n return isAncestorTask(taskId1, taskId2, tasks) || isAncestorTask(taskId2, taskId1, tasks);\n}\n","/**\n * High-level schedule command functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task } from './types';\nimport {\n normalizeUTCDate,\n parseDateOnly,\n addBusinessDays,\n subtractBusinessDays,\n alignToWorkingDay,\n getTaskDuration,\n getBusinessDaysCount,\n} from './dateMath';\nimport {\n calculateSuccessorDate,\n getDependencyLag,\n normalizeDependencyLag,\n computeLagFromDates,\n normalizePredecessorDates,\n} from './dependencies';\n\n// Re-export for backward compat — these live in dateMath now\nexport { alignToWorkingDay, getTaskDuration };\n\n/**\n * Build a task range (start/end dates) from a start date and duration.\n */\nexport function buildTaskRangeFromStart(\n startDate: Date,\n duration: number,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = 1\n): { start: Date; end: Date } {\n const normalizedStart = businessDays && weekendPredicate\n ? alignToWorkingDay(startDate, snapDirection, weekendPredicate)\n : normalizeUTCDate(startDate);\n\n if (businessDays && weekendPredicate) {\n return {\n start: normalizedStart,\n end: parseDateOnly(addBusinessDays(normalizedStart, duration, weekendPredicate)),\n };\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n return {\n start: normalizedStart,\n end: new Date(normalizedStart.getTime() + (Math.max(1, duration) - 1) * DAY_MS),\n };\n}\n\n/**\n * Build a task range (start/end dates) from an end date and duration.\n */\nexport function buildTaskRangeFromEnd(\n endDate: Date,\n duration: number,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = -1\n): { start: Date; end: Date } {\n const normalizedEnd = businessDays && weekendPredicate\n ? alignToWorkingDay(endDate, snapDirection, weekendPredicate)\n : normalizeUTCDate(endDate);\n\n if (businessDays && weekendPredicate) {\n return {\n start: parseDateOnly(subtractBusinessDays(normalizedEnd, duration, weekendPredicate)),\n end: normalizedEnd,\n };\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n return {\n start: new Date(normalizedEnd.getTime() - (Math.max(1, duration) - 1) * DAY_MS),\n end: normalizedEnd,\n };\n}\n\n/**\n * Move a task range to a new start date, preserving duration.\n */\nexport function moveTaskRange(\n originalStart: string | Date,\n originalEnd: string | Date,\n proposedStart: Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = 1\n): { start: Date; end: Date } {\n return buildTaskRangeFromStart(\n proposedStart,\n getTaskDuration(originalStart, originalEnd, businessDays, weekendPredicate),\n businessDays,\n weekendPredicate,\n snapDirection\n );\n}\n\n/**\n * Clamp task range start date based on incoming FS dependencies.\n */\nexport function clampTaskRangeForIncomingFS(\n task: Pick<Task, 'dependencies'>,\n proposedStart: Date,\n proposedEnd: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n if (!task.dependencies?.length) {\n return { start: proposedStart, end: proposedEnd };\n }\n\n let minAllowedStart: Date | null = null;\n\n for (const dep of task.dependencies) {\n if (dep.type !== 'FS') {\n continue;\n }\n\n const predecessor = allTasks.find(candidate => candidate.id === dep.taskId);\n if (!predecessor) {\n continue;\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const predecessorDuration = getTaskDuration(\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n const candidateMinStart = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n 'FS',\n -predecessorDuration,\n businessDays,\n weekendPredicate\n );\n\n if (!minAllowedStart || candidateMinStart.getTime() > minAllowedStart.getTime()) {\n minAllowedStart = candidateMinStart;\n }\n }\n\n if (!minAllowedStart || proposedStart.getTime() >= minAllowedStart.getTime()) {\n return { start: proposedStart, end: proposedEnd };\n }\n\n return buildTaskRangeFromStart(\n minAllowedStart,\n getTaskDuration(proposedStart, proposedEnd, businessDays, weekendPredicate),\n businessDays,\n weekendPredicate\n );\n}\n\n/**\n * Recalculate incoming dependency lags after a task's dates change.\n */\nexport function recalculateIncomingLags(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): NonNullable<Task['dependencies']> {\n if (!task.dependencies) return [];\n return task.dependencies.map(dep => {\n const predecessor = allTasks.find(candidate => candidate.id === dep.taskId);\n if (!predecessor) {\n return { ...dep, lag: getDependencyLag(dep) };\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(\n predecessor,\n (d) => new Date(d instanceof Date ? d.getTime() : `${String(d).split('T')[0]}T00:00:00.000Z`)\n );\n const nextLag = computeLagFromDates(\n dep.type,\n predecessorStart,\n predecessorEnd,\n newStartDate,\n newEndDate,\n businessDays,\n weekendPredicate\n );\n\n return { ...dep, lag: nextLag };\n });\n}\n\n","/**\n * Command-level scheduling API.\n * High-level functions that compose low-level scheduling primitives.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, ScheduleCommandResult, ScheduleCommandOptions } from './types';\nimport { moveTaskRange, recalculateIncomingLags, buildTaskRangeFromEnd, buildTaskRangeFromStart, getTaskDuration } from './commands';\nimport { universalCascade } from './cascade';\nimport { parseDateOnly } from './dateMath';\nimport { calculateSuccessorDate, getDependencyLag, normalizePredecessorDates } from './dependencies';\nimport { computeParentDates, isTaskParent } from './hierarchy';\n\nfunction toIsoDate(date: Date): string {\n return date.toISOString().split('T')[0];\n}\n\nfunction createChangedResult(snapshot: Task[], nextTasks: Task[]): ScheduleCommandResult {\n const originalById = new Map(snapshot.map(task => [task.id, task]));\n const changedTasks = nextTasks.filter(task => JSON.stringify(originalById.get(task.id)) !== JSON.stringify(task));\n\n return {\n changedTasks,\n changedIds: changedTasks.map(task => task.id),\n };\n}\n\n/**\n * Move a task to a new start date with cascade and lag recalculation.\n * Identical to manual composition: moveTaskRange -> recalculateIncomingLags -> universalCascade.\n */\nexport function moveTaskWithCascade(\n taskId: string,\n newStart: Date,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n // Step 1: Calculate new range preserving duration\n const newRange = moveTaskRange(\n task.startDate,\n task.endDate,\n newStart,\n businessDays,\n weekendPredicate\n );\n\n // Step 2: Recalculate incoming dependency lags\n const updatedDependencies = recalculateIncomingLags(\n task,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Step 3: Create moved task with updated deps\n const movedTask: Task = {\n ...task,\n startDate: newRange.start.toISOString().split('T')[0],\n endDate: newRange.end.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n // Step 4: Cascade through dependency graph\n if (options?.skipCascade) {\n return {\n changedTasks: [movedTask],\n changedIds: [movedTask.id],\n };\n }\n\n const cascadeResult = universalCascade(\n movedTask,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Merge: movedTask + cascade results\n const resultMap = new Map<string, Task>();\n resultMap.set(movedTask.id, movedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Resize a task by changing its start or end date.\n * anchor='end': new end date, start stays fixed.\n * anchor='start': new start date, end stays fixed.\n */\nexport function resizeTaskWithCascade(\n taskId: string,\n anchor: 'start' | 'end',\n newDate: Date,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n const originalStart = parseDateOnly(task.startDate);\n const originalEnd = parseDateOnly(task.endDate);\n let newRange: { start: Date; end: Date };\n\n if (anchor === 'end') {\n // anchor='end': new end date, start stays fixed\n newRange = { start: originalStart, end: newDate };\n } else {\n // anchor='start': new start date, end stays fixed\n newRange = { start: newDate, end: originalEnd };\n }\n\n // Recalculate lags\n const updatedDependencies = recalculateIncomingLags(\n task,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Create resized task\n const resizedTask: Task = {\n ...task,\n startDate: newRange.start.toISOString().split('T')[0],\n endDate: newRange.end.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n if (options?.skipCascade) {\n return {\n changedTasks: [resizedTask],\n changedIds: [resizedTask.id],\n };\n }\n\n // Cascade through dependency graph\n const cascadeResult = universalCascade(\n resizedTask,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const resultMap = new Map<string, Task>();\n resultMap.set(resizedTask.id, resizedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Recalculate a task's dates based on its dependency constraints.\n * Finds all predecessors and computes the most constrained date.\n */\nexport function recalculateTaskFromDependencies(\n taskId: string,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n if (!task.dependencies || task.dependencies.length === 0) {\n // No dependencies — return the task as-is\n return {\n changedTasks: [task],\n changedIds: [task.id],\n };\n }\n\n // Find the most constrained start/end based on all predecessors\n let constrainedStart: Date | null = null;\n let constrainedEnd: Date | null = null;\n\n for (const dep of task.dependencies) {\n const predecessor = snapshot.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n\n const { predStart, predEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const constraintDate = calculateSuccessorDate(\n predStart,\n predEnd,\n dep.type,\n getDependencyLag(dep),\n businessDays,\n weekendPredicate\n );\n\n const duration = getTaskDuration(\n parseDateOnly(task.startDate),\n parseDateOnly(task.endDate),\n businessDays,\n weekendPredicate\n );\n\n let range: { start: Date; end: Date };\n if (dep.type === 'FS' || dep.type === 'SS') {\n range = buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate);\n } else {\n range = buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);\n }\n\n // Take the latest start as the effective constraint\n if (!constrainedStart || range.start.getTime() > constrainedStart.getTime()) {\n constrainedStart = range.start;\n constrainedEnd = range.end;\n }\n }\n\n if (!constrainedStart || !constrainedEnd) {\n return {\n changedTasks: [task],\n changedIds: [task.id],\n };\n }\n\n // Recalculate lags for the new position\n const updatedDependencies = recalculateIncomingLags(\n task,\n constrainedStart,\n constrainedEnd,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const recalculatedTask: Task = {\n ...task,\n startDate: constrainedStart.toISOString().split('T')[0],\n endDate: constrainedEnd.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n if (options?.skipCascade) {\n return {\n changedTasks: [recalculatedTask],\n changedIds: [recalculatedTask.id],\n };\n }\n\n // Cascade through dependency graph\n const cascadeResult = universalCascade(\n recalculatedTask,\n constrainedStart,\n constrainedEnd,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const resultMap = new Map<string, Task>();\n resultMap.set(recalculatedTask.id, recalculatedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Full project schedule recalculation.\n * Recomputes the project against a continuously updated working snapshot.\n * Returns only tasks whose normalized state changed.\n */\nexport function recalculateProjectSchedule(\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n const workingMap = new Map(snapshot.map(task => [task.id, { ...task }]));\n const indegree = new Map<string, number>();\n const successorIdsByTask = new Map<string, string[]>();\n\n for (const task of snapshot) {\n indegree.set(task.id, 0);\n successorIdsByTask.set(task.id, []);\n }\n\n for (const task of snapshot) {\n for (const dep of task.dependencies ?? []) {\n if (!workingMap.has(dep.taskId)) {\n continue;\n }\n\n indegree.set(task.id, (indegree.get(task.id) ?? 0) + 1);\n successorIdsByTask.get(dep.taskId)?.push(task.id);\n }\n }\n\n const queue = snapshot\n .filter(task => (indegree.get(task.id) ?? 0) === 0)\n .map(task => task.id);\n\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n\n for (const successorId of successorIdsByTask.get(currentId) ?? []) {\n const nextIndegree = (indegree.get(successorId) ?? 0) - 1;\n indegree.set(successorId, nextIndegree);\n\n if (nextIndegree !== 0) {\n continue;\n }\n\n const currentTask = workingMap.get(successorId);\n if (!currentTask || currentTask.locked || !currentTask.dependencies?.length) {\n queue.push(successorId);\n continue;\n }\n\n const duration = getTaskDuration(\n parseDateOnly(currentTask.startDate),\n parseDateOnly(currentTask.endDate),\n businessDays,\n weekendPredicate\n );\n\n let constrainedRange: { start: Date; end: Date } | null = null;\n\n for (const dep of currentTask.dependencies) {\n const predecessor = workingMap.get(dep.taskId);\n if (!predecessor) {\n continue;\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const constraintDate = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n dep.type,\n getDependencyLag(dep),\n businessDays,\n weekendPredicate\n );\n\n const candidateRange = dep.type === 'FS' || dep.type === 'SS'\n ? buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate)\n : buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);\n\n if (\n !constrainedRange ||\n candidateRange.start.getTime() > constrainedRange.start.getTime() ||\n (\n candidateRange.start.getTime() === constrainedRange.start.getTime() &&\n candidateRange.end.getTime() > constrainedRange.end.getTime()\n )\n ) {\n constrainedRange = candidateRange;\n }\n }\n\n if (!constrainedRange) {\n queue.push(successorId);\n continue;\n }\n\n workingMap.set(successorId, {\n ...currentTask,\n startDate: toIsoDate(constrainedRange.start),\n endDate: toIsoDate(constrainedRange.end),\n });\n queue.push(successorId);\n }\n }\n\n const parentsByDepth = snapshot\n .filter(task => isTaskParent(task.id, snapshot))\n .map(task => {\n let depth = 0;\n let current = task.parentId ? workingMap.get(task.parentId) : undefined;\n while (current) {\n depth++;\n current = current.parentId ? workingMap.get(current.parentId) : undefined;\n }\n return { taskId: task.id, depth };\n })\n .sort((left, right) => right.depth - left.depth);\n\n const workingTasks = () => Array.from(workingMap.values());\n\n for (const { taskId } of parentsByDepth) {\n const parent = workingMap.get(taskId);\n if (!parent || parent.locked) {\n continue;\n }\n\n const { startDate, endDate } = computeParentDates(taskId, workingTasks());\n workingMap.set(taskId, {\n ...parent,\n startDate: toIsoDate(startDate),\n endDate: toIsoDate(endDate),\n });\n }\n\n return createChangedResult(snapshot, Array.from(workingMap.values()));\n}\n","/**\n * Dependency validation and cycle detection.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, DependencyError, ValidationResult } from './types';\nimport { areTasksHierarchicallyRelated } from './hierarchy';\n\n/**\n * Build adjacency list for dependency graph (task -> successors)\n */\nexport function buildAdjacencyList(tasks: Task[]): Map<string, string[]> {\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 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 * 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 invalid hierarchy links (ancestor <-> descendant)\n for (const task of tasks) {\n if (!task.dependencies) continue;\n\n for (const dep of task.dependencies) {\n if (!taskIds.has(dep.taskId)) {\n continue;\n }\n\n if (areTasksHierarchicallyRelated(task.id, dep.taskId, tasks)) {\n errors.push({\n type: 'constraint',\n taskId: task.id,\n message: `Dependencies between parent and child tasks are not allowed: ${dep.taskId} -> ${task.id}`,\n relatedTaskIds: [dep.taskId, task.id],\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","import type { Task } from '../types';\nimport { computeParentDates, computeParentProgress, isTaskParent } from '../core/scheduling';\nimport { normalizeTaskDates } from './dateUtils';\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 * Also normalizes task dates to ensure startDate is always before or equal to endDate.\n */\nexport function normalizeHierarchyTasks<T extends Task>(tasks: T[]): T[] {\n const orderedTasks = flattenHierarchy(tasks).map((task) => {\n // Normalize dates for all tasks (swap if endDate < startDate)\n const { startDate, endDate } = normalizeTaskDates(task.startDate, task.endDate);\n return { ...task, startDate: startDate as T['startDate'], endDate: endDate as T['endDate'] };\n }) 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, getWeekSpans, getWeekBlocks, getMonthBlocks, getYearSpans, type WeekBlock, type WeekSpan, type MonthBlock, type YearSpan } 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 /** View mode: 'day' renders individual day columns, 'week' renders 7-day week columns, 'month' renders one column per month */\n viewMode?: 'day' | 'week' | 'month';\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isCustomWeekend?: (date: Date) => boolean;\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/week columns\n * Bottom row: Day numbers (centered) in individual day columns OR week start day numbers\n *\n * Supports two view modes:\n * - day (default): each column = 1 day, shows month names + individual day numbers\n * - week: each column = 7 days, shows month names spanning week columns + week-start dates\n */\nconst TimeScaleHeader: React.FC<TimeScaleHeaderProps> = ({\n days,\n dayWidth,\n headerHeight,\n viewMode = 'day',\n isCustomWeekend,\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 // Week-view: blocks with variable width (split on month boundaries)\n const weekBlocks = useMemo(\n () => (viewMode === 'week' ? getWeekBlocks(days) : []),\n [days, viewMode]\n );\n\n // Week-view: month spans grouped over week-blocks (row 1 labels)\n const weekSpans = useMemo(\n () => (viewMode === 'week' ? getWeekSpans(days) : []),\n [days, viewMode]\n );\n\n // Calculate column widths for each block (for grid template)\n const weekColumnWidths = useMemo(\n () => weekBlocks.map(b => b.days * dayWidth),\n [weekBlocks, dayWidth]\n );\n\n // Calculate total width for grid template\n const weekGridTemplate = useMemo(\n () => weekColumnWidths.map(w => `${w}px`).join(' '),\n [weekColumnWidths]\n );\n\n // Month-view: one block per calendar month (row 2 columns)\n const monthBlocks = useMemo(\n () => (viewMode === 'month' ? getMonthBlocks(days) : []),\n [days, viewMode]\n );\n\n // Month-view: year spans over month blocks (row 1 labels)\n const yearSpans = useMemo(\n () => (viewMode === 'month' ? getYearSpans(days) : []),\n [days, viewMode]\n );\n\n // Month-view: grid template for row 2 (variable column widths = days * dayWidth)\n const monthGridTemplate = useMemo(\n () => monthBlocks.map(b => `${b.days * dayWidth}px`).join(' '),\n [monthBlocks, dayWidth]\n );\n\n // Separator positions — same Math.round formula as GridBackground to guarantee pixel alignment.\n // fullHeight=true → spans both header rows (thick boundary between spans in row 1).\n // fullHeight=false → spans row 2 only (thin sub-column divider, doesn't cut through row 1 spans).\n const separators = useMemo(() => {\n const result: Array<{ x: number; isThick: boolean; fullHeight: boolean }> = [];\n if (viewMode === 'day') {\n for (let i = 1; i < days.length; i++) {\n if (days[i].getUTCDate() === 1) {\n result.push({ x: Math.round(i * dayWidth), isThick: true, fullHeight: true });\n }\n }\n } else if (viewMode === 'week') {\n let dayIndex = 0;\n for (let i = 0; i < weekBlocks.length; i++) {\n if (i > 0) {\n const isMonth = weekBlocks[i - 1].startDate.getUTCMonth() !== weekBlocks[i].startDate.getUTCMonth();\n result.push({ x: Math.round(dayIndex * dayWidth), isThick: isMonth, fullHeight: isMonth });\n }\n dayIndex += weekBlocks[i].days;\n }\n } else if (viewMode === 'month') {\n let dayIndex = 0;\n for (let i = 0; i < monthBlocks.length; i++) {\n if (i > 0) {\n const isYear = monthBlocks[i].startDate.getUTCMonth() === 0;\n result.push({ x: Math.round(dayIndex * dayWidth), isThick: isYear, fullHeight: isYear });\n }\n dayIndex += monthBlocks[i].days;\n }\n }\n return result;\n }, [days, weekBlocks, monthBlocks, dayWidth, viewMode]);\n\n return (\n <div\n className=\"gantt-tsh-header\"\n style={{ height: `${headerHeight}px`, position: 'relative' }}\n >\n {/* Separator lines — pixel-aligned with GridBackground */}\n {separators.map((sep, i) => (\n <div\n key={`sep-${i}`}\n className={`gantt-tsh-separator${sep.isThick ? ' gantt-tsh-separator--thick' : ''}`}\n style={sep.fullHeight\n ? { left: `${sep.x}px`, top: 0, bottom: 0 }\n : { left: `${sep.x}px`, top: rowHeight, height: rowHeight }}\n />\n ))}\n\n {/* Month row - top */}\n <div\n className=\"gantt-tsh-monthRow\"\n style={{ height: `${rowHeight}px` }}\n >\n {viewMode === 'week' ? (\n // Week-view row 1: month names spanning week blocks\n weekSpans.map((span: WeekSpan, index: number) => (\n <div\n key={`wmonth-${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 ) : viewMode === 'month' ? (\n // Month-view row 1: year labels spanning all months of that year\n yearSpans.map((span: YearSpan, index: number) => (\n <div\n key={`year-${index}`}\n className=\"gantt-tsh-monthCell\"\n style={{ width: `${span.days * dayWidth}px` }}\n >\n {span.year.getUTCFullYear().toString()}\n </div>\n ))\n ) : (\n // Day-view row 1: month names spanning day columns (existing code)\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 )}\n </div>\n\n {/* Day/Week row - bottom */}\n <div\n className=\"gantt-tsh-dayRow\"\n style={{\n height: `${rowHeight}px`,\n gridTemplateColumns: viewMode === 'week'\n ? weekGridTemplate\n : viewMode === 'month'\n ? monthGridTemplate\n : dayGridTemplate,\n }}\n >\n {viewMode === 'week' ? (\n // Week-view row 2: week block start day numbers (variable width)\n weekBlocks.map((block, index) => {\n const prevBlock = weekBlocks[index - 1];\n const isMonthBoundary =\n index > 0 && prevBlock &&\n prevBlock.startDate.getUTCMonth() !== block.startDate.getUTCMonth();\n // Show date only for full weeks (7 days)\n const showDate = block.days === 7;\n return (\n <div\n key={`week-${index}`}\n className=\"gantt-tsh-dayCell gantt-tsh-weekCell\"\n >\n <span className=\"gantt-tsh-dayLabel\">\n {showDate ? String(block.startDate.getUTCDate()).padStart(2, '0') : ''}\n </span>\n </div>\n );\n })\n ) : viewMode === 'month' ? (\n // Month-view row 2: one column per month, shows abbreviated month name\n monthBlocks.map((block: MonthBlock, index: number) => {\n const MIN_DAYS_TO_SHOW_LABEL = 15;\n const showLabel = block.days >= MIN_DAYS_TO_SHOW_LABEL;\n const isYearBoundary = index > 0 && block.startDate.getUTCMonth() === 0;\n return (\n <div\n key={`mblock-${index}`}\n className=\"gantt-tsh-dayCell gantt-tsh-weekCell\"\n >\n <span className=\"gantt-tsh-dayLabel\">\n {showLabel\n ? (() => { const s = block.startDate.toLocaleString('ru-RU', { month: 'long', timeZone: 'UTC' }); return s.charAt(0).toUpperCase() + s.slice(1); })()\n : ''}\n </span>\n </div>\n );\n })\n ) : (\n // Day-view row 2: individual day numbers (existing code)\n days.map((day, index) => {\n const isWeekendDay = isCustomWeekend\n ? isCustomWeekend(day)\n : day.getUTCDay() === 0 || day.getUTCDay() === 6;\n const prevDay = days[index - 1];\n const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();\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 ${isWeekendDay ? 'gantt-tsh-weekendDay' : ''} ${isTodayDate ? 'gantt-tsh-today' : ''}`}>\n <span className=\"gantt-tsh-dayLabel\">{format(day, 'd')}</span>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n};\n\nexport default TimeScaleHeader;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { parseUTCDate, formatDateRangeLabel, createCustomDayPredicate } from '../../utils/dateUtils';\nimport { calculateMilestoneGeometry, calculateTaskBar, pixelsToDate } from '../../utils/geometry';\nimport { isTaskExpired } from '../../utils/expired';\nimport { isMilestoneTask, normalizeTaskDatesForType } from '../../utils/taskType';\nimport { useTaskDrag } from '../../hooks/useTaskDrag';\nimport { isTaskParent, getChildren, getBusinessDaysCount } from '../../core/scheduling';\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. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => 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 /** Whether this row matches the active filter highlight */\n isFilterMatch?: boolean;\n /** Calculate duration in business days (excluding weekends) */\n businessDays?: boolean;\n /** Custom weekend configuration */\n customDays?: Array<{ date: Date; type: 'weekend' | 'workday' }>;\n /** Custom weekend predicate (overrides default Saturday/Sunday) */\n isWeekend?: (date: Date) => boolean;\n /** Disable task drag and resize (overrides task.locked) */\n disableTaskDrag?: 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: onTasksChange is intentionally excluded from this comparison because:\n * 1. The parent (GanttChart) wraps onTasksChange in useCallback for referential stability\n * 2. onTasksChange 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 onTasksChange —\n * callbacks excluded from comparison because GanttChart wraps them in useCallback).\n *\n * Excluding onTasksChange 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.type === nextProps.task.type &&\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 prevProps.isFilterMatch === nextProps.isFilterMatch &&\n prevProps.businessDays === nextProps.businessDays &&\n prevProps.customDays === nextProps.customDays &&\n prevProps.isWeekend === nextProps.isWeekend &&\n prevProps.disableTaskDrag === nextProps.disableTaskDrag\n // onTasksChange, 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, onTasksChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isFilterMatch = false, businessDays, customDays, isWeekend, disableTaskDrag = false }) => {\n const defaultParentBarColor = '#782FC4';\n // Extract divider from task prop\n const { divider: taskDivider } = task;\n\n const normalizedTask = useMemo(() => normalizeTaskDatesForType(task), [task]);\n const milestone = useMemo(() => isMilestoneTask(normalizedTask), [normalizedTask]);\n\n // Parse dates as UTC\n const taskStartDate = useMemo(() => parseUTCDate(normalizedTask.startDate), [normalizedTask.startDate]);\n const taskEndDate = useMemo(() => parseUTCDate(normalizedTask.endDate), [normalizedTask.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 return isTaskExpired(normalizedTask);\n }, [normalizedTask.startDate, normalizedTask.endDate, normalizedTask.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 const milestoneGeometry = useMemo(\n () => calculateMilestoneGeometry(taskStartDate, monthStart, dayWidth),\n [taskStartDate, 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 // 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 const externalTaskNameColor = useMemo(() => {\n if (isExpired) {\n return 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)';\n }\n const baseColor = isParent\n ? (task.color || defaultParentBarColor)\n : (task.color || 'var(--gantt-task-bar-default-color)');\n return `color-mix(in srgb, ${baseColor} 40%, black)`;\n }, [defaultParentBarColor, isExpired, isParent, task.color]);\n\n // At 100% progress, tint the bar itself instead of rendering a fill overlay.\n const barStyle = useMemo(() => {\n const parentBarColor = task.color || defaultParentBarColor;\n if (isParent) {\n if (progressWidth >= 100) {\n const c = isExpired\n ? 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)'\n : `color-mix(in srgb, ${parentBarColor} 40%, black)`;\n return { backgroundColor: c, '--gantt-parent-bar-color': c } as React.CSSProperties;\n }\n return { '--gantt-parent-bar-color': parentBarColor } as React.CSSProperties;\n }\n if (progressWidth >= 100) {\n return { backgroundColor: progressColor };\n }\n return { backgroundColor: barColor };\n }, [defaultParentBarColor, isExpired, isParent, progressWidth, barColor, progressColor, task.color]);\n\n // Handle drag end - call onTasksChange with updated task\n const handleDragEnd = (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => {\n const updatedTask: Task = {\n ...normalizedTask,\n startDate: result.startDate.toISOString(),\n endDate: result.endDate.toISOString(),\n ...(result.updatedDependencies !== undefined && { dependencies: result.updatedDependencies }),\n };\n onTasksChange?.([updatedTask]);\n };\n\n // Weekend predicate for business days calculation (must be before useTaskDrag)\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\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 disableTaskDrag,\n onCascadeProgress,\n onCascade,\n businessDays,\n weekendPredicate,\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 const displayMilestoneGeometry = useMemo(() => {\n // Milestones are always anchored to a single day cell even if some preview path\n // passes a wider width (for example, malformed input dates before normalization).\n const centerX = Math.round(displayLeft + dayWidth / 2);\n const halfSize = Math.round(milestoneGeometry.size / 2);\n return {\n centerX,\n left: centerX - halfSize,\n right: centerX + halfSize,\n size: milestoneGeometry.size,\n };\n }, [displayLeft, dayWidth, milestoneGeometry.size]);\n const visualLeft = milestone ? displayMilestoneGeometry.left : displayLeft;\n const visualWidth = milestone ? displayMilestoneGeometry.size : displayWidth;\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 ? (\n milestone\n ? pixelsToDate(displayLeft, monthStart, dayWidth)\n : pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth)\n )\n : taskEndDate;\n\n const dateRangeLabel = formatDateRangeLabel(currentStartDate, currentEndDate);\n\n // Calculate duration in days (calendar or business)\n const durationDays = businessDays\n ? getBusinessDaysCount(currentStartDate, currentEndDate, weekendPredicate)\n : 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 // Parent bars have overflow: visible (for bracket ears), so threshold must be stricter:\n // \"X задач 100%\" ≈ 60–70px text + 16px padding = ~110px\n // Regular: \"15 д 100%\" ≈ 76px, \"1 д 100%\" ≈ 62px\n const estimatedTextWidth = isParent ? 120 : (durationDays >= 10 ? 76 : 62);\n const showProgressInside = !milestone && progressWidth > 0 && displayWidth > estimatedTextWidth;\n\n // Determine if duration fits inside the bar\n // For 1-day tasks: always show duration outside (too narrow)\n // Parent bars: child count label is longer — need more space\n const MIN_DURATION_WIDTH = isParent ? 80 : 50;\n const showDurationInside = !milestone && durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;\n\n return (\n <div\n data-filter-match={isFilterMatch ? 'true' : 'false'}\n className={`gantt-tr-row ${isFilterMatch ? 'gantt-tr-row-filter-match' : ''}`}\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' : ''} ${milestone ? 'gantt-tr-milestone' : ''}`}\n style={{\n left: `${visualLeft}px`,\n ...barStyle,\n ...(milestone\n ? {\n height: `${displayMilestoneGeometry.size}px`,\n width: `${displayMilestoneGeometry.size}px`,\n padding: 0,\n }\n : {\n width: `${visualWidth}px`,\n height: isParent ? 'var(--gantt-parent-bar-height, 14px)' : 'var(--gantt-task-bar-height)',\n }),\n cursor: dragHandleProps.style.cursor,\n userSelect: dragHandleProps.style.userSelect,\n }}\n onMouseDown={dragHandleProps.onMouseDown}\n >\n {!milestone && progressWidth > 0 && progressWidth < 100 && (\n <div\n className=\"gantt-tr-progressBar\"\n style={{\n width: `${progressWidth}%`,\n backgroundColor: progressColor,\n ...(isParent && {\n borderRadius: 'var(--gantt-parent-bar-radius, 8px) 0 0 0',\n }),\n }}\n />\n )}\n {!isParent && !milestone && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleLeft\" />}\n {showDurationInside && (\n <span className=\"gantt-tr-taskDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n )}\n {progressWidth > 0 && showProgressInside && (\n <span className=\"gantt-tr-progressText\">\n {progressWidth}%\n </span>\n )}\n {!isParent && !milestone && <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: `${visualLeft}px`\n }}\n >\n <span className=\"gantt-tr-dateLabel gantt-tr-dateLabelLeft\">\n {dateRangeLabel}\n </span>\n </div>\n {task.locked && (\n <svg\n className=\"gantt-tr-lockIcon\"\n style={{\n position: 'absolute',\n left: `${visualLeft - 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: `${visualLeft + Math.max(visualWidth, 20) - Math.min(6, Math.max(visualWidth, 20) / 2) + 8}px`,\n color: isParent ? (task.color || defaultParentBarColor) : barColor,\n }}\n >\n {!showDurationInside && !milestone && (\n <span className=\"gantt-tr-externalDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n )}\n {progressWidth > 0 && !showProgressInside && (\n <span className=\"gantt-tr-externalProgress\">\n {progressWidth}%\n </span>\n )}\n <span\n className=\"gantt-tr-externalTaskName\"\n style={{ color: externalTaskNameColor }}\n >\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 * Calculate fixed-size milestone geometry centered on a single task day.\n */\nexport const calculateMilestoneGeometry = (\n taskDate: Date,\n monthStart: Date,\n dayWidth: number,\n size: number = 14\n): { centerX: number; left: number; right: number; size: number } => {\n const { left, width } = calculateTaskBar(taskDate, taskDate, monthStart, dayWidth);\n const centerX = Math.round(left + width / 2);\n const halfSize = Math.round(size / 2);\n\n return {\n centerX,\n left: centerX - halfSize,\n right: centerX + halfSize,\n size,\n };\n};\n\n/**\n * Resolve milestone connection points relative to the task day cell.\n * Anchors sit at day boundary +/- half diamond diagonal.\n */\nexport const calculateMilestoneConnectionBounds = (\n dayLeft: number,\n dayWidth: number,\n size: number = 14\n): { left: number; right: number } => {\n const halfDiagonal = Math.round(size / Math.SQRT2);\n const visualNudge = 2;\n return {\n left: dayLeft + halfDiagonal + visualNudge,\n right: dayLeft + dayWidth - halfDiagonal - visualNudge,\n };\n};\n\ntype HorizontalGeometryTask = {\n startDate: string | Date;\n endDate: string | Date;\n type?: 'task' | 'milestone';\n};\n\n/**\n * Resolve horizontal task geometry with optional drag override.\n * Milestones always stay anchored to a single day even if an override carries a wider width.\n */\nexport const resolveTaskHorizontalGeometry = (\n task: HorizontalGeometryTask,\n monthStart: Date,\n dayWidth: number,\n override?: { left: number; width: number }\n): { left: number; right: number } => {\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n\n if (task.type === 'milestone') {\n const size = 14;\n if (override) {\n return calculateMilestoneConnectionBounds(override.left, dayWidth, size);\n }\n\n const bar = calculateTaskBar(startDate, startDate, monthStart, dayWidth);\n return calculateMilestoneConnectionBounds(bar.left, dayWidth, size);\n }\n\n if (override) {\n return {\n left: override.left,\n right: override.left + override.width,\n };\n }\n\n const bar = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n return { left: bar.left, right: bar.left + bar.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 * @param isCustomWeekend - Optional predicate for custom weekend logic (e.g., holidays, shift patterns)\n * @returns Array of weekend block objects with left position and width\n *\n * Example:\n * // Default behavior (Saturday/Sunday)\n * calculateWeekendBlocks(dateRange, dayWidth)\n *\n * // Custom weekends (holidays, shifted workdays)\n * const isCustomWeekend = createIsWeekendPredicate({\n * weekends: [new Date(Date.UTC(2026, 2, 8))], // March 8 holiday\n * workdays: [new Date(Date.UTC(2026, 2, 15))] // March 15 workday\n * });\n * calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend)\n */\nexport const calculateWeekendBlocks = (\n dateRange: Date[],\n dayWidth: number,\n isCustomWeekend?: (date: Date) => boolean\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 // Use custom predicate if provided, otherwise default Saturday/Sunday\n const isWeekend = isCustomWeekend\n ? isCustomWeekend(date)\n : date.getUTCDay() === 0 || date.getUTCDay() === 6;\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 // Same column: straight vertical line without chamfer.\n // This matters for stacked milestones where the diagonal corner looks wrong.\n if (fx === tx) {\n return `M ${fx} ${fy} V ${ty}`;\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 grid line positions for week-view mode.\n * Lines appear at every 7-day boundary (each week column edge).\n * Month boundaries are always rendered at the exact day position (day 1 of a new month),\n * even when the boundary falls in the middle of a week column.\n * No day-level lines; no weekend blocks.\n *\n * @param dateRange - Array of Date objects (from getMultiMonthDays, day-based)\n * @param dayWidth - Width of each day in pixels\n * @returns Array of grid line objects sorted by x position\n */\nexport const calculateWeekGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean }> => {\n // Import getWeekBlocks locally to avoid circular dependency\n const { getWeekBlocks } = require('./dateUtils');\n const blocks = getWeekBlocks(dateRange);\n\n const lines: Array<{ x: number; isMonthStart: boolean }> = [];\n let currentDayIndex = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n currentDayIndex += block.days;\n\n // Check if this block boundary is also a month boundary\n const blockEndMonth = dateRange[currentDayIndex - 1];\n const nextBlockMonth = currentDayIndex < dateRange.length\n ? dateRange[currentDayIndex]\n : null;\n\n const isMonthBoundary = nextBlockMonth &&\n blockEndMonth.getUTCMonth() !== nextBlockMonth.getUTCMonth();\n\n lines.push({\n x: Math.round(currentDayIndex * dayWidth),\n isMonthStart: isMonthBoundary || false,\n });\n }\n\n // Remove the last line if it's at the right edge (duplicates grid border)\n if (lines.length > 0 && lines[lines.length - 1].x === Math.round(dateRange.length * dayWidth)) {\n lines.pop();\n }\n\n return lines;\n};\n\n/**\n * Calculate grid line positions for month-view mode.\n * Thin line (isMonthStart=false) at each month boundary (1st of every month).\n * Thick line (isMonthStart=true) at each year boundary (1st of January).\n * No day-level or week-level lines.\n *\n * @param dateRange - Array of Date objects (from getMultiMonthDays)\n * @param dayWidth - Width of each day in pixels\n * @returns Array of grid line objects sorted by x position\n */\nexport const calculateMonthGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean }> => {\n const lines: Array<{ x: number; isMonthStart: boolean }> = [];\n\n for (let i = 1; i < dateRange.length; i++) {\n const date = dateRange[i];\n // Линия только на 1-м числе месяца\n if (date.getUTCDate() === 1) {\n const x = Math.round(i * dayWidth);\n // Толстая линия на 1 января (граница года)\n const isYearBoundary = date.getUTCMonth() === 0;\n lines.push({ x, isMonthStart: isYearBoundary });\n }\n }\n\n return lines;\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","import type { Task } from '../types';\nimport { parseUTCDate } from './dateUtils';\n\n/**\n * Checks whether a task is behind the expected progress for the current date.\n * Uses the same progress-based rule as expired task highlighting in TaskRow.\n */\nexport const isTaskExpired = (\n task: Task | undefined,\n referenceDate: Date = new Date(),\n): boolean => {\n if (!task) return false;\n\n const actualProgress = task.progress ?? 0;\n if (actualProgress >= 100) return false;\n\n // Align the day boundary to local time, then compare using UTC-safe task dates.\n const today = new Date(Date.UTC(\n referenceDate.getFullYear(),\n referenceDate.getMonth(),\n referenceDate.getDate(),\n ));\n\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n\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 expectedProgress = (elapsed / duration) * 100;\n\n return actualProgress < expectedProgress;\n};\n","import { parseUTCDate } from './dateUtils';\n\nexport type TaskType = 'task' | 'milestone';\n\nexport type TaskWithType = {\n startDate: string | Date;\n endDate: string | Date;\n type?: TaskType;\n};\n\nexport const TASK_TYPE_DEFAULT = 'task';\n\nexport function getTaskType(task: { type?: TaskType }): TaskType {\n return task.type ?? TASK_TYPE_DEFAULT;\n}\n\nexport function isMilestoneTask(task: { type?: TaskType }): boolean {\n return getTaskType(task) === 'milestone';\n}\n\nfunction normalizeMilestoneStartDate(startDateInput: string | Date): string | Date {\n const parsedStartDate = parseUTCDate(startDateInput);\n\n if (startDateInput instanceof Date) {\n return new Date(Date.UTC(\n parsedStartDate.getUTCFullYear(),\n parsedStartDate.getUTCMonth(),\n parsedStartDate.getUTCDate()\n ));\n }\n\n return parsedStartDate.toISOString().split('T')[0];\n}\n\nexport function normalizeTaskDatesForType<\n TTask extends { startDate: string | Date; endDate: string | Date; type?: 'task' | 'milestone' }\n>(task: TTask): TTask {\n if (!isMilestoneTask(task)) {\n return task;\n }\n\n const startDate = normalizeMilestoneStartDate(task.startDate);\n\n return {\n ...task,\n endDate: startDate,\n } as TTask;\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 { isMilestoneTask, normalizeTaskDatesForType } from '../utils/taskType';\n// Domain scheduling functions\nimport {\n buildTaskRangeFromEnd,\n buildTaskRangeFromStart,\n calculateSuccessorDate,\n clampTaskRangeForIncomingFS,\n getDependencyLag,\n getTransitiveCascadeChain,\n moveTaskRange,\n recalculateIncomingLags,\n getChildren,\n isTaskParent,\n universalCascade,\n} from '../core/scheduling';\n\n// UI adapter functions (pixel-to-date conversion)\nimport { resolveDateRangeFromPixels, clampDateRangeForIncomingFS } from '../adapters/scheduling';\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, finalMode: 'move' | 'resize-left' | 'resize-right') => 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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => void;\n businessDays?: boolean;\n weekendPredicate?: (date: Date) => boolean;\n}\n\nlet globalActiveDrag: ActiveDragState | null = null;\nlet globalRafId: number | null = null;\n\nfunction getDayOffsetFromMonthStart(date: Date, monthStart: Date): number {\n return Math.round(\n (Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate())) /\n (24 * 60 * 60 * 1000)\n );\n}\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, mode } = globalActiveDrag;\n globalActiveDrag = null;\n onComplete(currentLeft, currentWidth, mode);\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 // For milestones, force width to single day regardless of stored dates\n const draggedTask = allTasks.find(t => t.id === activeDrag.taskId);\n const effectiveWidth = draggedTask && isMilestoneTask(draggedTask) ? dayWidth : initialWidth;\n\n let newLeft = initialLeft;\n let newWidth = effectiveWidth;\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 // Incoming dependency lag is editable by dragging the successor itself.\n // Do not clamp successor movement/resize by its current dependency dates;\n // the new lag will be recomputed from the final dates on drop.\n\n if (activeDrag.businessDays && activeDrag.weekendPredicate && draggedTask) {\n const previewRange = clampDateRangeForIncomingFS(\n draggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n activeDrag.monthStart,\n dayWidth,\n draggedTask,\n true,\n activeDrag.weekendPredicate\n ),\n allTasks,\n mode,\n true,\n activeDrag.weekendPredicate\n );\n const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);\n const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);\n newLeft = Math.round(alignedStartDay * dayWidth);\n newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);\n } else if (draggedTask) {\n const previewRange = clampDateRangeForIncomingFS(\n draggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n activeDrag.monthStart,\n dayWidth,\n draggedTask\n ),\n allTasks,\n mode\n );\n const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);\n const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);\n newLeft = Math.round(alignedStartDay * dayWidth);\n newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);\n }\n\n // Milestone: force single-day width after all date recalculations\n if (draggedTask && isMilestoneTask(draggedTask)) {\n newWidth = dayWidth;\n }\n\n // ── Universal preview cascade ──────────────────────────────────────────\n // Same algorithm as handleComplete — converts pixels→dates, runs\n // universalCascade, converts dates→pixels for overrides.\n\n // Universal preview: convert pixels → dates → universalCascade → pixels\n if (!activeDrag.disableConstraints && activeDrag.onCascadeProgress) {\n const { dayWidth, monthStart: mStart, taskId: dragId } = activeDrag;\n const originalDraggedTask = draggedTask ?? allTasks.find(t => t.id === dragId);\n const previewRange = originalDraggedTask\n ? clampDateRangeForIncomingFS(\n originalDraggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n mStart,\n dayWidth,\n originalDraggedTask,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n ),\n allTasks,\n mode,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n )\n : (() => {\n const previewStartDay = Math.round(newLeft / dayWidth);\n const previewEndDay = previewStartDay + Math.round(newWidth / dayWidth) - 1;\n return {\n start: new Date(Date.UTC(\n mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate() + previewStartDay\n )),\n end: new Date(Date.UTC(\n mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate() + previewEndDay\n )),\n };\n })();\n const previewStartDate = previewRange.start;\n const isMilestone = originalDraggedTask ? isMilestoneTask(originalDraggedTask) : false;\n const previewEndDate = isMilestone ? previewRange.start : previewRange.end;\n\n const movedTaskData = originalDraggedTask ?? { id: dragId, name: '', startDate: '', endDate: '' };\n const cascadeResult = universalCascade(\n { ...movedTaskData, startDate: previewStartDate.toISOString(), endDate: previewEndDate.toISOString() },\n previewStartDate,\n previewEndDate,\n allTasks,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n );\n\n const mergedPreviewTasks = allTasks.map(task => {\n const previewTask = cascadeResult.find(candidate => candidate.id === task.id);\n return previewTask ?? task;\n });\n\n const previewTasks = cascadeResult.map(task => {\n const previewStart = new Date(task.startDate as string);\n const previewEnd = new Date(task.endDate as string);\n return {\n ...task,\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n previewStart,\n previewEnd,\n mergedPreviewTasks,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n ),\n }),\n };\n });\n\n // Convert cascaded tasks → pixel overrides\n const overrides = new Map<string, { left: number; width: number }>();\n // Always include the dragged task itself\n overrides.set(dragId, { left: newLeft, width: newWidth });\n\n for (const task of cascadeResult) {\n if (task.id === dragId) continue;\n const taskStart = new Date(task.startDate as string);\n const taskEnd = new Date(task.endDate as string);\n const startOff = Math.round(\n (Date.UTC(taskStart.getUTCFullYear(), taskStart.getUTCMonth(), taskStart.getUTCDate()) -\n Date.UTC(mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const endOff = Math.round(\n (Date.UTC(taskEnd.getUTCFullYear(), taskEnd.getUTCMonth(), taskEnd.getUTCDate()) -\n Date.UTC(mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n overrides.set(task.id, {\n left: Math.round(startOff * dayWidth),\n width: Math.round((endOff - startOff + 1) * dayWidth),\n });\n }\n\n activeDrag.onCascadeProgress(overrides, previewTasks);\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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => 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 /** When true, drag is disabled globally for all tasks (shows grab cursor instead of not-allowed) */\n disableTaskDrag?: boolean;\n /** If true, dependency cascade calculations skip weekends */\n businessDays?: boolean;\n /** Function that returns true for weekends (for businessDays mode) */\n weekendPredicate?: (date: Date) => 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 locked = false,\n disableTaskDrag = false,\n businessDays = true,\n weekendPredicate,\n } = options;\n const rawHookTask = allTasks.find(t => t.id === taskId);\n const hookTask = rawHookTask ? normalizeTaskDatesForType(rawHookTask) : undefined;\n const hookTaskIsMilestone = hookTask ? isMilestoneTask(hookTask) : false;\n\n // Track if this hook instance owns the current global drag\n const isOwnerRef = useRef<boolean>(false);\n const effectiveLocked = locked || disableTaskDrag;\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 = hookTaskIsMilestone\n ? 0\n : 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, hookTaskIsMilestone]);\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, finalMode: 'move' | 'resize-left' | 'resize-right') => {\n const wasOwner = isOwnerRef.current;\n isOwnerRef.current = false;\n\n const currentTaskRaw = allTasks.find(t => t.id === taskId);\n const currentTask = currentTaskRaw ? normalizeTaskDatesForType(currentTaskRaw) : undefined;\n const finalRange = currentTask\n ? clampDateRangeForIncomingFS(\n currentTask,\n resolveDateRangeFromPixels(\n finalMode,\n finalLeft,\n finalWidth,\n monthStart,\n dayWidth,\n currentTask,\n businessDays,\n weekendPredicate\n ),\n allTasks,\n finalMode,\n businessDays,\n weekendPredicate\n )\n : (() => {\n const dayOffset = Math.round(finalLeft / dayWidth);\n const durationDays = Math.round(finalWidth / dayWidth) - 1;\n return {\n start: new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n )),\n end: new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset + durationDays\n )),\n };\n })();\n\n const newStartDate = finalRange.start;\n const newEndDate = currentTask && isMilestoneTask(currentTask)\n ? finalRange.start\n : finalRange.end;\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 // Skip if position didn't actually change (e.g. click without drag)\n const startUnchanged = newStartDate.getTime() === Date.UTC(\n initialStartDate.getUTCFullYear(), initialStartDate.getUTCMonth(), initialStartDate.getUTCDate()\n );\n const baselineEndDate = hookTaskIsMilestone ? initialStartDate : initialEndDate;\n const endUnchanged = newEndDate.getTime() === Date.UTC(\n baselineEndDate.getUTCFullYear(), baselineEndDate.getUTCMonth(), baselineEndDate.getUTCDate()\n );\n if (startUnchanged && endUnchanged) {\n // Reset position from dates (in case pixel rounding drifted)\n const { left, width } = getInitialPosition();\n setCurrentLeft(left);\n setCurrentWidth(width);\n return;\n }\n\n if (!disableConstraints && onCascade && allTasks.length > 0) {\n // Hard mode with onCascade: use universalCascade for all cases\n // (parent drag, child drag, root task drag — all handled uniformly)\n const draggedTaskData = currentTask;\n\n const movedTask: Task = {\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, businessDays, weekendPredicate),\n }),\n };\n\n const cascadeResult = universalCascade(movedTask, newStartDate, newEndDate, allTasks, businessDays, weekendPredicate);\n\n if (cascadeResult.length > 0) {\n onCascade([movedTask, ...cascadeResult]);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n\n // No dependent tasks to cascade — still call onCascade with just the moved task\n // so the state update is consistent\n onCascade([movedTask]);\n return;\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 updatedDependencies = currentTask?.dependencies\n ? recalculateIncomingLags(currentTask, newStartDate, newEndDate, allTasks, businessDays, weekendPredicate)\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 }, [\n dayWidth,\n monthStart,\n onDragEnd,\n onDragStateChange,\n taskId,\n disableConstraints,\n onCascade,\n allTasks,\n businessDays,\n weekendPredicate,\n initialStartDate,\n initialEndDate,\n hookTaskIsMilestone,\n ]);\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 (effectiveLocked) 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 if (currentTask && isMilestoneTask(currentTask)) {\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 businessDays,\n weekendPredicate,\n };\n }, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade, effectiveLocked]);\n\n /**\n * Get cursor style based on current position\n */\n const getCursorStyle = useCallback((): string => {\n if (disableTaskDrag) return 'grab'; // Global disable - allow pan\n if (locked) return 'not-allowed'; // Task-specific locked\n if (isDragging) {\n return 'grabbing';\n }\n return 'grab';\n }, [disableTaskDrag, 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","/**\n * UI adapter: converts pixel coordinates to date ranges for drag interactions.\n * @module adapters/scheduling\n *\n * These functions bridge the chart's pixel-space (left, width, dayWidth)\n * with the scheduling domain's date-space. They depend on core scheduling\n * primitives but are NOT part of the domain core themselves.\n */\n\nimport type { Task } from '../../core/scheduling/types';\nimport {\n moveTaskRange,\n buildTaskRangeFromStart,\n buildTaskRangeFromEnd,\n} from '../../core/scheduling/commands';\nimport {\n alignToWorkingDay,\n getBusinessDaysCount,\n} from '../../core/scheduling/dateMath';\nimport { clampTaskRangeForIncomingFS } from '../../core/scheduling/commands';\n\n/**\n * Convert pixel coordinates to a date range, applying business-day alignment\n * when businessDays mode is active. This is the pure scheduling core of\n * drag-to-date conversion.\n *\n * Extracted from useTaskDrag.ts resolveDraggedRange.\n */\nexport function resolveDateRangeFromPixels(\n mode: 'move' | 'resize-left' | 'resize-right',\n left: number,\n width: number,\n monthStart: Date,\n dayWidth: number,\n task: Task,\n businessDays?: boolean,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n const dayOffset = Math.round(left / dayWidth);\n const rawStartDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n ));\n const rawEndOffset = dayOffset + Math.round(width / dayWidth) - 1;\n const rawEndDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + rawEndOffset\n ));\n const isMilestone = task.type === 'milestone';\n\n // Milestone type has priority over incoming date span.\n // During drag, milestones are always treated as zero-duration (single date).\n if (isMilestone) {\n const anchorDate = mode === 'resize-right' ? rawEndDate : rawStartDate;\n if (businessDays && weekendPredicate) {\n const originalAnchor = mode === 'resize-right'\n ? new Date(task.endDate as string)\n : new Date(task.startDate as string);\n const snapDirection: 1 | -1 = anchorDate.getTime() >= originalAnchor.getTime() ? 1 : -1;\n const alignedDate = alignToWorkingDay(anchorDate, snapDirection, weekendPredicate);\n return { start: alignedDate, end: alignedDate };\n }\n return { start: anchorDate, end: anchorDate };\n }\n\n if (!(businessDays && weekendPredicate)) {\n return { start: rawStartDate, end: rawEndDate };\n }\n\n if (mode === 'move') {\n const originalStart = new Date(task.startDate as string);\n const snapDirection = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;\n return moveTaskRange(\n task.startDate,\n task.endDate,\n rawStartDate,\n true,\n weekendPredicate,\n snapDirection\n );\n }\n\n if (mode === 'resize-right') {\n const fixedStart = new Date(task.startDate as string);\n const originalEnd = new Date(task.endDate as string);\n const snapDirection: 1 | -1 = rawEndDate.getTime() >= originalEnd.getTime() ? 1 : -1;\n const alignedEnd = alignToWorkingDay(rawEndDate, snapDirection, weekendPredicate);\n const duration = Math.max(1, getBusinessDaysCount(fixedStart, alignedEnd, weekendPredicate));\n return buildTaskRangeFromStart(fixedStart, duration, true, weekendPredicate);\n }\n\n const fixedEnd = new Date(task.endDate as string);\n const originalStart = new Date(task.startDate as string);\n const snapDirection: 1 | -1 = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;\n const alignedStart = alignToWorkingDay(rawStartDate, snapDirection, weekendPredicate);\n const duration = Math.max(1, getBusinessDaysCount(alignedStart, fixedEnd, weekendPredicate));\n return buildTaskRangeFromEnd(fixedEnd, duration, true, weekendPredicate);\n}\n\n/**\n * Clamp a proposed date range based on incoming FS dependencies.\n * For resize-right mode, returns range unchanged (only start is clamped).\n *\n * Extracted from useTaskDrag.ts clampDraggedRangeForIncomingFS.\n */\nexport function clampDateRangeForIncomingFS(\n task: Task,\n range: { start: Date; end: Date },\n allTasks: Task[],\n mode: 'move' | 'resize-left' | 'resize-right',\n businessDays?: boolean,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n if (mode === 'resize-right') {\n return range;\n }\n\n return clampTaskRangeForIncomingFS(\n task,\n range.start,\n range.end,\n allTasks,\n businessDays,\n weekendPredicate\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, calculateWeekGridLines, calculateMonthGridLines } 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 /** View mode: 'day' renders per-day lines with weekend blocks, 'week' renders per-week lines only, 'month' renders per-month lines only */\n viewMode?: 'day' | 'week' | 'month';\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isCustomWeekend?: (date: Date) => boolean;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Re-renders when dateRange length, dayWidth, totalHeight, or viewMode change.\n * Returns true (skip re-render) only when all four 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 prevProps.viewMode === nextProps.viewMode &&\n prevProps.isCustomWeekend === nextProps.isCustomWeekend\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 (day-view only)\n * - React.memo optimization for performance\n * - Pointer events disabled (clicks pass through to tasks)\n *\n * View modes:\n * - day (default): per-day grid lines + weekend background blocks\n * - week: per-week grid lines only (no weekend blocks, lines every 7 days)\n */\nconst GridBackground: React.FC<GridBackgroundProps> = React.memo(\n ({ dateRange, dayWidth, totalHeight, viewMode = 'day', isCustomWeekend }) => {\n // Week-view: grid lines at each 7-day boundary\n const weekGridLines = useMemo(() => {\n if (viewMode !== 'week') return [];\n return calculateWeekGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Day-view: grid line positions per day (existing logic)\n const gridLines = useMemo<GridLine[]>(() => {\n if (viewMode === 'week' || viewMode === 'month') return [];\n return calculateGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Month-view: grid lines at each month/year boundary\n const monthGridLines = useMemo(() => {\n if (viewMode !== 'month') return [];\n return calculateMonthGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Weekend background blocks: only in day-view (locked decision from RESEARCH.md)\n const weekendBlocks = useMemo(() => {\n if (viewMode === 'week' || viewMode === 'month') return []; // No weekend highlighting in week/month-view\n return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);\n }, [dateRange, dayWidth, viewMode, isCustomWeekend]);\n\n // Calculate total grid width (formula must not change — Pitfall 3)\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) — day-view only */}\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 {viewMode === 'week' ? (\n // Week-view: one line per week column boundary\n weekGridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : 'gantt-gb-weekSeparator';\n return (\n <div\n key={`wgridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{ left: `${line.x}px` }}\n />\n );\n })\n ) : viewMode === 'month' ? (\n // Month-view: thin line at each month boundary, thick at year boundary\n monthGridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : 'gantt-gb-weekSeparator';\n return (\n <div\n key={`mgridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{ left: `${line.x}px` }}\n />\n );\n })\n ) : (\n // Day-view: existing code (unchanged)\n gridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : line.isWeekStart\n ? 'gantt-gb-weekSeparator'\n : 'gantt-gb-dayLine';\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 )}\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 { calculateDependencyPath, resolveTaskHorizontalGeometry } from '../../utils/geometry';\nimport { isMilestoneTask } from '../../utils/taskType';\nimport { getAllDependencyEdges, detectCycles } from '../../utils/dependencyUtils';\nimport './DependencyLines.css';\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 businessDays?: boolean;\n weekendPredicate?: (date: Date) => boolean;\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 businessDays = true,\n weekendPredicate,\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 // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);\n\n indices.set(task.id, index);\n positions.set(task.id, {\n left: computed.left,\n right: computed.right,\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 // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);\n\n // Store virtual position using ancestor's rowTop\n positions.set(task.id, {\n left: computed.left,\n right: computed.right,\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 taskMap = new Map(tasksForEdges.map(task => [task.id, task]));\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 const predecessorTask = taskMap.get(edge.predecessorId);\n const successorTask = taskMap.get(edge.successorId);\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 let 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 stackedMilestonesSameDay = Boolean(\n predecessorTask &&\n successorTask &&\n isMilestoneTask(predecessorTask) &&\n isMilestoneTask(successorTask) &&\n edge.lag === 0 &&\n new Date(predecessorTask.startDate).toISOString().split('T')[0] ===\n new Date(successorTask.startDate).toISOString().split('T')[0] &&\n predecessor.rowTop !== successor.rowTop &&\n edge.type === 'FS'\n );\n\n const finalToX = stackedMilestonesSameDay\n ? Math.round(((predecessor.left + predecessor.right) / 2 + (successor.left + successor.right) / 2) / 2)\n : toX;\n if (stackedMilestonesSameDay) {\n fromX = finalToX;\n }\n const arrivesFromRight = edge.type === 'FF' || edge.type === 'SF';\n\n const from = { x: fromX, y: fromY };\n const to = { x: finalToX, 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 lines.push({\n id: `${edge.predecessorId}-${edge.successorId}-${edge.type}`,\n path,\n hasCycle,\n lag: edge.lag,\n fromX,\n toX: finalToX,\n fromY,\n reverseOrder,\n isVirtual,\n });\n }\n\n return lines;\n }, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds]);\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 data-testid=\"dependency-lines-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 type { CustomDayConfig } from '../../utils/dateUtils';\nimport { createCustomDayPredicate } from '../../utils/dateUtils';\nimport { validateDependencies, calculateSuccessorDate, buildTaskRangeFromEnd, buildTaskRangeFromStart, getTaskDuration, isTaskParent, areTasksHierarchicallyRelated, getChildren } from '../../core/scheduling';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport { getVisibleReorderPosition } from '../../utils/taskListReorder';\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 type { TaskListColumn } from './columns/types';\nimport { createBuiltInColumns, BUILT_IN_COLUMN_WIDTHS } from './columns/createBuiltInColumns';\nimport { resolveTaskListColumns } from './columns/resolveTaskListColumns';\nimport type { TaskListColumn as NewTaskListColumn } from './columns/types';\nimport './TaskList.css';\n\nexport { LINK_TYPE_ICONS };\n\nconst LINK_TYPE_ORDER: LinkType[] = ['FS', 'SS', 'FF', 'SF'];\ntype DependencyPickMode = 'predecessor' | 'successor';\nconst MIN_TASK_LIST_WIDTH = 530;\n\nconst BUILT_IN_CSS_CLASSES: Record<string, string> = {\n number: 'gantt-tl-cell-number',\n name: 'gantt-tl-cell-name',\n startDate: 'gantt-tl-cell-date',\n endDate: 'gantt-tl-cell-date',\n duration: 'gantt-tl-cell-duration',\n progress: 'gantt-tl-cell-progress',\n};\n\n/**\n * Get all descendant tasks of a parent task (recursively).\n * Returns an array of all tasks where task.parentId is in the parent chain.\n *\n * @param parentId - ID of the parent task\n * @param tasks - All tasks array\n * @returns Array of descendant tasks (not including the parent itself)\n */\nfunction getAllDescendants(parentId: string, tasks: Task[]): Task[] {\n const descendants: Task[] = [];\n const visited = new Set<string>();\n\n function collectChildren(taskId: string) {\n if (visited.has(taskId)) return;\n visited.add(taskId);\n\n const children = getChildren(taskId, tasks);\n for (const child of children) {\n descendants.push(child);\n collectChildren(child.id);\n }\n }\n\n collectChildren(parentId);\n return descendants;\n}\n\nfunction duplicateTaskSubtree(anchorTaskId: string, orderedTasks: Task[]): Task[] {\n const anchorTask = orderedTasks.find(task => task.id === anchorTaskId);\n if (!anchorTask) return orderedTasks;\n\n const descendants = getAllDescendants(anchorTaskId, orderedTasks);\n const sourceIds = new Set([anchorTaskId, ...descendants.map(task => task.id)]);\n const sourceSubtree = orderedTasks.filter(task => sourceIds.has(task.id));\n const cloneIdMap = new Map(sourceSubtree.map(task => [task.id, crypto.randomUUID()]));\n\n const clonedSubtree = sourceSubtree.map(task => {\n const clonedDependencies = task.dependencies\n ?.map(dep => ({\n ...dep,\n taskId: cloneIdMap.get(dep.taskId) ?? dep.taskId,\n }));\n\n return {\n ...task,\n id: cloneIdMap.get(task.id)!,\n name: task.id === anchorTaskId ? `${task.name} (копия)` : task.name,\n parentId: task.parentId ? (cloneIdMap.get(task.parentId) ?? task.parentId) : undefined,\n dependencies: clonedDependencies,\n };\n });\n\n const anchorIndex = orderedTasks.findIndex(task => task.id === anchorTaskId);\n const insertIndex = anchorIndex + sourceSubtree.length;\n return [\n ...orderedTasks.slice(0, insertIndex),\n ...clonedSubtree,\n ...orderedTasks.slice(insertIndex),\n ];\n}\n\n/**\n * Вычисляет иерархический номер задачи на основе позиции в списке visibleTasks.\n * Корневые задачи: 1, 2, 3...\n * Дочерние задачи: 1.1, 1.2, 2.1, 2.1.1 и т.д.\n *\n * @param tasks - Массив видимых задач (уже отсортированных в иерархическом порядке)\n * @param taskIndex - Индекс задачи в массиве visibleTasks\n * @returns Иерархический номер в виде строки\n */\nfunction getTaskNumber(tasks: Task[], taskIndex: number): string {\n const task = tasks[taskIndex];\n if (!task) return '';\n\n // Если это корневая задача (нет parentId)\n if (!task.parentId) {\n // Найти порядковый номер среди корневых задач\n let rootIndex = 0;\n for (let i = 0; i < taskIndex; i++) {\n if (!tasks[i].parentId) {\n rootIndex++;\n }\n }\n return String(rootIndex + 1);\n }\n\n // Для дочерней задачи - найти родительский номер\n const parentIndex = tasks.findIndex(t => t.id === task.parentId);\n if (parentIndex === -1) {\n // Родитель не найден - fallback на плоский номер\n return String(taskIndex + 1);\n }\n\n const parentNumber = getTaskNumber(tasks, parentIndex);\n\n // Найти порядковый номер среди детей этого родителя\n let siblingIndex = 0;\n for (let i = 0; i < taskIndex; i++) {\n if (tasks[i].parentId === task.parentId) {\n siblingIndex++;\n }\n }\n\n return `${parentNumber}.${siblingIndex + 1}`;\n}\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. Values below MIN_TASK_LIST_WIDTH are clamped. */\n taskListWidth?: number;\n /** Callback when tasks are modified via inline edit. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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 /** Show right-side shadow when chart content is horizontally scrolled */\n hasRightShadow?: 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 /** Custom day configurations for date picker */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate for date picker */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях */\n businessDays?: boolean;\n /** Task IDs highlighted by the active filter */\n highlightedTaskIds?: Set<string>;\n /** Filter mode: 'highlight' shows yellow highlight on matches, 'hide' hides non-matching tasks */\n filterMode?: 'highlight' | 'hide';\n /** Task IDs that match the filter (used for hide mode). When undefined, no filtering is applied */\n filteredTaskIds?: Set<string>;\n /** Whether filter is currently active (needed to distinguish \"no filter\" from \"filter with no matches\") */\n isFilterActive?: boolean;\n /** Additional columns to display after built-in columns */\n additionalColumns?: TaskListColumn<any>[];\n}\n\ninterface PendingInsertState {\n anchorTaskId: string;\n insertAfterTaskId: string;\n parentId?: string;\n startDate: string | Date;\n endDate: string | Date;\n nestingDepth: number;\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, Duration, Progress, 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 = MIN_TASK_LIST_WIDTH,\n onTasksChange,\n selectedTaskId,\n onTaskSelect,\n show = true,\n hasRightShadow = false,\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 customDays,\n isWeekend,\n businessDays,\n highlightedTaskIds = new Set(),\n filterMode = 'highlight',\n filteredTaskIds = new Set(),\n isFilterActive = false,\n additionalColumns,\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(() => {\n return normalizeHierarchyTasks(tasks);\n }, [tasks]);\n\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\n\n // Filter tasks to hide children of collapsed parents.\n // Checks the full ancestor chain so grandchildren are hidden when any ancestor is collapsed.\n const visibleTasks = useMemo(() => {\n const parentMap = new Map(orderedTasks.map(t => [t.id, (t as any).parentId as string | undefined]));\n\n function isAnyAncestorCollapsed(parentId: string | undefined): boolean {\n let current = parentId;\n while (current) {\n if (collapsedParentIds.has(current)) return true;\n current = parentMap.get(current);\n }\n return false;\n }\n\n let tasks = orderedTasks.filter(task => !isAnyAncestorCollapsed((task as any).parentId));\n\n // In 'hide' mode with active filter, only show matching tasks\n if (filterMode === 'hide' && isFilterActive) {\n tasks = tasks.filter(task => filteredTaskIds.has(task.id));\n }\n\n return tasks;\n }, [orderedTasks, collapsedParentIds, filterMode, filteredTaskIds, isFilterActive]);\n\n const totalHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.length, rowHeight]\n );\n const visibleTaskNumberMap = useMemo(\n () =>\n Object.fromEntries(\n visibleTasks.map((task, index) => [task.id, String(getTaskNumber(visibleTasks, index))])\n ) as Record<string, string>,\n [visibleTasks]\n );\n\n // Оригинальные номера задач на основе полного списка (до фильтрации)\n // Используются для сохранения нумерации при скрытии задач\n const originalTaskNumberMap = useMemo(\n () => {\n const numberMap = new Map<string, string>();\n for (let i = 0; i < orderedTasks.length; i++) {\n numberMap.set(orderedTasks[i].id, getTaskNumber(orderedTasks, i));\n }\n return Object.fromEntries(numberMap) as Record<string, string>;\n },\n [orderedTasks]\n );\n\n // Compute nesting depth for each task (0 = root, 1 = child, 2 = grandchild, etc.)\n const nestingDepthMap = useMemo(() => {\n const depthMap = new Map<string, number>();\n const taskById = new Map(tasks.map(t => [t.id, t]));\n\n function getDepth(taskId: string): number {\n if (depthMap.has(taskId)) return depthMap.get(taskId)!;\n const task = taskById.get(taskId);\n if (!task || !(task as any).parentId || !taskById.has((task as any).parentId)) {\n depthMap.set(taskId, 0);\n return 0;\n }\n const depth = getDepth((task as any).parentId) + 1;\n depthMap.set(taskId, depth);\n return depth;\n }\n\n for (const task of tasks) {\n getDepth(task.id);\n }\n return depthMap;\n }, [tasks]);\n\n // For each child task, determine if it's the last visible child of its parent\n const lastChildIds = useMemo(() => {\n const last = new Set<string>();\n const seenParents = new Set<string>();\n for (let i = visibleTasks.length - 1; i >= 0; i--) {\n const t = visibleTasks[i] as Task;\n if (t.parentId && !seenParents.has(t.parentId)) {\n last.add(t.id);\n seenParents.add(t.parentId);\n }\n }\n return last;\n }, [visibleTasks]);\n\n const visibleParentIds = useMemo(() => {\n const parentIds = new Set<string>();\n for (const task of visibleTasks) {\n if (task.parentId) parentIds.add(task.parentId);\n }\n return parentIds;\n }, [visibleTasks]);\n\n // For each visible task, determine whether each ancestor line above the direct parent\n // should continue through the full row or terminate at the row midpoint.\n const ancestorLineModesMap = useMemo(() => {\n const taskById = new Map(tasks.map(t => [t.id, t]));\n\n const isDescendantOf = (taskId: string, ancestorId: string): boolean => {\n let current: any = taskById.get(taskId);\n while (current?.parentId && taskById.has(current.parentId)) {\n if (current.parentId === ancestorId) return true;\n current = taskById.get(current.parentId);\n }\n return false;\n };\n\n const map = new Map<string, (\"full\" | \"half\")[]>();\n for (let index = 0; index < visibleTasks.length; index++) {\n const task = visibleTasks[index];\n const ancestorIds: string[] = [];\n let current: any = taskById.get(task.id);\n while (current?.parentId && taskById.has(current.parentId)) {\n ancestorIds.unshift(current.parentId as string);\n current = taskById.get(current.parentId);\n }\n\n const ancestorsAboveParent = ancestorIds.slice(0, -1);\n const modes = ancestorsAboveParent.map((ancestorId) => {\n const hasLaterVisibleDescendant = visibleTasks\n .slice(index + 1)\n .some((laterTask) => isDescendantOf(laterTask.id, ancestorId));\n return hasLaterVisibleDescendant ? \"full\" : \"half\";\n });\n\n map.set(task.id, modes);\n }\n return map;\n }, [tasks, visibleTasks]);\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 [dependencyPickMode, setDependencyPickMode] = useState<DependencyPickMode>('successor');\n const [typeMenuOpen, setTypeMenuOpen] = useState(false);\n const [dependencyError, setDependencyError] = useState<string | null>(null);\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, chip selection, and task row selection\n useEffect(() => {\n if (!selectingPredecessorFor && !selectedChip && !selectedTaskId) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n onTaskSelect?.(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 onTaskSelect?.(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, selectedTaskId, onTaskSelect, 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 links between ancestors and descendants in either direction\n if (areTasksHierarchicallyRelated(successorTaskId, predecessorTaskId, tasks)) {\n setDependencyError('Связи между родителем и потомком запрещены');\n setTimeout(() => setDependencyError(null), 3000);\n setSelectingPredecessorFor(null);\n return;\n }\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 const hasHierarchyConstraint = validation.errors.some(error => error.type === 'constraint');\n setDependencyError(\n hasHierarchyConstraint\n ? 'Связи между родителем и потомком запрещены'\n : 'Цикл зависимостей!'\n );\n setTimeout(() => setDependencyError(null), 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(\n predStart,\n predEnd,\n linkType,\n 0,\n businessDays ?? true,\n weekendPredicate\n );\n\n const origSuccessor = tasks.find(t => t.id === successorTaskId)!;\n const duration = getTaskDuration(\n origSuccessor.startDate,\n origSuccessor.endDate,\n businessDays ?? true,\n weekendPredicate\n );\n\n let newStart: Date;\n let newEnd: Date;\n\n if (linkType === 'FS' || linkType === 'SS') {\n ({ start: newStart, end: newEnd } = buildTaskRangeFromStart(\n constraintDate,\n duration,\n businessDays ?? true,\n weekendPredicate\n ));\n } else {\n ({ start: newStart, end: newEnd } = buildTaskRangeFromEnd(\n constraintDate,\n duration,\n businessDays ?? true,\n weekendPredicate\n ));\n }\n\n const snappedTask: Task = {\n ...updatedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n };\n onTasksChange?.([snappedTask]);\n } else {\n // Predecessor not found — emit without snap (graceful fallback)\n onTasksChange?.([updatedTask]);\n }\n\n setSelectingPredecessorFor(null);\n }, [tasks, onTasksChange]);\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 onTasksChange?.([{ ...task, dependencies: updatedDeps }]);\n }, [tasks, onTasksChange]);\n\n // New task creation state\n const [isCreating, setIsCreating] = useState(false);\n const [pendingInsert, setPendingInsert] = useState<PendingInsertState | null>(null);\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 const dragTaskIdRef = useRef<string | null>(null);\n\n // Helper: check if a parent task can be dropped at a specific position\n // Parent tasks cannot be dropped:\n // 1. Between their own children\n // 2. Between another parent's children (would make them a child)\n // 3. Under their own descendants (would create a cycle)\n const isValidParentDrop = useCallback((draggedTaskId: string, dropIndex: number): boolean => {\n // If not a parent, allow all drops\n if (!isTaskParent(draggedTaskId, tasks)) {\n return true;\n }\n\n const dropTarget = visibleTasks[dropIndex];\n if (!dropTarget) return true;\n\n // Scenario 1: Dropping parent between its own children\n if (dropTarget.parentId === draggedTaskId) {\n return false;\n }\n\n // Scenario 2: Dropping parent between another parent's children\n // Allow this for unlimited nesting — parent can become nested under another task.\n // Scenarios 1 and 3 still protect against circular references and self-nesting.\n\n // Scenario 3: Dropping parent under one of its own descendants\n // This would create a cycle (parent becomes child of its descendant)\n // Check if dropTarget is a descendant of draggedTaskId\n const draggedTask = orderedTasks.find(t => t.id === draggedTaskId);\n if (!draggedTask) return true;\n\n const descendants = getAllDescendants(draggedTaskId, orderedTasks);\n const descendantIds = new Set(descendants.map(d => d.id));\n\n if (descendantIds.has(dropTarget.id)) {\n return false;\n }\n\n // Allow dropping on other root tasks (parents or non-parents)\n return true;\n }, [tasks, visibleTasks, orderedTasks]);\n\n const handleDragStart = useCallback((index: number, e: React.DragEvent) => {\n e.dataTransfer.effectAllowed = 'move';\n setDraggingIndex(index);\n dragOriginIndexRef.current = index;\n dragTaskIdRef.current = visibleTasks[index]?.id ?? null;\n }, [visibleTasks]);\n\n const handleDragOver = useCallback((index: number, e: React.DragEvent) => {\n e.preventDefault();\n\n const draggedTaskId = dragTaskIdRef.current;\n if (!draggedTaskId) return;\n\n // Don't show drop indication if this is an invalid parent drop\n if (!isValidParentDrop(draggedTaskId, index)) {\n setDragOverIndex(null);\n e.dataTransfer.dropEffect = 'none';\n return;\n }\n\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(index);\n }, [isValidParentDrop]);\n\n const handleDrop = useCallback((dropIndex: number, e: React.DragEvent) => {\n e.preventDefault();\n const originVisibleIndex = dragOriginIndexRef.current;\n const movedTaskId = dragTaskIdRef.current;\n\n // No-op: same position (line is already where the row is)\n if (originVisibleIndex === null || movedTaskId === null || originVisibleIndex === dropIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n // Reject invalid parent drops (parent being dragged into children or another parent)\n if (!isValidParentDrop(movedTaskId, dropIndex)) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const reorderPosition = getVisibleReorderPosition(\n orderedTasks,\n visibleTasks,\n movedTaskId,\n originVisibleIndex,\n dropIndex,\n );\n\n if (!reorderPosition) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const { originOrderedIndex, insertIndex } = reorderPosition;\n\n // Early exit: if insertIndex equals originOrderedIndex, the subtree would be removed\n // and re-inserted at the exact same position - a true no-op. Skip the callback.\n if (insertIndex === originOrderedIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const moved = orderedTasks[originOrderedIndex];\n\n // Check if this is a parent task with children\n const hasChildren = isTaskParent(moved.id, orderedTasks);\n\n // Extract the subtree to move (parent + all descendants, if any)\n let subtree: Task[];\n let subtreeCount: number;\n\n if (hasChildren) {\n // Get all descendants of the parent\n const descendants = getAllDescendants(moved.id, orderedTasks);\n subtree = [moved, ...descendants];\n subtreeCount = subtree.length;\n } else {\n // Single task (not a parent)\n subtree = [moved];\n subtreeCount = 1;\n }\n\n const reordered = [...orderedTasks];\n\n // Remove the entire subtree from its original position\n reordered.splice(originOrderedIndex, subtreeCount);\n\n // CRITICAL: insertIndex is already relative to reorderedWithoutMoved\n // After the splice, reordered === reorderedWithoutMoved (same array, same order)\n // So we should use insertIndex directly, NOT insertIndex - subtreeCount\n // The old code was subtracting subtreeCount again, which was incorrect\n const adjustedInsertIndex = insertIndex;\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 if (parentIndex === -1) {\n // Parent not found - should not happen, but handle gracefully\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 // If adjustedInsertIndex is <= parent (at or above parent position) or > groupEnd (below all siblings)\n // Note: adjustedInsertIndex == 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 (adjustedInsertIndex <= parentIndex || adjustedInsertIndex > groupEnd) {\n inferredParentId = undefined; // Exit group - become root\n } else {\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 after splicing\n }\n\n // Now splice the entire subtree into its final position\n reordered.splice(adjustedInsertIndex, 0, ...subtree);\n\n // For root tasks, check if they should join a group (need reordered for this)\n // IMPORTANT: Parent tasks (hasChildren === true) must NEVER be reparented during drag-drop.\n // They always stay at root level regardless of where they are dropped.\n // Only leaf/child tasks (non-parents) can be adopted into a group by neighboring tasks.\n if (!moved.parentId && !hasChildren) {\n const taskAbove = adjustedInsertIndex > 0 ? reordered[adjustedInsertIndex - 1] : null;\n const taskBelow = adjustedInsertIndex < reordered.length - 1 ? reordered[adjustedInsertIndex + 1] : null;\n\n // Join a group ONLY if placed between parent and its first child,\n // or between two children of the same parent.\n // Dropping after the last child of a group keeps the task at root level.\n if (taskAbove && taskBelow && taskBelow.parentId === taskAbove.id) {\n // Placed between a parent and its first child\n inferredParentId = taskAbove.id;\n } else if (taskAbove && taskBelow && taskAbove.parentId && taskAbove.parentId === taskBelow.parentId) {\n // Placed between two children of the same parent\n inferredParentId = taskAbove.parentId;\n } else if (!taskAbove && taskBelow && taskBelow.parentId) {\n // Placed at the very top, above a child — join that group\n inferredParentId = taskBelow.parentId;\n }\n }\n\n onReorder?.(reordered, moved.id, inferredParentId);\n onTaskSelect?.(moved.id);\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n }, [orderedTasks, visibleTasks, 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 dragTaskIdRef.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 const findInsertAfterTaskId = useCallback((anchorTaskId: string): string => {\n const anchorIndex = orderedTasks.findIndex(task => task.id === anchorTaskId);\n if (anchorIndex === -1) {\n return anchorTaskId;\n }\n\n const taskById = new Map(orderedTasks.map(task => [task.id, task]));\n let insertAfterTaskId = anchorTaskId;\n\n for (let index = anchorIndex + 1; index < orderedTasks.length; index += 1) {\n let currentParentId = orderedTasks[index]?.parentId;\n let isDescendant = false;\n\n while (currentParentId) {\n if (currentParentId === anchorTaskId) {\n isDescendant = true;\n break;\n }\n currentParentId = taskById.get(currentParentId)?.parentId;\n }\n\n if (!isDescendant) {\n break;\n }\n\n insertAfterTaskId = orderedTasks[index].id;\n }\n\n return insertAfterTaskId;\n }, [orderedTasks]);\n\n const pendingInsertDisplayTaskId = useMemo(() => {\n if (!pendingInsert) {\n return null;\n }\n\n const taskById = new Map(visibleTasks.map(task => [task.id, task]));\n if (!taskById.has(pendingInsert.anchorTaskId)) {\n return null;\n }\n\n let displayTaskId = pendingInsert.anchorTaskId;\n\n for (const task of visibleTasks) {\n let currentParentId = task.parentId;\n while (currentParentId) {\n if (currentParentId === pendingInsert.anchorTaskId) {\n displayTaskId = task.id;\n break;\n }\n currentParentId = taskById.get(currentParentId)?.parentId;\n }\n }\n\n return displayTaskId;\n }, [pendingInsert, visibleTasks]);\n\n const handleStartInsertAfter = useCallback((taskId: string, newTask: Task) => {\n const anchorTask = orderedTasks.find(task => task.id === taskId);\n if (!anchorTask) {\n return;\n }\n\n setIsCreating(false);\n setPendingInsert({\n anchorTaskId: taskId,\n insertAfterTaskId: findInsertAfterTaskId(taskId),\n parentId: anchorTask.parentId,\n startDate: newTask.startDate,\n endDate: newTask.endDate,\n nestingDepth: nestingDepthMap.get(taskId) ?? 0,\n });\n }, [findInsertAfterTaskId, nestingDepthMap, orderedTasks]);\n\n const handleConfirmInsertedTask = useCallback((name: string) => {\n if (!pendingInsert) {\n return;\n }\n\n const newTask: Task = {\n id: crypto.randomUUID(),\n name,\n startDate: pendingInsert.startDate,\n endDate: pendingInsert.endDate,\n parentId: pendingInsert.parentId,\n };\n\n onInsertAfter?.(pendingInsert.insertAfterTaskId, newTask);\n setPendingInsert(null);\n }, [onInsertAfter, pendingInsert]);\n\n const handleCancelInsertedTask = useCallback(() => setPendingInsert(null), []);\n\n /**\n * Calculate the depth of a task in the hierarchy.\n * Root tasks have depth 0, their children have depth 1, etc.\n */\n function getTaskDepth(task: Task | undefined, tasks: Task[]): number {\n if (!task) return 0;\n let depth = 0;\n let current: Task | undefined = task;\n while (current) {\n if (!current.parentId) break;\n depth++;\n const parentId: string = current.parentId;\n current = tasks.find(t => t.id === parentId);\n }\n return depth;\n }\n\n /**\n * Demote wrapper — move task down one level in hierarchy.\n *\n * Rules:\n * 1. Find the PREVIOUS task at the SAME depth level (same hierarchy level)\n * 2. Make that task the parent of the current task\n * 3. If no previous task at same level exists (first task), create \"Новый раздел\"\n *\n * Example:\n * - Task 1.1 (depth 1)\n * - Task 1.2 (depth 1)\n * - [Task to demote] (depth 1) → becomes child of Task 1.2\n *\n * Result:\n * - Task 1.1 (depth 1)\n * - Task 1.2 (depth 1)\n * - Task to demote (depth 2, child of 1.2)\n *\n * The `_newParentId` argument from TaskListRow is ignored — we compute the correct parent here.\n */\n const handleDemoteWrapper = useCallback((taskId: string, _newParentId: string) => {\n const taskIndex = visibleTasks.findIndex(t => t.id === taskId);\n const currentTask = visibleTasks[taskIndex];\n const currentDepth = getTaskDepth(currentTask, orderedTasks);\n\n if (taskIndex > 0) {\n // Search backwards for the previous task at the same depth level\n for (let i = taskIndex - 1; i >= 0; i--) {\n const previousTask = visibleTasks[i];\n const previousDepth = getTaskDepth(previousTask, orderedTasks);\n\n // Found a task at the same level - use it as parent\n if (previousDepth === currentDepth) {\n onDemoteTask?.(taskId, previousTask.id);\n return;\n }\n\n // If we encounter a task at a shallower depth, stop searching\n // (no same-level task exists before this point)\n if (previousDepth < currentDepth) {\n break;\n }\n }\n\n // No same-level task found - cannot demote\n return;\n }\n\n // First-task case: create \"Новый раздел\" as a new root parent\n const demotedTask = orderedTasks.find(t => t.id === taskId);\n if (!demotedTask) return;\n\n const newSectionTask: Task = {\n id: crypto.randomUUID(),\n name: 'Новый раздел',\n startDate: demotedTask.startDate,\n endDate: demotedTask.endDate,\n };\n\n const updatedTasks: Task[] = [\n newSectionTask,\n ...orderedTasks.map(t =>\n t.id === taskId ? { ...t, parentId: newSectionTask.id } : t\n ),\n ];\n\n onReorder?.(updatedTasks, taskId, newSectionTask.id);\n }, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);\n\n const handleDuplicateTask = useCallback((taskId: string) => {\n const duplicatedTasks = duplicateTaskSubtree(taskId, orderedTasks);\n onReorder?.(duplicatedTasks);\n }, [orderedTasks, onReorder]);\n\n // ---- Column resolution ----\n const builtInColumns = useMemo(() => createBuiltInColumns<Task>({ businessDays }), [businessDays]);\n const resolvedColumns = useMemo(\n () => resolveTaskListColumns(builtInColumns, (additionalColumns ?? []) as NewTaskListColumn<Task>[]),\n [builtInColumns, additionalColumns]\n );\n const resolvedColumnWidthTotal = useMemo(\n () => resolvedColumns.reduce((sum, col) => sum + (col.width ?? 120), 0),\n [resolvedColumns]\n );\n\n const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH, resolvedColumnWidthTotal);\n\n return (\n <div\n ref={overlayRef}\n className={`gantt-tl-overlay${show ? '' : ' gantt-tl-hidden'}${hasRightShadow ? ' gantt-tl-overlay-shadowed' : ''}`}\n style={{ '--tasklist-width': `${effectiveTaskListWidth}px` } as React.CSSProperties}\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 {resolvedColumns.map(col => {\n // Dependencies header has special Popover UI\n if (col.id === 'dependencies') {\n return (\n <div key={col.id} className=\"gantt-tl-headerCell gantt-tl-cell-deps\"\n data-column-id=\"dependencies\"\n 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 {dependencyError && (\n <div className=\"gantt-tl-dep-error\">{dependencyError}</div>\n )}\n </div>\n );\n }\n // Built-in columns use CSS classes for width (same as body cells — no inline width override)\n const builtInClass = BUILT_IN_CSS_CLASSES[col.id];\n if (builtInClass !== undefined) {\n return (\n <div key={col.id}\n className={`gantt-tl-headerCell ${builtInClass}`}\n data-column-id={col.id}>\n {col.header}\n </div>\n );\n }\n // Custom columns\n return (\n <div key={col.id}\n className=\"gantt-tl-headerCell gantt-tl-headerCell-custom\"\n data-column-id={`custom:${col.id}`}\n data-custom-column-id={col.id}\n style={{ width: col.width, minWidth: col.width, flexShrink: 0 }}>\n {col.header}\n </div>\n );\n })}\n </div>\n\n {/* Data rows */}\n <div className=\"gantt-tl-body\" style={{ height: `${totalHeight}px` }}>\n {visibleTasks.map((task, index) => {\n const previousVisibleTask = index > 0 ? visibleTasks[index - 1] : undefined;\n const canDemoteTask = index === 0\n || !task.parentId\n || previousVisibleTask?.id !== task.parentId;\n\n return (\n <React.Fragment key={task.id}>\n <TaskListRow\n task={task}\n rowIndex={index}\n taskNumber={originalTaskNumberMap[task.id] || ''}\n taskNumberMap={originalTaskNumberMap}\n rowHeight={rowHeight}\n onTasksChange={onTasksChange}\n selectedTaskId={selectedTaskId}\n onRowClick={handleRowClick}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n allTasks={tasks}\n activeLinkType={activeLinkType}\n onSetActiveLinkType={setActiveLinkType}\n selectingPredecessorFor={selectingPredecessorFor}\n dependencyPickMode={dependencyPickMode}\n onSetDependencyPickMode={setDependencyPickMode}\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={handleStartInsertAfter}\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 ? handleDemoteWrapper : undefined}\n onDuplicateTask={onReorder ? handleDuplicateTask : undefined}\n canDemoteTask={canDemoteTask}\n isLastChild={lastChildIds.has(task.id)}\n nestingDepth={nestingDepthMap.get(task.id) ?? 0}\n hasVisibleChildren={visibleParentIds.has(task.id)}\n ancestorLineModes={ancestorLineModesMap.get(task.id) ?? []}\n customDays={customDays}\n isWeekend={isWeekend}\n businessDays={businessDays}\n isFilterMatch={filterMode === 'highlight' ? highlightedTaskIds.has(task.id) : false}\n isFilterHideMode={filterMode === 'hide' && isFilterActive}\n resolvedColumns={resolvedColumns}\n />\n {pendingInsertDisplayTaskId === task.id && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmInsertedTask}\n onCancel={handleCancelInsertedTask}\n nestingDepth={pendingInsert?.nestingDepth ?? 0}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n\n {/* Ghost row for new task creation — positioned OUTSIDE body div to avoid height desync */}\n {isCreating && !pendingInsert && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmNewTask}\n onCancel={handleCancelNewTask}\n nestingDepth={0}\n />\n )}\n\n {/* Add task button - also serves as drop target for moving tasks to end */}\n {enableAddTask && onAdd && !isCreating && !pendingInsert && (\n <button\n className={`gantt-tl-add-btn${dragOverIndex === visibleTasks.length ? ' gantt-tl-add-btn-drag-over' : ''}`}\n onClick={() => {\n setPendingInsert(null);\n setIsCreating(true);\n }}\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","import type { Task } from '../components/GanttChart';\n\ntype TaskLike = { id: string };\n\nexport interface VisibleReorderPosition {\n originOrderedIndex: number;\n insertIndex: number;\n}\n\n/**\n * Get all descendant IDs of a task (recursively).\n * Used to identify the entire subtree that must move together when dragging a parent.\n */\nfunction getDescendantIds(taskId: string, tasks: TaskLike[]): string[] {\n const descendants: string[] = [];\n const visited = new Set<string>();\n\n function collect(id: string) {\n if (visited.has(id)) return;\n visited.add(id);\n\n // Find all direct children of this task\n for (const task of tasks) {\n if ((task as any).parentId === id && !visited.has(task.id)) {\n descendants.push(task.id);\n collect(task.id);\n }\n }\n }\n\n collect(taskId);\n return descendants;\n}\n\n/**\n * Map visible drag/drop positions to indices in the full ordered task list.\n * This keeps collapsed descendants attached to their parent row.\n *\n * When dragging a parent task, all its descendants are included in the move,\n * so they are all filtered out before calculating the insert position.\n */\nexport function getVisibleReorderPosition(\n orderedTasks: TaskLike[],\n visibleTasks: TaskLike[],\n movedTaskId: string,\n originVisibleIndex: number,\n dropVisibleIndex: number,\n): VisibleReorderPosition | null {\n const originOrderedIndex = orderedTasks.findIndex((task) => task.id === movedTaskId);\n if (originOrderedIndex === -1) {\n return null;\n }\n\n // Get all descendant IDs if this is a parent task\n const descendantIds = getDescendantIds(movedTaskId, orderedTasks);\n const allMovedIds = new Set([movedTaskId, ...descendantIds]);\n\n // Filter out ALL tasks that will move (parent + descendants)\n const reorderedWithoutMoved = orderedTasks.filter((task) => !allMovedIds.has(task.id));\n const visibleWithoutMoved = visibleTasks.filter((task) => !allMovedIds.has(task.id));\n\n if (visibleWithoutMoved.length === 0) {\n return { originOrderedIndex, insertIndex: 0 };\n }\n\n // CRITICAL: dropVisibleIndex is an index into the ORIGINAL visibleTasks, NOT into\n // visibleWithoutMoved (which has fewer items after removing the moved subtree).\n // We must look up the actual drop target task by its ID from the original list,\n // then find it in visibleWithoutMoved.\n\n // Look up the actual task at the drop position in the ORIGINAL visible list\n const dropTargetTask = visibleTasks[dropVisibleIndex];\n\n if (!dropTargetTask) {\n // dropVisibleIndex is beyond the end of the original list - append at end\n return {\n originOrderedIndex,\n insertIndex: reorderedWithoutMoved.length,\n };\n }\n\n // Find the drop target in the filtered array (visibleWithoutMoved has the moved subtree removed)\n const filteredDropIndex = visibleWithoutMoved.findIndex((t) => t.id === dropTargetTask.id);\n\n if (filteredDropIndex === -1) {\n // Drop target was part of the moved subtree - should not happen after isValidParentDrop check\n // Append at end as fallback\n return {\n originOrderedIndex,\n insertIndex: reorderedWithoutMoved.length,\n };\n }\n\n const targetVisibleTask = visibleWithoutMoved[filteredDropIndex];\n\n // Find the target in reorderedWithoutMoved.\n // The drop indicator semantics: indicator at position N shows the TOP border of row N,\n // meaning the task will be inserted ABOVE row N.\n // We use the drop target's position directly without skipping past its group.\n // This preserves \"drop at top of родитель2 = insert before родитель2\" semantics.\n // To move a parent PAST родитель2's entire group, the user must drag to the end of the list\n // (past all of родитель2's children), which triggers the \"append at end\" path above.\n const insertIndex = reorderedWithoutMoved.findIndex((task) => task.id === targetVisibleTask.id);\n\n return {\n originOrderedIndex,\n insertIndex,\n };\n}\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, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useMemo,\n} from \"react\";\nimport type { Task } from \"../GanttChart\";\nimport type { LinkType } from \"../../types\";\nimport type { CustomDayConfig } from \"../../utils/dateUtils\";\nimport { parseUTCDate, normalizeTaskDates, createCustomDayPredicate } from \"../../utils/dateUtils\";\nimport { isMilestoneTask, normalizeTaskDatesForType } from \"../../utils/taskType\";\nimport {\n getBusinessDaysCount,\n addBusinessDays,\n subtractBusinessDays,\n alignToWorkingDay,\n buildTaskRangeFromEnd,\n buildTaskRangeFromStart,\n getDependencyLag,\n calculateSuccessorDate,\n clampTaskRangeForIncomingFS,\n normalizeDependencyLag,\n isTaskParent,\n findParentId,\n getChildren,\n recalculateIncomingLags,\n} from \"../../core/scheduling\";\nimport { Input } from \"../ui/Input\";\nimport { DatePicker } from \"../ui/DatePicker\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/Popover\";\nimport { LINK_TYPE_ICONS } from \"./DepIcons\";\nimport type { TaskListColumn as NewTaskListColumn } from \"./columns/types\";\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst LINK_TYPE_ORDER: LinkType[] = [\"FS\", \"SS\", \"FF\", \"SF\"];\n\nconst getInclusiveDurationDays = (\n startDate: string | Date,\n endDate: string | Date,\n): number => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n return Math.max(\n 1,\n Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1,\n );\n};\n\nconst getEndDateFromDuration = (\n startDate: string | Date,\n durationDays: number,\n): string => {\n const start = parseUTCDate(startDate);\n return new Date(start.getTime() + (durationDays - 1) * DAY_MS)\n .toISOString()\n .split(\"T\")[0];\n};\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 taskNumber?: string;\n taskNumberMap?: Record<string, string>;\n predecessorName?: string;\n predecessorTaskNumber?: 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 /** The successor task (needed for lag date computation) */\n task: Task;\n /** All tasks (needed to find predecessor dates) */\n allTasks: Task[];\n /** Callback to save date changes after lag modification */\n onTasksChange?: TaskListRowProps[\"onTasksChange\"];\n businessDays?: boolean;\n weekendPredicate: (date: Date) => boolean;\n}\n\nconst TrashIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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\nconst VerticalDotsIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"19\" r=\"2\" />\n </svg>\n);\n\nconst CopyIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n);\n\nconst TASK_COLOR_PALETTE = [\n // { label: \"Палисандр\", value: \"#A61E4D\" },\n // { label: \"Киноварь\", value: \"#E8590C\" },\n // { label: \"Жёлт\", value: \"#eec45c\" },\n { label: \"Киноварь2\", value: \"#fe724e\" },\n // { label: \"Оранжевый\", value: \"#F08C00\" },\n { label: \"Оранжевый2\", value: \"#ff991f\" },\n { label: \"Золотой\", value: \"#e5c800\" },\n { label: \"Бирюза\", value: \"#58d8a3\" },\n { label: \"Палисандр\", value: \"#d64a7b\" },\n { label: \"Песочный\", value: \"#997B10\" },\n { label: \"Шартрез\", value: \"#A3BE00\" },\n { label: \"Голубой\", value: \"#03c7e6\" },\n { label: \"Виноград2\", value: \"#8678d9\" },\n { label: \"Серый2\", value: \"#6b778c\" },\n { label: \"Лесной\", value: \"#2B8A3E\" },\n // { label: \"Лесной3\", value: \"#60b838\" },\n // { label: \"Бирюза\", value: \"#0B7285\" },\n // { label: \"Серый\", value: \"#495057\" },\n // { label: \"Океан\", value: \"#5244ff\" },\n // { label: \"Океан2\", value: \"#0626ba\" },\n // { label: \"Виноград\", value: \"#AE3EC9\" },\n] as const;\n\nconst ChevronRightIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst LINK_TYPE_LABELS_RU: Record<LinkType, string> = {\n FS: \"ОН\",\n SS: \"НН\",\n FF: \"ОО\",\n SF: \"НО\",\n};\n\nfunction formatTaskNumberLabel(taskNumber?: string): string {\n return taskNumber ? `${taskNumber}. ` : \"\";\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 /** Row index - first row cannot demote */\n rowIndex: number;\n /** Whether demote action should be shown for this row */\n canDemote: boolean;\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 ArrowLeft = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n);\n\nconst ArrowRight = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n);\n\nconst HierarchyButton: React.FC<HierarchyButtonProps> = ({\n isChild,\n rowIndex: _rowIndex,\n canDemote,\n onPromote,\n onDemote,\n}) => {\n const canPromote = isChild && onPromote;\n const showDemote = canDemote && !!onDemote;\n\n if (!canPromote && !showDemote) return null;\n\n return (\n <>\n {canPromote && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={(e) => {\n e.stopPropagation();\n onPromote!(e);\n }}\n title=\"Повысить уровень\"\n >\n <ArrowLeft />\n </button>\n )}\n {showDemote && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={(e) => {\n e.stopPropagation();\n onDemote!(e);\n }}\n title=\"Понизить уровень\"\n >\n <ArrowRight />\n </button>\n )}\n </>\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)\n return `Начать через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0)\n return `Начать за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Начать сразу после окончания`;\n }\n if (type === \"FF\") {\n if (effectiveLag > 0)\n return `Завершить через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0)\n return `Завершить за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Завершить после окончания`;\n }\n if (type === \"SS\") {\n if (effectiveLag > 0)\n return `Начать через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0)\n return `Начать за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Начать вместе с началом`;\n }\n if (type === \"SF\") {\n if (effectiveLag > 0)\n return `Завершить через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0)\n return `Завершить за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Завершить до начала`;\n }\n return \"\";\n}\n\nconst DepChip: React.FC<DepChipProps> = ({\n lag,\n dep,\n taskId,\n taskNumber,\n predecessorName,\n predecessorTaskNumber,\n selectedChip,\n disableDependencyEditing,\n onChipSelect,\n onRowClick,\n onScrollToTask,\n onRemoveDependency,\n onChipSelectClear,\n task,\n allTasks,\n onTasksChange,\n businessDays = true,\n weekendPredicate,\n}) => {\n const [popoverOpen, setPopoverOpen] = useState(false);\n const lagAbs = Math.abs(lag ?? 0);\n const [inputAbs, setInputAbs] = useState(lagAbs === 0 ? \"\" : String(lagAbs));\n useEffect(() => {\n const abs = Math.abs(lag ?? 0);\n setInputAbs(abs === 0 ? \"\" : String(abs));\n }, [lag]);\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 // Toggle popover and chip selection together\n const nextOpen = !popoverOpen;\n setPopoverOpen(nextOpen);\n if (nextOpen) {\n onChipSelect?.({\n successorId: taskId,\n predecessorId: dep.taskId,\n linkType: dep.type,\n });\n onScrollToTask?.(taskId);\n } else {\n // Only clear selection when explicitly closing via chip click\n onChipSelect?.(null);\n }\n };\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n setPopoverOpen(open);\n // Don't clear selectedChip on automatic popover close (e.g. focus loss, escape)\n // Only clear when user explicitly closes via chip click or trash button\n },\n [],\n );\n\n const handleTrashClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemoveDependency?.(taskId, dep.taskId, dep.type);\n onChipSelectClear();\n setPopoverOpen(false);\n };\n\n const handleLagChange = useCallback(\n (newLag: number) => {\n if (!onTasksChange || !allTasks) return;\n const taskById = new Map(allTasks.map((t) => [t.id, t]));\n const predecessor = taskById.get(dep.taskId);\n if (!predecessor) return;\n\n const predStart = parseUTCDate(predecessor.startDate);\n // Milestone predecessors have zero duration — treat end = start\n const predEnd = predecessor.type === 'milestone' ? predStart : parseUTCDate(predecessor.endDate);\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const normalizedLag = normalizeDependencyLag(\n dep.type,\n newLag,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate,\n );\n\n const constraintDate = calculateSuccessorDate(\n predStart,\n predEnd,\n dep.type,\n normalizedLag,\n businessDays,\n weekendPredicate,\n );\n\n let newStart: Date, newEnd: Date;\n if (dep.type === \"FS\" || dep.type === \"SS\") {\n newStart = constraintDate;\n if (businessDays) {\n const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);\n newEnd = addBusinessDays(constraintDate, businessDuration, weekendPredicate);\n } else {\n newEnd = new Date(constraintDate.getTime() + durationMs);\n }\n } else {\n newEnd = constraintDate;\n if (businessDays) {\n const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);\n newStart = subtractBusinessDays(constraintDate, businessDuration, weekendPredicate);\n } else {\n newStart = new Date(constraintDate.getTime() - durationMs);\n }\n }\n\n onTasksChange([\n {\n ...task,\n startDate: newStart.toISOString().split(\"T\")[0],\n endDate: newEnd.toISOString().split(\"T\")[0],\n dependencies: (task.dependencies ?? []).map((existingDep) =>\n existingDep.taskId === dep.taskId && existingDep.type === dep.type\n ? { ...existingDep, lag: normalizedLag }\n : existingDep\n ),\n },\n ]);\n },\n [dep, task, allTasks, onTasksChange, businessDays, weekendPredicate],\n );\n\n const handleInputCommit = useCallback(\n (raw: string) => {\n if (raw === \"\") {\n handleLagChange(0);\n return;\n }\n const parsed = parseInt(raw, 10);\n const effectiveLag = lag ?? 0;\n if (isNaN(parsed)) {\n const abs = Math.abs(effectiveLag);\n setInputAbs(abs === 0 ? \"\" : String(abs));\n return;\n }\n let newLag: number;\n if (parsed === 0) {\n newLag = 0;\n } else if (dep.type === \"SF\") {\n newLag = -Math.abs(parsed);\n } else {\n // sign comes from what the user typed: \"-4\" → negative, \"4\" → positive\n newLag = parsed; // parseInt preserves the sign from input\n }\n if (newLag !== effectiveLag) handleLagChange(newLag);\n },\n [lag, dep.type, handleLagChange],\n );\n\n const Icon = LINK_TYPE_ICONS[dep.type];\n const depName = predecessorName ?? dep.taskId;\n const effectiveLag = lag ?? 0;\n\n // Derive action verb, preWord and afterWhat (sign-dependent for FS/FF/SS)\n const actionVerb =\n dep.type === \"FS\" || dep.type === \"SS\" ? \"начать\" : \"завершить\";\n const zeroPlaceholder =\n dep.type === \"SF\"\n ? \"чётко\"\n : dep.type === \"FF\"\n ? \"вместе\"\n : dep.type === \"SS\"\n ? \"вместе\"\n : \"сразу\";\n let afterWhat: string;\n let preWord: string | null = null;\n if (dep.type === \"SF\") {\n afterWhat =\n effectiveLag < 0\n ? \"до начала\"\n : effectiveLag === 0\n ? \"с началом\"\n : \"после начала\";\n if (effectiveLag > 0) preWord = \"через\";\n else if (effectiveLag < 0) preWord = \"за\";\n } else if (dep.type === \"SS\") {\n afterWhat =\n effectiveLag < 0\n ? \"до начала\"\n : effectiveLag === 0\n ? \"с началом\"\n : \"после начала\";\n if (effectiveLag > 0) preWord = \"через\";\n else if (effectiveLag < 0) preWord = \"за\";\n } else {\n // FS, FF\n if (effectiveLag > 0) {\n preWord = \"через\";\n afterWhat = \"после окончания\";\n } else if (effectiveLag < 0) {\n preWord = \"за\";\n afterWhat = \"до окончания\";\n } else {\n afterWhat = \"после окончания\";\n }\n }\n\n return (\n <Popover open={popoverOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <span\n className={`gantt-tl-dep-chip${isSelected ? \" gantt-tl-dep-chip-selected\" : \"\"}`}\n onClick={handleClick}\n title={`[${LINK_TYPE_LABELS_RU[dep.type]}] ${formatTaskNumberLabel(predecessorTaskNumber)}${depName}`}\n >\n <Icon />\n {effectiveLag !== 0\n ? effectiveLag > 0\n ? `+${effectiveLag}`\n : `${effectiveLag}`\n : \"\"}\n </span>\n </PopoverTrigger>\n <PopoverContent\n className=\"gantt-tl-dep-edit-popover\"\n portal={true}\n align=\"start\"\n >\n <div onClick={(e) => e.stopPropagation()}>\n <div className=\"gantt-tl-dep-edit-task\">\n {formatTaskNumberLabel(taskNumber)}\n {task.name}\n </div>\n <div className=\"gantt-tl-dep-edit-row\">\n <span className=\"gantt-tl-dep-edit-label\">\n {actionVerb}\n {preWord ? ` ${preWord}` : \"\"}\n </span>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-btn\"\n onClick={() => handleLagChange(effectiveLag - 1)}\n >\n −\n </button>\n <input\n type=\"number\"\n className=\"gantt-tl-dep-edit-input\"\n value={inputAbs}\n placeholder={zeroPlaceholder}\n min=\"0\"\n onChange={(e) => setInputAbs(e.target.value)}\n onFocus={(e) => e.target.select()}\n onBlur={(e) => handleInputCommit(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleInputCommit(inputAbs);\n }}\n />\n {!(dep.type === \"SF\" && effectiveLag === 0) && (\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-btn\"\n onClick={() => handleLagChange(effectiveLag + 1)}\n >\n +\n </button>\n )}\n {effectiveLag !== 0 && <span>д.</span>}\n <span>{afterWhat}</span>\n </div>\n <div className=\"gantt-tl-dep-edit-pred\">\n {formatTaskNumberLabel(predecessorTaskNumber)}\n {depName}\n </div>\n {!disableDependencyEditing && (\n <>\n <hr className=\"gantt-tl-dep-edit-divider\" />\n <div className=\"gantt-tl-dep-edit-actions\">\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-close\"\n onClick={() => {\n setPopoverOpen(false);\n onChipSelectClear();\n }}\n >\n Закрыть\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-delete\"\n onClick={handleTrashClick}\n >\n Удалить связь\n </button>\n </div>\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\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 /** Hierarchical task number (e.g., \"1.2.3\") */\n taskNumber?: string;\n /** Visible task-list numbers by task id */\n taskNumberMap?: Record<string, string>;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via inline edit. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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 /** Callback to change active link type for new dependencies */\n onSetActiveLinkType?: (linkType: LinkType) => void;\n /** Current dependency picking direction */\n dependencyPickMode?: \"predecessor\" | \"successor\";\n /** Callback to change dependency picking direction */\n onSetDependencyPickMode?: (mode: \"predecessor\" | \"successor\") => void;\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?: (\n successorTaskId: string,\n predecessorTaskId: string,\n linkType: LinkType,\n ) => void;\n /** Callback to remove a dependency link */\n onRemoveDependency?: (\n taskId: string,\n predecessorTaskId: string,\n linkType: LinkType,\n ) => void;\n /** Currently selected chip (for predecessor-side delete) */\n selectedChip?: {\n successorId: string;\n predecessorId: string;\n linkType: string;\n } | null;\n /** Callback when a chip is clicked (selects it) */\n onChipSelect?: (\n chip: {\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null,\n ) => 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 /** Callback when task or task group should be duplicated */\n onDuplicateTask?: (taskId: string) => void;\n /** Whether demote action should be shown for this row */\n canDemoteTask?: boolean;\n /** Whether this child is the last sibling (affects connector icon shape) */\n isLastChild?: boolean;\n /** Nesting depth (0 = root, 1 = child, 2 = grandchild, etc.) */\n nestingDepth?: number;\n /** Whether this row currently has visible children in the rendered task list */\n hasVisibleChildren?: boolean;\n /** For each ancestor above the direct parent: whether its vertical line is full or ends at mid-row */\n ancestorLineModes?: (\"full\" | \"half\")[];\n /** Custom day configurations for date picker */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate for date picker */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях */\n businessDays?: boolean;\n /** Whether this row matches the active filter highlight */\n isFilterMatch?: boolean;\n /** Whether filter is in hide mode (simplifies hierarchy rendering to avoid confusion) */\n isFilterHideMode?: boolean;\n /** Resolved columns (built-in + custom) for unified rendering */\n resolvedColumns?: NewTaskListColumn<Task>[];\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\"))\n 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 taskNumber,\n taskNumberMap = {},\n rowHeight,\n onTasksChange,\n selectedTaskId,\n onRowClick,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n allTasks = [],\n activeLinkType,\n onSetActiveLinkType,\n dependencyPickMode = \"successor\",\n onSetDependencyPickMode,\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 onDuplicateTask,\n canDemoteTask = true,\n isLastChild = true,\n nestingDepth = 0,\n hasVisibleChildren = false,\n ancestorLineModes = [],\n customDays,\n isWeekend,\n businessDays,\n isFilterMatch = false,\n isFilterHideMode = false,\n resolvedColumns,\n }) => {\n const [editingColumnId, setEditingColumnId] = useState<string | null>(null);\n const editingName = editingColumnId === 'name';\n const editingDuration = editingColumnId === 'duration';\n const editingProgress = editingColumnId === 'progress';\n const normalizedTask = useMemo(() => normalizeTaskDatesForType(task), [task]);\n const isMilestone = useMemo(() => isMilestoneTask(normalizedTask), [normalizedTask]);\n const [nameValue, setNameValue] = useState(\"\");\n const nameInputRef = useRef<HTMLInputElement>(null);\n const [durationValue, setDurationValue] = useState(() =>\n getInclusiveDurationDays(normalizedTask.startDate, normalizedTask.endDate),\n );\n const durationInputRef = useRef<HTMLInputElement>(null);\n const dependencySearchInputRef = useRef<HTMLInputElement>(null);\n const dependencySearchListRef = useRef<HTMLDivElement>(null);\n const [progressValue, setProgressValue] = useState(0);\n const progressInputRef = useRef<HTMLInputElement>(null);\n const [overflowOpen, setOverflowOpen] = useState(false);\n const [contextMenuOpen, setContextMenuOpen] = useState(false);\n const [colorMenuOpen, setColorMenuOpen] = useState(false);\n const nameConfirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const durationConfirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const progressConfirmedRef = 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\">(\n \"doubleclick\",\n ); // How editing was started\n\n const isSelected = selectedTaskId === task.id;\n\n // Hierarchy computed values\n const isParent = useMemo(\n () => isTaskParent(task.id, allTasks),\n [task.id, allTasks],\n );\n const isChild = task.parentId !== undefined;\n\n // Create custom weekend predicate from props (memoized for performance)\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\n\n // Memoized duration calculation function (business days vs calendar days)\n const getDuration = useCallback(\n (start: string | Date, end: string | Date) => {\n return businessDays\n ? getBusinessDaysCount(start, end, weekendPredicate)\n : getInclusiveDurationDays(start, end);\n },\n [businessDays, weekendPredicate]\n );\n\n // Memoized end date calculation function (business days vs calendar days)\n const getEndDate = useCallback(\n (start: string | Date, duration: number) => {\n return businessDays\n ? addBusinessDays(start, duration, weekendPredicate).toISOString().split('T')[0]\n : getEndDateFromDuration(start, duration);\n },\n [businessDays, weekendPredicate]\n );\n\n const isCollapsed = collapsedParentIds.has(task.id);\n\n const getHierarchyLineColor = useCallback((columnDepth: number) => {\n return columnDepth % 2 === 0\n ? \"#93c5fd\"\n : \"var(--gantt-hierarchy-line-color)\";\n }, []);\n\n // Picker mode flags for this row\n const isPicking = selectingPredecessorFor != null;\n const isSourceRow = isPicking && selectingPredecessorFor === task.id;\n const [dependencySearchQuery, setDependencySearchQuery] = useState(\"\");\n const [highlightedDependencyIndex, setHighlightedDependencyIndex] = useState(0);\n\n // Chip data: always reflect the persisted business lag, not the visual calendar gap.\n const chips = useMemo(() => {\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 = getDependencyLag(dep);\n return { dep, lag, predecessorName: pred?.name ?? dep.taskId };\n });\n }, [task.dependencies, allTasks]);\n\n const linkWord = chips.length <= 4 ? \"связи\" : \"связей\";\n\n const dependencySearchCandidates = useMemo(() => {\n if (!isSourceRow) return [];\n\n const normalizedQuery = dependencySearchQuery.trim().toLowerCase();\n return allTasks\n .filter((candidate) => candidate.id !== task.id)\n .map((candidate) => {\n const number = taskNumberMap[candidate.id];\n const label = `${formatTaskNumberLabel(number)}${candidate.name}`;\n const matchingDependencies = dependencyPickMode === \"predecessor\"\n ? (task.dependencies ?? []).filter((dep) => dep.taskId === candidate.id)\n : (candidate.dependencies ?? []).filter((dep) => dep.taskId === task.id);\n return {\n task: candidate,\n label,\n linkedTypes: matchingDependencies.map((dep) => dep.type),\n isAlreadyLinked: matchingDependencies.length > 0,\n searchable: `${number ?? \"\"} ${candidate.name}`.toLowerCase(),\n };\n })\n .filter((candidate) =>\n normalizedQuery === \"\" ? true : candidate.searchable.includes(normalizedQuery)\n );\n }, [\n isSourceRow,\n dependencySearchQuery,\n allTasks,\n task.id,\n activeLinkType,\n dependencyPickMode,\n taskNumberMap,\n task.dependencies,\n ]);\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 useEffect(() => {\n if (!isSourceRow && dependencySearchQuery !== \"\") {\n setDependencySearchQuery(\"\");\n }\n }, [isSourceRow, dependencySearchQuery]);\n\n useEffect(() => {\n setHighlightedDependencyIndex(0);\n }, [dependencySearchQuery, isSourceRow, dependencyPickMode]);\n\n useEffect(() => {\n if (dependencySearchCandidates.length === 0) {\n setHighlightedDependencyIndex(0);\n return;\n }\n\n if (highlightedDependencyIndex > dependencySearchCandidates.length - 1) {\n setHighlightedDependencyIndex(dependencySearchCandidates.length - 1);\n }\n }, [dependencySearchCandidates, highlightedDependencyIndex]);\n\n useEffect(() => {\n if (isSourceRow && dependencySearchInputRef.current) {\n dependencySearchInputRef.current.focus();\n dependencySearchInputRef.current.select();\n }\n }, [isSourceRow, dependencyPickMode, activeLinkType]);\n\n useEffect(() => {\n if (!isSourceRow || dependencySearchCandidates.length === 0) {\n return;\n }\n\n const listElement = dependencySearchListRef.current;\n const activeElement = listElement?.querySelector<HTMLElement>(\n `.gantt-tl-dep-source-option[data-index=\"${highlightedDependencyIndex}\"]`\n );\n\n activeElement?.scrollIntoView({\n block: \"nearest\",\n });\n }, [isSourceRow, highlightedDependencyIndex, dependencySearchCandidates]);\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 → onTasksChange → 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 nameConfirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = \"autoedit\";\n setNameValue(task.name);\n setEditingColumnId('name');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editingTaskId, task.id, disableTaskNameEditing]);\n\n const handleNameClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n onScrollToTask?.(task.id);\n },\n [task.id, onRowClick, onScrollToTask],\n );\n\n const handleNameDoubleClick = useCallback(\n (e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n nameConfirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = \"doubleclick\";\n setNameValue(task.name);\n setEditingColumnId('name');\n },\n [task.name, disableTaskNameEditing],\n );\n\n const handleRowKeyDown = useCallback(\n (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 nameConfirmedRef.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 setEditingColumnId('name');\n return;\n }\n },\n [editingName, disableTaskNameEditing, task.name],\n );\n\n const handleNameSave = useCallback(() => {\n if (nameConfirmedRef.current) {\n // Already saved via Enter key, skip blur handler\n nameConfirmedRef.current = false;\n return;\n }\n if (nameValue.trim()) {\n onTasksChange?.([{ ...task, name: nameValue.trim() }]);\n }\n setEditingColumnId(null);\n }, [nameValue, task, onTasksChange]);\n\n const handleNameCancel = useCallback(() => {\n setEditingColumnId(null);\n }, []);\n\n const handleNameKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n nameConfirmedRef.current = true; // Mark as saved to prevent blur from triggering again\n if (nameValue.trim()) {\n onTasksChange?.([{ ...task, name: nameValue.trim() }]);\n }\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleNameCancel();\n }\n },\n [nameValue, task, onTasksChange, handleNameCancel],\n );\n\n const handleDurationClick = useCallback(\n (e: React.MouseEvent) => {\n if (task.locked) return;\n e.stopPropagation();\n durationConfirmedRef.current = false;\n setDurationValue(\n isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate),\n );\n setEditingColumnId('duration');\n },\n [task.locked, normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone],\n );\n\n const applyDurationChange = useCallback((nextDuration: number) => {\n const normalizedDuration = Math.max(0, Math.round(nextDuration) || 0);\n setDurationValue(normalizedDuration);\n }, []);\n\n const handleDurationSave = useCallback(() => {\n if (durationConfirmedRef.current) {\n durationConfirmedRef.current = false;\n return;\n }\n const rounded = Math.round(durationValue) || 0;\n if (isMilestone && rounded > 0) {\n // Convert milestone → task\n onTasksChange?.([\n { ...task, type: 'task' as const, endDate: getEndDate(task.startDate, rounded) },\n ]);\n } else if (!isMilestone && rounded === 0) {\n // Convert task → milestone\n onTasksChange?.([\n { ...task, type: 'milestone' as const, endDate: task.startDate },\n ]);\n } else if (!isMilestone && rounded > 0) {\n onTasksChange?.([\n { ...task, endDate: getEndDate(task.startDate, rounded) },\n ]);\n }\n // isMilestone && rounded === 0 → no-op, just close\n setEditingColumnId(null);\n }, [durationValue, task, onTasksChange, getEndDate, isMilestone]);\n\n const handleDurationCancel = useCallback(() => {\n setDurationValue(isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate));\n setEditingColumnId(null);\n }, [normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]);\n\n const handleDurationAdjust = useCallback(\n (delta: number) => {\n applyDurationChange(durationValue + delta);\n },\n [applyDurationChange, durationValue],\n );\n\n const handleDurationKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (e.key === \"Enter\") {\n durationConfirmedRef.current = true;\n const rounded = Math.round(durationValue) || 0;\n if (isMilestone && rounded > 0) {\n // Convert milestone → task\n onTasksChange?.([\n { ...task, type: 'task' as const, endDate: getEndDate(task.startDate, rounded) },\n ]);\n } else if (!isMilestone && rounded === 0) {\n // Convert task → milestone\n onTasksChange?.([\n { ...task, type: 'milestone' as const, endDate: task.startDate },\n ]);\n } else if (!isMilestone && rounded > 0) {\n onTasksChange?.([\n { ...task, endDate: getEndDate(task.startDate, rounded) },\n ]);\n }\n // isMilestone && rounded === 0 → no-op, just close\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleDurationCancel();\n }\n },\n [durationValue, task, onTasksChange, handleDurationCancel, getEndDate, isMilestone],\n );\n\n const handleProgressClick = useCallback(\n (e: React.MouseEvent) => {\n if (task.locked) return;\n e.stopPropagation();\n progressConfirmedRef.current = false;\n setProgressValue(task.progress ?? 0);\n setEditingColumnId('progress');\n },\n [task.progress, task.locked],\n );\n\n const handleProgressSave = useCallback(() => {\n if (progressConfirmedRef.current) {\n progressConfirmedRef.current = false;\n return;\n }\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n\n // Cascade 100% or 0% progress to all children when parent is marked complete/reset\n if (\n (clampedValue === 100 || clampedValue === 0) &&\n isTaskParent(task.id, allTasks)\n ) {\n const children = getChildren(task.id, allTasks);\n const updatedTasks = [\n { ...task, progress: clampedValue },\n ...children.map((child) => ({ ...child, progress: clampedValue })),\n ];\n onTasksChange?.(updatedTasks);\n } else {\n onTasksChange?.([{ ...task, progress: clampedValue }]);\n }\n setEditingColumnId(null);\n }, [progressValue, task, onTasksChange, allTasks]);\n\n const handleProgressCancel = useCallback(() => {\n setEditingColumnId(null);\n }, []);\n\n const handleProgressAdjust = useCallback((delta: number) => {\n setProgressValue((current) =>\n Math.max(0, Math.min(100, current + delta)),\n );\n }, []);\n\n const handleProgressKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation(); // Prevent row-level keyboard handler from interfering\n if (e.key === \"Enter\") {\n progressConfirmedRef.current = true;\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n\n // Cascade 100% or 0% progress to all children when parent is marked complete/reset\n if (\n (clampedValue === 100 || clampedValue === 0) &&\n isTaskParent(task.id, allTasks)\n ) {\n const children = getChildren(task.id, allTasks);\n const updatedTasks = [\n { ...task, progress: clampedValue },\n ...children.map((child) => ({\n ...child,\n progress: clampedValue,\n })),\n ];\n onTasksChange?.(updatedTasks);\n } else {\n onTasksChange?.([{ ...task, progress: clampedValue }]);\n }\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleProgressCancel();\n }\n },\n [progressValue, task, onTasksChange, handleProgressCancel, allTasks],\n );\n\n useEffect(() => {\n if (editingProgress && progressInputRef.current) {\n progressInputRef.current.focus();\n progressInputRef.current.select();\n }\n }, [editingProgress]);\n\n useEffect(() => {\n setDurationValue(getDuration(normalizedTask.startDate, normalizedTask.endDate));\n }, [normalizedTask.startDate, normalizedTask.endDate, getDuration]);\n\n useEffect(() => {\n if (editingDuration && durationInputRef.current) {\n durationInputRef.current.focus();\n durationInputRef.current.select();\n }\n }, [editingDuration]);\n\n const emitMilestoneDateChange = useCallback((nextDateISO: string) => {\n const alignedDate = businessDays\n ? alignToWorkingDay(new Date(`${nextDateISO}T00:00:00.000Z`), 1, weekendPredicate)\n : new Date(`${nextDateISO}T00:00:00.000Z`);\n\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n alignedDate,\n alignedDate,\n allTasks,\n businessDays,\n weekendPredicate\n );\n const normalized = normalizeTaskDatesForType({\n ...task,\n startDate: clampedRange.start.toISOString().split(\"T\")[0],\n endDate: clampedRange.end.toISOString().split(\"T\")[0],\n });\n const startDate = parseUTCDate(normalized.startDate);\n const endDate = parseUTCDate(normalized.endDate);\n\n onTasksChange?.([\n {\n ...normalized,\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n }, [task, onTasksChange, allTasks, businessDays, weekendPredicate]);\n\n // Both date pickers shift the whole task (preserving duration), same as drag-move\n // Also normalizes dates to ensure startDate is always before or equal to endDate\n const handleStartDateChange = useCallback(\n (newDateISO: string) => {\n if (!newDateISO) return;\n if (isMilestone) {\n emitMilestoneDateChange(newDateISO);\n return;\n }\n let nextEndISO: string;\n const normalizedInputStart = businessDays\n ? alignToWorkingDay(new Date(`${newDateISO}T00:00:00.000Z`), 1, weekendPredicate)\n : new Date(`${newDateISO}T00:00:00.000Z`);\n\n if (businessDays) {\n const duration = getDuration(task.startDate, task.endDate);\n nextEndISO = buildTaskRangeFromStart(\n normalizedInputStart,\n duration,\n true,\n weekendPredicate,\n 1\n ).end.toISOString().split(\"T\")[0];\n } else {\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n nextEndISO = new Date(normalizedInputStart.getTime() + durationMs).toISOString().split(\"T\")[0];\n }\n\n const { startDate: normalizedStart, endDate: normalizedEnd } =\n normalizeTaskDates(normalizedInputStart, nextEndISO);\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n new Date(`${normalizedStart}T00:00:00.000Z`),\n new Date(`${normalizedEnd}T00:00:00.000Z`),\n allTasks,\n businessDays,\n weekendPredicate\n );\n const startDate = clampedRange.start;\n const endDate = clampedRange.end;\n onTasksChange?.([\n {\n ...task,\n startDate: startDate.toISOString().split(\"T\")[0],\n endDate: endDate.toISOString().split(\"T\")[0],\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n },\n [task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange],\n );\n\n const handleEndDateChange = useCallback(\n (newDateISO: string) => {\n if (!newDateISO) return;\n if (isMilestone) {\n emitMilestoneDateChange(newDateISO);\n return;\n }\n let nextStartISO: string;\n const normalizedInputEnd = businessDays\n ? alignToWorkingDay(new Date(`${newDateISO}T00:00:00.000Z`), -1, weekendPredicate)\n : new Date(`${newDateISO}T00:00:00.000Z`);\n\n if (businessDays) {\n const duration = getDuration(task.startDate, task.endDate);\n nextStartISO = buildTaskRangeFromEnd(\n normalizedInputEnd,\n duration,\n true,\n weekendPredicate,\n -1\n ).start.toISOString().split(\"T\")[0];\n } else {\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n nextStartISO = new Date(normalizedInputEnd.getTime() - durationMs).toISOString().split(\"T\")[0];\n }\n\n const { startDate: normalizedStart, endDate: normalizedEnd } =\n normalizeTaskDates(nextStartISO, normalizedInputEnd);\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n new Date(`${normalizedStart}T00:00:00.000Z`),\n new Date(`${normalizedEnd}T00:00:00.000Z`),\n allTasks,\n businessDays,\n weekendPredicate\n );\n const startDate = clampedRange.start;\n const endDate = clampedRange.end;\n onTasksChange?.([\n {\n ...task,\n startDate: startDate.toISOString().split(\"T\")[0],\n endDate: endDate.toISOString().split(\"T\")[0],\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n },\n [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange],\n );\n\n const handleRowClickInternal = useCallback(() => {\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleNumberClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n },\n [task.id, onRowClick],\n );\n\n const handleToggleCollapse = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleCollapse?.(task.id);\n },\n [task.id, onToggleCollapse],\n );\n\n // Hierarchy handlers - promote/demote\n const handlePromote = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onPromoteTask?.(task.id);\n },\n [task.id, onPromoteTask],\n );\n\n const handleDemote = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n // The parent calculation is done in TaskList.tsx's handleDemoteWrapper,\n // which has access to the ordered visible task list and implements the\n // \"previous visible task becomes parent\" principle.\n // Pass empty string as placeholder — the wrapper ignores this value.\n onDemoteTask?.(task.id, \"\");\n },\n [task.id, onDemoteTask],\n );\n\n const handleApplyColor = useCallback(\n (color?: string) => {\n if (!onTasksChange) return;\n\n const descendantIds = new Set<string>();\n if (isParent) {\n const stack = getChildren(task.id, allTasks);\n while (stack.length > 0) {\n const current = stack.shift();\n if (!current || descendantIds.has(current.id)) continue;\n descendantIds.add(current.id);\n stack.push(...getChildren(current.id, allTasks));\n }\n }\n\n const updatedTasks: Task[] = [\n { ...task, color },\n ...allTasks\n .filter(candidate => descendantIds.has(candidate.id))\n .map(candidate => ({ ...candidate, color })),\n ];\n\n onTasksChange(updatedTasks);\n setColorMenuOpen(false);\n setContextMenuOpen(false);\n },\n [allTasks, isParent, onTasksChange, task],\n );\n\n // Dependency handlers\n const handleAddClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(task.id);\n },\n [task.id, onSetSelectingPredecessorFor],\n );\n\n const handlePredecessorPick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!isPicking || isSourceRow) return;\n if (!selectingPredecessorFor || !activeLinkType) return;\n if (dependencyPickMode === \"predecessor\") {\n onAddDependency?.(selectingPredecessorFor, task.id, activeLinkType);\n } else {\n onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);\n }\n },\n [\n isPicking,\n isSourceRow,\n selectingPredecessorFor,\n task.id,\n activeLinkType,\n dependencyPickMode,\n onAddDependency,\n ],\n );\n\n const handleCancelPicking = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(null);\n },\n [onSetSelectingPredecessorFor],\n );\n\n const handleSourceCellClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n handleCancelPicking(e);\n }\n },\n [handleCancelPicking],\n );\n\n const handleSearchPick = useCallback(\n (pickedTaskId: string) => {\n if (!activeLinkType) return;\n if (dependencyPickMode === \"predecessor\") {\n onAddDependency?.(task.id, pickedTaskId, activeLinkType);\n } else {\n onAddDependency?.(pickedTaskId, task.id, activeLinkType);\n }\n },\n [activeLinkType, dependencyPickMode, onAddDependency, task.id],\n );\n\n const handleSearchRemove = useCallback(\n (pickedTaskId: string) => {\n const matchingTypes = dependencyPickMode === \"predecessor\"\n ? (task.dependencies ?? [])\n .filter((dep) => dep.taskId === pickedTaskId)\n .map((dep) => dep.type)\n : ((allTasks.find((candidate) => candidate.id === pickedTaskId)?.dependencies ?? []))\n .filter((dep) => dep.taskId === task.id)\n .map((dep) => dep.type);\n\n for (const linkType of matchingTypes) {\n if (dependencyPickMode === \"predecessor\") {\n onRemoveDependency?.(task.id, pickedTaskId, linkType);\n } else {\n onRemoveDependency?.(pickedTaskId, task.id, linkType);\n }\n }\n },\n [allTasks, dependencyPickMode, onRemoveDependency, task.dependencies, task.id],\n );\n\n const sourcePickerContent = (\n <div\n className=\"gantt-tl-dep-source-picker\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"gantt-tl-dep-source-direction\">\n <button\n type=\"button\"\n className={`gantt-tl-dep-source-direction-btn${dependencyPickMode === \"successor\" ? \" gantt-tl-dep-source-direction-btn-active\" : \"\"}`}\n onClick={() => onSetDependencyPickMode?.(\"successor\")}\n >\n Последователь\n </button>\n <button\n type=\"button\"\n className={`gantt-tl-dep-source-direction-btn${dependencyPickMode === \"predecessor\" ? \" gantt-tl-dep-source-direction-btn-active\" : \"\"}`}\n onClick={() => onSetDependencyPickMode?.(\"predecessor\")}\n >\n Предшественник\n </button>\n </div>\n <div className=\"gantt-tl-dep-source-types\">\n {LINK_TYPE_ORDER.map((linkType) => {\n const Icon = LINK_TYPE_ICONS[linkType];\n return (\n <button\n key={linkType}\n type=\"button\"\n className={`gantt-tl-dep-source-type-btn${activeLinkType === linkType ? \" gantt-tl-dep-source-type-btn-active\" : \"\"}`}\n onClick={() => onSetActiveLinkType?.(linkType)}\n aria-label={`Выбрать тип связи ${linkType}`}\n title={linkType}\n >\n <Icon />\n <span>{LINK_TYPE_LABELS_RU[linkType]}</span>\n </button>\n );\n })}\n </div>\n <div className=\"gantt-tl-dep-source-picker-head\">\n <input\n ref={dependencySearchInputRef}\n type=\"text\"\n className=\"gantt-tl-dep-source-input\"\n placeholder={dependencyPickMode === \"predecessor\" ? \"Укажите предшественника\" : \"Укажите последователя\"}\n value={dependencySearchQuery}\n onChange={(e) => setDependencySearchQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n onSetSelectingPredecessorFor?.(null);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (dependencySearchCandidates.length > 0) {\n setHighlightedDependencyIndex((current) =>\n Math.min(current + 1, dependencySearchCandidates.length - 1)\n );\n }\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n if (dependencySearchCandidates.length > 0) {\n setHighlightedDependencyIndex((current) => Math.max(current - 1, 0));\n }\n return;\n }\n if (e.key === \"Enter\" && dependencySearchCandidates[highlightedDependencyIndex]) {\n e.preventDefault();\n const activeCandidate = dependencySearchCandidates[highlightedDependencyIndex];\n if (activeCandidate.isAlreadyLinked) {\n handleSearchRemove(activeCandidate.task.id);\n } else {\n handleSearchPick(activeCandidate.task.id);\n }\n }\n }}\n />\n </div>\n <div\n ref={dependencySearchListRef}\n className=\"gantt-tl-dep-source-list\"\n >\n {dependencySearchCandidates.length > 0 ? (\n dependencySearchCandidates.map(({ task: candidate, label, isAlreadyLinked }, index) => (\n <button\n key={candidate.id}\n type=\"button\"\n data-index={index}\n className={`gantt-tl-dep-source-option${index === highlightedDependencyIndex ? \" gantt-tl-dep-source-option-active\" : \"\"}${isAlreadyLinked ? \" gantt-tl-dep-source-option-linked\" : \"\"}`}\n onClick={() => {\n if (!isAlreadyLinked) {\n handleSearchPick(candidate.id);\n }\n }}\n onMouseEnter={() => setHighlightedDependencyIndex(index)}\n onKeyDown={(e) => {\n // Allow Delete/Backspace to remove linked items via keyboard\n if (isAlreadyLinked && (e.key === \"Delete\" || e.key === \"Backspace\")) {\n e.preventDefault();\n handleSearchRemove(candidate.id);\n }\n }}\n title={label}\n >\n <span className=\"gantt-tl-dep-source-option-label\">{label}</span>\n {isAlreadyLinked && (\n <span\n className=\"gantt-tl-dep-source-option-remove\"\n onClick={(e) => {\n e.stopPropagation();\n handleSearchRemove(candidate.id);\n }}\n aria-label={`Удалить связь с ${label}`}\n >\n ×\n </span>\n )}\n </button>\n ))\n ) : (\n <span className=\"gantt-tl-dep-source-hint\">Ничего не найдено</span>\n )}\n </div>\n </div>\n );\n\n // True when this row is the predecessor for the currently selected chip\n const isSelectedPredecessor =\n selectedChip != null && selectedChip.predecessorId === task.id;\n const isSelectedDependencyOwner =\n selectedChip != null && selectedChip.successorId === task.id;\n\n // Delete the selected dependency from the predecessor row's \"Удалить\" button\n const handleDeleteSelected = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!selectedChip) return;\n onRemoveDependency?.(\n selectedChip.successorId,\n selectedChip.predecessorId,\n selectedChip.linkType as LinkType,\n );\n onChipSelect?.(null);\n },\n [selectedChip?.successorId, selectedChip?.predecessorId, selectedChip?.linkType, onRemoveDependency, onChipSelect],\n );\n\n const startDateISO = toISODate(normalizedTask.startDate);\n const endDateISO = editingDuration\n ? getEndDate(normalizedTask.startDate, durationValue)\n : toISODate(normalizedTask.endDate);\n\n // --- Built-in cell JSX (referenced from resolvedColumns.map) ---\n const numberCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-number\"\n onClick={handleNumberClick}\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\">\n {taskNumber || rowIndex + 1}\n </span>\n </div>\n );\n\n const nameTriggerPaddingLeft =\n isParent\n ? `${nestingDepth * 20 + 28}px`\n : nestingDepth > 0\n ? `${nestingDepth * 20 + 8}px`\n : undefined;\n\n const nameInputPaddingLeft =\n nestingDepth > 0 ? `${nestingDepth * 20 + 8}px` : undefined;\n\n const nameCell = (\n <div className=\"gantt-tl-cell gantt-tl-cell-name\">\n {isChild && !editingName && (\n <>\n {!isFilterHideMode && (\n <>\n {/* Ancestor continuation lines — full-height vertical bars for each ongoing ancestor level */}\n {ancestorLineModes.map((mode, idx) =>\n mode ? (\n <React.Fragment key={idx}>\n <span\n data-testid={`gantt-tl-ancestor-connector-${idx}`}\n style={{\n position: \"absolute\",\n left: `${idx * 20 + 9}px`,\n top: 0,\n height: mode === \"half\" ? `${rowHeight / 2}px` : `${rowHeight}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(idx),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n {mode === \"half\" && (\n <span\n data-testid={`gantt-tl-ancestor-connector-cap-${idx}`}\n style={{\n position: \"absolute\",\n left: `${idx * 20 + 9}px`,\n top: `${rowHeight / 2 - 0.75}px`,\n width: \"5px\",\n height: \"1.5px\",\n background: getHierarchyLineColor(idx),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n </React.Fragment>\n ) : null\n )}\n {/* Vertical line from parent to last child position */}\n {nestingDepth > 0 && (\n <span\n data-testid=\"gantt-tl-child-connector-vertical\"\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 9}px`,\n top: 0,\n height:\n isLastChild && !hasVisibleChildren\n ? `${rowHeight / 2}px`\n : `${rowHeight}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth - 1),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n {/* Horizontal branch */}\n <span\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 9}px`,\n top: `${rowHeight / 2 - 0.75}px`,\n width: \"8px\",\n height: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth - 1),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n {/* End dot */}\n <span\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 15}px`,\n top: `${rowHeight / 2 - 2}px`,\n width: \"4px\",\n height: \"4px\",\n borderRadius: \"50%\",\n background: getHierarchyLineColor(nestingDepth - 1),\n pointerEvents: \"none\",\n }}\n />\n </>\n )}\n {isParent && !editingName && (\n <>\n {!isFilterHideMode && !isCollapsed && (\n <span\n style={{\n position: \"absolute\",\n left: `${nestingDepth * 20 + 9}px`,\n top: `${rowHeight / 2 + 7}px`,\n height: `${rowHeight / 2 - 7}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-collapse-btn ${isCollapsed ? \"gantt-tl-collapse-btn-collapsed\" : \"\"}`}\n onClick={handleToggleCollapse}\n style={{ left: `${nestingDepth * 20 + 1}px` }}\n aria-label={isCollapsed ? \"Expand children\" : \"Collapse children\"}\n >\n <ChevronRightIcon />\n </button>\n </>\n )}\n </>\n )}\n {!isChild && isParent && !editingName && (\n <>\n {!isFilterHideMode && !isCollapsed && (\n <span\n data-testid=\"gantt-tl-parent-connector-tail\"\n style={{\n position: \"absolute\",\n left: `${nestingDepth * 20 + 9}px`,\n top: `${rowHeight / 2 + 7}px`,\n height: `${rowHeight / 2 - 7}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-collapse-btn ${isCollapsed ? \"gantt-tl-collapse-btn-collapsed\" : \"\"}`}\n onClick={handleToggleCollapse}\n style={{ left: `${nestingDepth * 20 + 1}px` }}\n aria-label={isCollapsed ? \"Expand children\" : \"Collapse children\"}\n >\n <ChevronRightIcon />\n </button>\n </>\n )}\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 style={{ paddingLeft: nameInputPaddingLeft }}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <button\n type=\"button\"\n className={[\n \"gantt-tl-name-trigger\",\n disableTaskNameEditing ? \"gantt-tl-name-locked\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n title={task.name}\n onClick={handleNameClick}\n onDoubleClick={handleNameDoubleClick}\n style={{\n paddingLeft: nameTriggerPaddingLeft,\n paddingRight: task.color ? \"20px\" : undefined,\n }}\n >\n <span className=\"gantt-tl-name-trigger-text\">{task.name}</span>\n </button>\n )}\n {!editingName && task.color && (\n <span\n className=\"gantt-tl-name-color-stripe\"\n style={{ backgroundColor: task.color }}\n aria-hidden=\"true\"\n />\n )}\n {!editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onDuplicateTask || onTasksChange) && (\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(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate(),\n ),\n )\n .toISOString()\n .split(\"T\")[0];\n const endISO = new Date(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate() + 7,\n ),\n )\n .toISOString()\n .split(\"T\")[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name: \"Новая задача\",\n startDate: todayISO,\n endDate: endISO,\n parentId: task.parentId,\n };\n onInsertAfter(task.id, newTask);\n }}\n aria-label=\"Вставить задачу после этой\"\n >\n <PlusIcon />\n </button>\n )}\n <HierarchyButton\n isChild={isChild}\n rowIndex={rowIndex}\n canDemote={canDemoteTask}\n onPromote={onPromoteTask ? handlePromote : undefined}\n onDemote={onDemoteTask ? handleDemote : undefined}\n />\n {(onDuplicateTask || onDelete || onTasksChange) && (\n <Popover open={contextMenuOpen} onOpenChange={(open) => {\n setContextMenuOpen(open);\n if (!open) setColorMenuOpen(false);\n }}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-context\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen((v) => !v);\n }}\n aria-label=\"Дополнительно\"\n >\n <VerticalDotsIcon />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"gantt-tl-context-menu\" portal={true} align=\"end\">\n {onTasksChange && (\n <div className=\"gantt-tl-context-menu-section\">\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item gantt-tl-context-menu-item-toggle\"\n onClick={(e) => {\n e.stopPropagation();\n setColorMenuOpen((value) => !value);\n }}\n aria-expanded={colorMenuOpen}\n >\n <span className=\"gantt-tl-context-menu-item-main\">\n {task.color && (\n <span\n className=\"gantt-tl-color-swatch gantt-tl-color-swatch-inline\"\n style={{ backgroundColor: task.color }}\n aria-hidden=\"true\"\n />\n )}\n Цвет\n </span>\n <ChevronRightIcon />\n </button>\n {colorMenuOpen && (\n <div className=\"gantt-tl-color-grid\">\n <button\n type=\"button\"\n className={`gantt-tl-color-swatch gantt-tl-color-swatch-clear${!task.color ? \" is-selected\" : \"\"}`}\n onClick={(e) => {\n e.stopPropagation();\n handleApplyColor(undefined);\n }}\n aria-label=\"Сбросить цвет\"\n title=\"Сбросить цвет\"\n >\n <span className=\"gantt-tl-color-swatch-clear-line\" />\n </button>\n {TASK_COLOR_PALETTE.map((paletteColor) => (\n <button\n key={paletteColor.value}\n type=\"button\"\n className={`gantt-tl-color-swatch${task.color === paletteColor.value ? \" is-selected\" : \"\"}`}\n style={{ backgroundColor: paletteColor.value }}\n onClick={(e) => {\n e.stopPropagation();\n handleApplyColor(paletteColor.value);\n }}\n aria-label={`Выбрать цвет ${paletteColor.label}`}\n title={paletteColor.label}\n />\n ))}\n </div>\n )}\n </div>\n )}\n {onDuplicateTask && (\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen(false);\n onDuplicateTask(task.id);\n }}\n >\n <CopyIcon />\n Дублировать\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item gantt-tl-context-menu-item-danger\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen(false);\n onDelete(task.id);\n }}\n >\n <TrashIcon />\n Удалить задачу\n </button>\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n )}\n </div>\n );\n\n const startDateCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-date\"\n onClick={(e) => e.stopPropagation()}\n >\n <DatePicker\n value={startDateISO}\n onChange={handleStartDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n isWeekend={weekendPredicate}\n businessDays={businessDays}\n />\n </div>\n );\n\n const endDateCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-date\"\n onClick={(e) => e.stopPropagation()}\n >\n <DatePicker\n value={endDateISO}\n onChange={handleEndDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n isWeekend={weekendPredicate}\n businessDays={businessDays}\n />\n </div>\n );\n\n const durationCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-duration\"\n onClick={handleDurationClick}\n >\n {editingDuration && (\n <div\n className=\"gantt-tl-number-editor\"\n onClick={(e) => e.stopPropagation()}\n >\n <Input\n ref={durationInputRef}\n type=\"number\"\n min={0}\n step={1}\n value={durationValue}\n onChange={(e) =>\n applyDurationChange(parseInt(e.target.value, 10) || 0)\n }\n onBlur={handleDurationSave}\n onKeyDown={handleDurationKeyDown}\n className=\"gantt-tl-number-input\"\n />\n <div className=\"gantt-tl-number-steppers\" aria-hidden=\"true\">\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleDurationAdjust(1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleDurationAdjust(-1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n </div>\n </div>\n )}\n <span\n style={\n editingDuration\n ? { visibility: \"hidden\", pointerEvents: \"none\" }\n : undefined\n }\n >\n {isMilestone ? '◆' : `${getDuration(normalizedTask.startDate, normalizedTask.endDate)}д`}\n </span>\n </div>\n );\n\n const progressCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-progress\"\n onClick={handleProgressClick}\n >\n {editingProgress && (\n <div\n className=\"gantt-tl-number-editor\"\n onClick={(e) => e.stopPropagation()}\n >\n <Input\n ref={progressInputRef}\n type=\"number\"\n min={0}\n max={100}\n step={1}\n value={progressValue}\n onChange={(e) =>\n setProgressValue(parseInt(e.target.value, 10) || 0)\n }\n onBlur={handleProgressSave}\n onKeyDown={handleProgressKeyDown}\n className=\"gantt-tl-number-input\"\n />\n <div className=\"gantt-tl-number-steppers\" aria-hidden=\"true\">\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleProgressAdjust(1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleProgressAdjust(-1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n </div>\n </div>\n )}\n <span\n style={\n editingProgress\n ? { visibility: \"hidden\", pointerEvents: \"none\" }\n : task.progress === 100\n ? {\n backgroundColor: \"#17c864\",\n borderRadius: \"4px\",\n padding: \"2px 4px\",\n color: \"#ffffff\",\n }\n : undefined\n }\n >\n {task.progress\n ? Math.round(task.progress) === 100\n ? \"100\"\n : `${Math.round(task.progress)}%`\n : \"-\"}\n </span>\n </div>\n );\n\n const dependenciesCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-deps\"\n onClick={\n isSourceRow\n ? handleSourceCellClick\n : isPicking\n ? handlePredecessorPick\n : undefined\n }\n >\n {isSourceRow ? (\n <>\n <span\n className=\"gantt-tl-dep-source-hint\"\n onClick={handleCancelPicking}\n >\n Отменить\n </span>\n {sourcePickerContent}\n </>\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\">\n Связано с\n </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) => {\n e.stopPropagation();\n setOverflowOpen((v) => !v);\n }}\n >\n {chips.length} {linkWord}\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div\n className=\"gantt-tl-dep-overflow-list\"\n onClick={(e) => e.stopPropagation()}\n >\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 taskNumber={taskNumber}\n predecessorName={predecessorName}\n predecessorTaskNumber={taskNumberMap[dep.taskId]}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n task={task}\n allTasks={allTasks}\n onTasksChange={onTasksChange}\n businessDays={businessDays}\n weekendPredicate={weekendPredicate}\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 taskNumber={taskNumber}\n predecessorName={chips[0].predecessorName}\n predecessorTaskNumber={taskNumberMap[chips[0].dep.taskId]}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n task={task}\n allTasks={allTasks}\n onTasksChange={onTasksChange}\n businessDays={businessDays}\n weekendPredicate={weekendPredicate}\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 );\n\n const builtInCells: Record<string, React.ReactNode> = {\n number: numberCell,\n name: nameCell,\n startDate: startDateCell,\n endDate: endDateCell,\n duration: durationCell,\n progress: progressCell,\n dependencies: dependenciesCell,\n };\n\n return (\n <div\n data-filter-match={isFilterMatch ? 'true' : 'false'}\n className={[\n \"gantt-tl-row\",\n isFilterMatch ? \"gantt-tl-row-filter-match\" : \"\",\n isSelected ? \"gantt-tl-row-selected\" : \"\",\n isSelectedDependencyOwner ? \"gantt-tl-row-dependency-owner\" : \"\",\n isSelectedPredecessor ? \"gantt-tl-row-dependency-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 ]\n .filter(Boolean)\n .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 tabIndex={isSelected ? 0 : -1}\n >\n {resolvedColumns?.map(col => {\n const builtIn = builtInCells[col.id];\n if (builtIn) return <React.Fragment key={col.id}>{builtIn}</React.Fragment>;\n\n // Custom column\n const isEditing = editingColumnId === col.id;\n const editorFn = col.renderEditor;\n const columnContext = {\n task,\n rowIndex,\n isEditing,\n openEditor: () => {\n if (editorFn) setEditingColumnId(col.id);\n },\n closeEditor: () => {\n if (editingColumnId === col.id) setEditingColumnId(null);\n },\n updateTask: (patch: Partial<Task>) => {\n onTasksChange?.([{ ...task, ...patch } as Task]);\n setEditingColumnId(null);\n },\n };\n\n return (\n <div\n key={col.id}\n className=\"gantt-tl-cell gantt-tl-cell-custom\"\n data-column-id={`custom:${col.id}`}\n data-custom-column-id={col.id}\n data-custom-column-editing={isEditing ? \"true\" : \"false\"}\n data-testid={`custom-cell-${col.id}`}\n onClick={editorFn && !isEditing ? (e) => { e.stopPropagation(); setEditingColumnId(col.id); } : undefined}\n style={{ width: col.width ?? 120, minWidth: col.width ?? 120, flexShrink: 0 }}\n >\n {isEditing && editorFn ? (\n <div\n data-custom-column-editor={col.id}\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => e.stopPropagation()}\n >\n {editorFn(columnContext)}\n </div>\n ) : (\n col.renderCell(columnContext)\n )}\n </div>\n );\n })}\n </div>\n );\n },\n);\n\nTaskListRow.displayName = \"TaskListRow\";\nexport default TaskListRow;\n\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, useEffect, useRef } from 'react';\nimport { format, isValid, parse, addDays, addMonths, addYears, subMonths, subYears, subDays } 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 /** Optional predicate for custom weekend logic */\n isWeekend?: (date: Date) => boolean;\n /** Whether to use business days for +1/+7 buttons (default: true) */\n businessDays?: boolean;\n}\n\nconst segments = [\n { start: 0, end: 2, label: 'day', max: 31 },\n { start: 3, end: 5, label: 'month', max: 12 },\n { start: 6, end: 8, label: 'year', max: 99 },\n];\n\nconst shiftByBusinessDays = (\n startDate: Date,\n delta: number,\n weekendPredicate: (date: Date) => boolean\n): Date => {\n if (delta === 0) return startDate;\n\n const shifted = new Date(startDate);\n const step = delta > 0 ? 1 : -1;\n let remaining = Math.abs(delta);\n\n while (remaining > 0) {\n shifted.setUTCDate(shifted.getUTCDate() + step);\n if (!weekendPredicate(shifted)) {\n remaining--;\n }\n }\n\n return shifted;\n};\n\nconst snapToBusinessDay = (\n date: Date,\n direction: 1 | -1,\n weekendPredicate: (date: Date) => boolean\n): Date => {\n const snapped = new Date(date);\n while (weekendPredicate(snapped)) {\n snapped.setUTCDate(snapped.getUTCDate() + direction);\n }\n return snapped;\n};\n\nconst formatUTCDate = (date: Date, pattern: string): string => {\n const localDisplayDate = new Date(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n );\n return format(localDisplayDate, pattern);\n};\n\n/**\n * DatePicker component — shows formatted date as a button, opens calendar popup on click.\n * The popup includes a keyboard-navigable date input field above the calendar.\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 isWeekend,\n businessDays = true,\n}) => {\n const [open, setOpen] = useState(false);\n const [inputValue, setInputValue] = useState('');\n const [draftDate, setDraftDate] = useState<Date | undefined>(undefined);\n const dateInputRef = useRef<HTMLInputElement>(null);\n // Refs для синхронного отслеживания позиции — не зависят от DOM/rAF\n const segIdxRef = useRef(0); // текущий сегмент (0=day, 1=month, 2=year)\n const charPosRef = useRef(0); // позиция внутри сегмента (0 или 1)\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 const activeDate = draftDate ?? selectedDate;\n\n // Format Date for display on trigger button\n const displayValue = selectedDate\n ? formatUTCDate(selectedDate, displayFormat)\n : placeholder;\n\n // Sync inputValue with prop value\n useEffect(() => {\n if (value) {\n const d = new Date(value + 'T00:00:00Z');\n if (isValid(d)) {\n setInputValue(formatUTCDate(d, 'dd.MM.yy'));\n setDraftDate(undefined);\n }\n } else {\n setInputValue('');\n setDraftDate(undefined);\n }\n }, [value]);\n\n // Выделить сегмент по индексу (визуально)\n const selectSegByIdx = useCallback((idx: number) => {\n if (!dateInputRef.current) return;\n const seg = segments[idx] ?? segments[0];\n dateInputRef.current.setSelectionRange(seg.start, seg.end);\n }, []);\n\n // Auto-focus input when popup opens\n useEffect(() => {\n if (open) {\n setTimeout(() => {\n if (dateInputRef.current) {\n segIdxRef.current = 0;\n charPosRef.current = 0;\n dateInputRef.current.focus();\n selectSegByIdx(0);\n }\n }, 50);\n }\n }, [open, selectSegByIdx]);\n\n const handleFocus = () => {\n setTimeout(() => {\n segIdxRef.current = 0;\n charPosRef.current = 0;\n selectSegByIdx(0);\n }, 0);\n };\n\n const handleMouseDown = () => {\n setTimeout(() => {\n const pos = dateInputRef.current?.selectionStart ?? 0;\n const idx = segments.findIndex(s => pos >= s.start && pos <= s.end);\n segIdxRef.current = idx >= 0 ? idx : 0;\n charPosRef.current = 0;\n selectSegByIdx(segIdxRef.current);\n }, 0);\n };\n\n const handleShiftButtonMouseDown = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n },\n []\n );\n\n const updateFromDate = useCallback((newDate: Date) => {\n if (!isValid(newDate)) return;\n setInputValue(formatUTCDate(newDate, 'dd.MM.yy'));\n setDraftDate(newDate);\n }, []);\n\n const commitDate = useCallback((dateToCommit?: Date) => {\n const nextDate = dateToCommit ?? draftDate ?? selectedDate;\n if (!nextDate || !isValid(nextDate)) return;\n const iso = [\n nextDate.getUTCFullYear(),\n String(nextDate.getUTCMonth() + 1).padStart(2, '0'),\n String(nextDate.getUTCDate()).padStart(2, '0'),\n ].join('-');\n if (iso === value) return;\n onChange?.(iso);\n }, [draftDate, onChange, selectedDate, value]);\n\n const handleCalendarSelect = useCallback(\n (day: Date) => {\n const normalizedDay = businessDays && isWeekend && isWeekend(day)\n ? snapToBusinessDay(day, 1, isWeekend)\n : day;\n updateFromDate(normalizedDay);\n commitDate(normalizedDay);\n setOpen(false);\n },\n [businessDays, commitDate, isWeekend, updateFromDate]\n );\n\n const handleDayShift = useCallback(\n (delta: number) => {\n const base = activeDate ?? new Date();\n // Use business days if enabled and weekend predicate is available\n if (businessDays && isWeekend) {\n updateFromDate(shiftByBusinessDays(base, delta, isWeekend));\n } else {\n updateFromDate(addDays(base, delta));\n }\n },\n [activeDate, updateFromDate, businessDays, isWeekend]\n );\n\n const handleTriggerKeyDown = useCallback((e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n handleDayShift(1);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n handleDayShift(-1);\n }\n }, [disabled, handleDayShift]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!dateInputRef.current) return;\n const { value: inputVal } = dateInputRef.current;\n\n // Читаем сегмент из рефа — всегда актуально, даже при быстром вводе\n const segIdx = segIdxRef.current;\n const seg = segments[segIdx] ?? segments[0];\n\n if (e.key === 'Tab') return;\n\n if (e.key === 'Escape') {\n e.preventDefault(); e.stopPropagation();\n setOpen(false);\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault(); e.stopPropagation();\n commitDate();\n setOpen(false);\n return;\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault(); e.stopPropagation();\n const base = activeDate ?? new Date();\n let newDate = base;\n if (seg.label === 'day') newDate = e.key === 'ArrowUp' ? addDays(base, 1) : subDays(base, 1);\n if (seg.label === 'month') newDate = e.key === 'ArrowUp' ? addMonths(base, 1) : subMonths(base, 1);\n if (seg.label === 'year') newDate = e.key === 'ArrowUp' ? addYears(base, 1) : subYears(base, 1);\n if (businessDays && isWeekend && isWeekend(newDate)) {\n newDate = snapToBusinessDay(newDate, e.key === 'ArrowUp' ? 1 : -1, isWeekend);\n }\n charPosRef.current = 0;\n updateFromDate(newDate);\n requestAnimationFrame(() => selectSegByIdx(segIdx));\n return;\n }\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault(); e.stopPropagation();\n const chars = inputVal.split('');\n for (let i = seg.start; i < seg.end; i++) chars[i] = '0';\n charPosRef.current = 0;\n setInputValue(chars.join(''));\n requestAnimationFrame(() => selectSegByIdx(segIdx));\n return;\n }\n\n if (e.key === 'ArrowRight') {\n e.preventDefault(); e.stopPropagation();\n const next = segIdx + 1 < segments.length ? segIdx + 1 : 0;\n segIdxRef.current = next;\n charPosRef.current = 0;\n selectSegByIdx(next);\n return;\n }\n\n if (e.key === 'ArrowLeft') {\n e.preventDefault(); e.stopPropagation();\n const prev = segIdx - 1 >= 0 ? segIdx - 1 : segments.length - 1;\n segIdxRef.current = prev;\n charPosRef.current = 0;\n selectSegByIdx(prev);\n return;\n }\n\n if (/^\\d$/.test(e.key)) {\n e.preventDefault(); e.stopPropagation();\n const charPos = charPosRef.current;\n const charIndex = seg.start + charPos;\n const chars = inputVal.split('');\n\n // На первой позиции сегмента — сбрасываем вторую цифру\n if (charPos === 0) {\n for (let i = seg.start + 1; i < seg.end; i++) chars[i] = '0';\n }\n chars[charIndex] = e.key;\n\n const segStr = chars.slice(seg.start, seg.end).join('');\n const segVal = parseInt(segStr, 10);\n\n if (seg.label === 'month' && charPos === 0 && parseInt(e.key) > 1) return;\n if (seg.label === 'day' && charPos === 0 && parseInt(e.key) > 3) return;\n if (segVal > seg.max) return;\n\n const updated = chars.join('');\n setInputValue(updated);\n\n const segLen = seg.end - seg.start;\n if (charPos + 1 < segLen) {\n // Ещё не заполнили сегмент — двигаемся внутри\n charPosRef.current = charPos + 1;\n requestAnimationFrame(() => {\n dateInputRef.current?.setSelectionRange(charIndex + 1, seg.end);\n });\n } else {\n // Сегмент заполнен — переходим к следующему\n const nextIdx = segIdx + 1 < segments.length ? segIdx + 1 : segIdx;\n segIdxRef.current = nextIdx;\n charPosRef.current = 0;\n requestAnimationFrame(() => selectSegByIdx(nextIdx));\n }\n\n const parsed = parse(updated, 'dd.MM.yy', new Date());\n if (isValid(parsed) && !updated.includes('00.00')) {\n const normalizedDate = new Date(Date.UTC(parsed.getFullYear(), parsed.getMonth(), parsed.getDate()));\n updateFromDate(\n businessDays && isWeekend && isWeekend(normalizedDate)\n ? snapToBusinessDay(normalizedDate, 1, isWeekend)\n : normalizedDate\n );\n }\n }\n }, [activeDate, businessDays, commitDate, isWeekend, selectSegByIdx, updateFromDate]);\n\n const handleOpenChange = useCallback((nextOpen: boolean) => {\n if (!nextOpen && open) {\n commitDate();\n }\n setOpen(nextOpen);\n }, [commitDate, open]);\n\n return (\n <Popover open={open} onOpenChange={disabled ? undefined : handleOpenChange}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className={`gantt-datepicker-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled}\n onKeyDown={handleTriggerKeyDown}\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 <div className=\"gantt-datepicker-input-row\">\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(-7)} tabIndex={-1}>-7</button>\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(-1)} tabIndex={-1}>-1</button>\n <input\n ref={dateInputRef}\n type=\"text\"\n className=\"gantt-datepicker-date-input\"\n value={inputValue}\n onChange={() => {}}\n onFocus={handleFocus}\n onMouseDown={handleMouseDown}\n onKeyDown={handleKeyDown}\n onBlur={() => {\n commitDate();\n }}\n spellCheck={false}\n autoComplete=\"off\"\n />\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(1)} tabIndex={-1}>+1</button>\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(7)} tabIndex={-1}>+7</button>\n </div>\n <Calendar\n mode=\"single\"\n selected={activeDate}\n onSelect={handleCalendarSelect}\n initialDate={activeDate}\n isWeekend={isWeekend}\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 isSameDay,\n getDay,\n isToday,\n isWeekend,\n isBefore,\n startOfDay,\n} from 'date-fns';\nimport { ru } from 'date-fns/locale';\nimport { createCustomDayPredicate } from '../../utils/dateUtils';\n\nexport interface CalendarProps {\n selected?: Date;\n onSelect?: (date: Date) => void;\n initialDate?: Date;\n mode?: 'single' | 'range';\n disabled?: boolean;\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isWeekend?: (date: Date) => boolean;\n}\n\n\nfunction getDayClassName(\n day: Date,\n selected: Date | undefined,\n isWeekendProp?: (date: Date) => boolean\n): 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 // Use custom predicate if provided, otherwise default\n if (isWeekendProp ? isWeekendProp(day) : 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 isWeekend: isWeekendProp,\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 // Day of week headers (Monday-first)\n const weekdayLabels = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];\n const weekdayHeaders = weekdayLabels.map((label, i) => (\n <div key={`wd-${i}`} className=\"gantt-cal-weekday\">\n {label}\n </div>\n ));\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(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));\n const className = getDayClassName(day, selected, isWeekendProp);\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(Date.UTC(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 {weekdayHeaders}\n {emptyCells}\n {dayCells}\n </div>\n </div>\n );\n },\n [selected, onSelect, disabled, isWeekendProp]\n );\n\n const renderedMonths = useMemo(\n () => months.map(renderMonth),\n [months, renderMonth]\n );\n\n return (\n <div ref={scrollRef} className=\"gantt-cal-container\">\n {renderedMonths}\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 nestingDepth?: number;\n}\n\nexport const NewTaskRow: React.FC<NewTaskRowProps> = ({\n rowHeight,\n onConfirm,\n onCancel,\n nestingDepth = 0,\n}) => {\n const [nameValue, setNameValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n const confirmedRef = useRef(false);\n const inputInnerPadding = 4;\n const levelOffset = nestingDepth > 0 ? nestingDepth * 20 + 8 : 0;\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 style={{\n left: `${Math.max(0, levelOffset - inputInnerPadding)}px`,\n width: levelOffset > 0 ? `calc(100% - ${Math.max(0, levelOffset - inputInnerPadding)}px)` : '100%',\n paddingLeft: `${inputInnerPadding}px`,\n }}\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","import type { Task } from '../../GanttChart';\nimport type { TaskListColumn } from './types';\n\nexport const BUILT_IN_COLUMN_WIDTHS: Record<string, number> = {\n number: 40,\n name: 200,\n startDate: 90,\n endDate: 90,\n duration: 60,\n progress: 50,\n dependencies: 120,\n actions: 80,\n};\n\nexport function createBuiltInColumns<TTask extends Task>(opts?: {\n businessDays?: boolean;\n}): TaskListColumn<TTask>[] {\n return [\n { id: 'number', header: '\\u2116', width: BUILT_IN_COLUMN_WIDTHS.number, renderCell: () => null },\n { id: 'name', header: '\\u0418\\u043C\\u044F', width: BUILT_IN_COLUMN_WIDTHS.name, renderCell: () => null },\n { id: 'startDate', header: '\\u041D\\u0430\\u0447\\u0430\\u043B\\u043E', width: BUILT_IN_COLUMN_WIDTHS.startDate, renderCell: () => null },\n { id: 'endDate', header: '\\u041E\\u043A\\u043E\\u043D\\u0447\\u0430\\u043D\\u0438\\u0435', width: BUILT_IN_COLUMN_WIDTHS.endDate, renderCell: () => null },\n { id: 'duration', header: opts?.businessDays ? '\\u0414\\u043D. (\\u0440)' : '\\u0414\\u043D.', width: BUILT_IN_COLUMN_WIDTHS.duration, renderCell: () => null },\n { id: 'progress', header: '%', width: BUILT_IN_COLUMN_WIDTHS.progress, renderCell: () => null },\n { id: 'dependencies', header: null, width: BUILT_IN_COLUMN_WIDTHS.dependencies, renderCell: () => null },\n ];\n}\n","import type { Task } from '../../GanttChart';\nimport type { TaskListColumn } from './types';\n\nexport function resolveTaskListColumns<TTask extends Task>(\n builtIn: TaskListColumn<TTask>[],\n custom: TaskListColumn<TTask>[],\n): TaskListColumn<TTask>[] {\n // Dev-mode duplicate check\n if (process.env.NODE_ENV !== 'production') {\n const ids = new Set<string>();\n for (const col of [...builtIn, ...custom]) {\n if (ids.has(col.id)) {\n console.error(`[TaskList] Duplicate column id: \"${col.id}\"`);\n }\n ids.add(col.id);\n }\n }\n\n if (custom.length === 0) {\n return [...builtIn];\n }\n\n const result = [...builtIn];\n // Track last insertion index per anchor to preserve order for same-anchor columns\n const lastInsertAfter: Map<string, number> = new Map();\n const lastInsertBefore: Map<string, number> = new Map();\n\n for (const col of custom) {\n let insertAt: number;\n\n if ('before' in col && (col as { before: string }).before) {\n const anchor = (col as { before: string }).before;\n // If we've already inserted before this anchor, insert at the same position\n // so the new column goes right before the same target\n if (lastInsertBefore.has(anchor)) {\n insertAt = lastInsertBefore.get(anchor)!;\n } else {\n const idx = result.findIndex(c => c.id === anchor);\n insertAt = idx !== -1 ? idx : result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertBefore.set(anchor, insertAt);\n } else if ('after' in col && (col as { after: string }).after) {\n const anchor = (col as { after: string }).after;\n // If we've already inserted after this anchor, insert after the last insertion\n if (lastInsertAfter.has(anchor)) {\n insertAt = lastInsertAfter.get(anchor)! + 1;\n } else {\n const idx = result.findIndex(c => c.id === anchor);\n insertAt = idx !== -1 ? idx + 1 : result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertAfter.set(anchor, insertAt);\n } else {\n // No anchor — insert after 'name', tracking for multiple no-anchor columns\n const anchor = '__no_anchor__';\n if (lastInsertAfter.has(anchor)) {\n insertAt = lastInsertAfter.get(anchor)! + 1;\n } else {\n insertAt = result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertAfter.set(anchor, insertAt);\n }\n\n result.splice(insertAt, 0, col);\n }\n\n return result;\n}\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","// Utility functions barrel export\nexport * from './dateUtils';\nexport * from './dependencyUtils';\nexport * from './expired';\nexport * from './geometry';\nexport * from './hierarchyOrder';\nexport * from './taskListReorder';\n","import { Task } from '../types';\nimport { parseUTCDate } from '../utils/dateUtils';\nimport { isTaskExpired } from '../utils/expired';\n\n/**\n * Predicate function for filtering tasks\n * @param task - Task to evaluate\n * @returns true to include task in filtered results, false to exclude\n */\nexport type TaskPredicate = (task: Task | undefined) => boolean;\n\n/**\n * Combine predicates with AND logic — all must be true\n * @param predicates - Array of predicate functions\n * @returns Composite predicate that returns true only if all predicates return true\n */\nexport const and = (...predicates: TaskPredicate[]): TaskPredicate =>\n (task) => predicates.every(p => p(task));\n\n/**\n * Combine predicates with OR logic — at least one must be true\n * @param predicates - Array of predicate functions\n * @returns Composite predicate that returns true if any predicate returns true\n */\nexport const or = (...predicates: TaskPredicate[]): TaskPredicate =>\n (task) => predicates.some(p => p(task));\n\n/**\n * Invert a predicate's logic\n * @param predicate - Predicate function to invert\n * @returns Composite predicate that returns the opposite of the input predicate\n */\nexport const not = (predicate: TaskPredicate): TaskPredicate =>\n (task) => !predicate(task);\n\n/**\n * Filter tasks that have no dependencies\n * @returns Predicate that returns true for tasks without dependencies array or with empty array\n */\nexport const withoutDeps = (): TaskPredicate =>\n (task) => !!task && (!task.dependencies || task.dependencies.length === 0);\n\n/**\n * Filter expired (overdue) tasks\n * @param referenceDate - Date to compare against (default: now)\n * @returns Predicate that returns true for tasks ending before reference date\n */\nexport const expired = (referenceDate: Date = new Date()): TaskPredicate =>\n (task) => isTaskExpired(task, referenceDate);\n\n/**\n * Filter tasks that intersect with a date range\n * Task intersects if: taskStart <= rangeEnd && taskEnd >= rangeStart\n * @param rangeStart - Start of the date range\n * @param rangeEnd - End of the date range\n * @returns Predicate that returns true for tasks intersecting the range\n */\nexport const inDateRange = (rangeStart: Date, rangeEnd: Date): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n return taskStart.getTime() <= rangeEnd.getTime() && taskEnd.getTime() >= rangeStart.getTime();\n };\n\n/**\n * Filter tasks by progress value range\n * @param min - Minimum progress value (0-100)\n * @param max - Maximum progress value (0-100)\n * @returns Predicate that returns true for tasks with progress in [min, max] range\n */\nexport const progressInRange = (min: number, max: number): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const progress = task.progress ?? 0;\n return progress >= min && progress <= max;\n };\n\n/**\n * Filter tasks by name substring search\n * @param substring - Text to search for in task name\n * @param caseSensitive - If false (default), search is case-insensitive\n * @returns Predicate that returns true for tasks with substring in name\n */\nexport const nameContains = (substring: string, caseSensitive = false): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const name = task.name;\n const search = caseSensitive ? substring : substring.toLowerCase();\n const target = caseSensitive ? name : name.toLowerCase();\n return target.includes(search);\n };\n"],"mappings":"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","names":["addBusinessDays","getBusinessDaysCount","subtractBusinessDays","startOfMonth","addBusinessDays","getBusinessDaysCount","subtractBusinessDays","import_react","DAY_MS","DAY_MS","import_react","bar","isWeekend","getWeekBlocks","import_react","snapDirection","originalStart","duration","dayWidth","getUTCDayDifference","currentTask","import_jsx_runtime","React","isWeekend","import_react","import_jsx_runtime","import_react","import_jsx_runtime","arePropsEqual","React","import_jsx_runtime","import_react","import_jsx_runtime","React","lines","taskMap","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","isWeekend","import_jsx_runtime","import_jsx_runtime","DAY_MS","effectiveLag","React","isWeekend","import_react","import_jsx_runtime","import_jsx_runtime","LINK_TYPE_ORDER","getAllDescendants","isWeekend","tasks","React","import_jsx_runtime","isWeekend","tasks","import_react","import_jsx_runtime","React"]}
1
+ {"version":3,"sources":["../src/core/scheduling/dateMath.ts","../src/utils/dateUtils.ts","../src/index.ts","../src/components/GanttChart/GanttChart.tsx","../src/core/scheduling/index.ts","../src/core/scheduling/dependencies.ts","../src/core/scheduling/cascade.ts","../src/core/scheduling/hierarchy.ts","../src/core/scheduling/commands.ts","../src/core/scheduling/execute.ts","../src/core/scheduling/validation.ts","../src/utils/hierarchyOrder.ts","../src/components/TimeScaleHeader/TimeScaleHeader.tsx","../src/components/TaskRow/TaskRow.tsx","../src/utils/geometry.ts","../src/utils/expired.ts","../src/utils/taskType.ts","../src/hooks/useTaskDrag.ts","../src/adapters/scheduling/drag.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/utils/taskListReorder.ts","../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/TaskList/columns/createBuiltInColumns.tsx","../src/components/TaskList/columns/resolveTaskListColumns.ts","../src/components/ui/Button.tsx","../src/utils/index.ts","../src/filters/index.ts"],"sourcesContent":["/**\n * Pure date math utilities for the core scheduling module.\n * Zero React/DOM/date-fns dependencies.\n *\n * Functions moved from:\n * - dependencyUtils.ts: normalizeUTCDate, parseDateOnly, getBusinessDayOffset, shiftBusinessDayOffset, DAY_MS\n * - dateUtils.ts: getBusinessDaysCount, addBusinessDays, subtractBusinessDays\n */\n\nexport const DAY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Normalize a Date to UTC midnight (hours/minutes/seconds zeroed).\n */\nexport function normalizeUTCDate(date: Date): Date {\n return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));\n}\n\n/**\n * Parse a date string or Date object to a UTC midnight Date.\n * Handles ISO strings like \"2025-01-15\" by appending T00:00:00.000Z.\n */\nexport function parseDateOnly(date: string | Date): Date {\n const parsed = typeof date === 'string'\n ? new Date(`${date.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(date);\n return normalizeUTCDate(parsed);\n}\n\n/**\n * Compute the business-day offset between two dates.\n * Steps through each calendar day, counting only non-weekend days.\n * Returns a positive number if toDate > fromDate, negative if toDate < fromDate.\n */\nexport function getBusinessDayOffset(\n fromDate: Date,\n toDate: Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n const from = normalizeUTCDate(fromDate);\n const to = normalizeUTCDate(toDate);\n\n if (from.getTime() === to.getTime()) {\n return 0;\n }\n\n const step = to.getTime() > from.getTime() ? 1 : -1;\n const current = new Date(from);\n let offset = 0;\n\n while (current.getTime() !== to.getTime()) {\n current.setUTCDate(current.getUTCDate() + step);\n if (!weekendPredicate(current)) {\n offset += step;\n }\n }\n\n return offset;\n}\n\n/**\n * Shift a date by a business-day offset, skipping weekends.\n */\nexport function shiftBusinessDayOffset(\n date: Date,\n offset: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const current = normalizeUTCDate(date);\n\n if (offset === 0) {\n return current;\n }\n\n const step = offset > 0 ? 1 : -1;\n let remaining = Math.abs(offset);\n\n while (remaining > 0) {\n current.setUTCDate(current.getUTCDate() + step);\n if (!weekendPredicate(current)) {\n remaining--;\n }\n }\n\n return current;\n}\n\n/**\n * Count business days between two dates (inclusive), excluding weekends.\n * Returns minimum 1.\n */\nexport function getBusinessDaysCount(\n startDate: string | Date,\n endDate: string | Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n const start = typeof startDate === 'string'\n ? new Date(`${startDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(startDate);\n const end = typeof endDate === 'string'\n ? new Date(`${endDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(endDate);\n\n let count = 0;\n const current = new Date(start);\n\n while (current.getTime() <= end.getTime()) {\n if (!weekendPredicate(current)) {\n count++;\n }\n current.setUTCDate(current.getUTCDate() + 1);\n }\n\n return Math.max(1, count);\n}\n\n/**\n * Calculate end date by adding N business days to start date.\n * Returns a Date object.\n */\nexport function addBusinessDays(\n startDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const start = typeof startDate === 'string'\n ? new Date(`${startDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(startDate);\n const current = new Date(start);\n let targetDays = Math.max(1, businessDays);\n let businessDaysCounted = 0;\n\n while (businessDaysCounted < targetDays) {\n if (!weekendPredicate(current)) {\n businessDaysCounted++;\n }\n if (businessDaysCounted < targetDays) {\n current.setUTCDate(current.getUTCDate() + 1);\n }\n }\n\n return current;\n}\n\n/**\n * Calculate start date by subtracting N business days from end date.\n * Returns a Date object.\n */\nexport function subtractBusinessDays(\n endDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const end = typeof endDate === 'string'\n ? new Date(`${endDate.split('T')[0]}T00:00:00.000Z`)\n : normalizeUTCDate(endDate);\n const current = new Date(end);\n let targetDays = Math.max(1, businessDays);\n let businessDaysCounted = 0;\n\n while (businessDaysCounted < targetDays) {\n if (!weekendPredicate(current)) {\n businessDaysCounted++;\n }\n if (businessDaysCounted < targetDays) {\n current.setUTCDate(current.getUTCDate() - 1);\n }\n }\n\n return current;\n}\n\n/**\n * Snap a date to the nearest working day in the given direction.\n */\nexport function alignToWorkingDay(\n date: Date,\n direction: 1 | -1,\n weekendPredicate: (date: Date) => boolean\n): Date {\n const current = normalizeUTCDate(date);\n\n while (weekendPredicate(current)) {\n current.setUTCDate(current.getUTCDate() + direction);\n }\n\n return current;\n}\n\n/**\n * Get task duration in days (inclusive).\n * If businessDays mode, counts business days using weekendPredicate.\n * Otherwise, counts calendar days.\n */\nexport function getTaskDuration(\n startDate: string | Date,\n endDate: string | Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\n const start = parseDateOnly(startDate);\n const end = parseDateOnly(endDate);\n\n if (businessDays && weekendPredicate) {\n return getBusinessDaysCount(start, end, weekendPredicate);\n }\n\n return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1);\n}\n","import { parseISO, isValid } from 'date-fns';\nimport {\n getBusinessDaysCount as coreGetBusinessDaysCount,\n addBusinessDays as coreAddBusinessDays,\n subtractBusinessDays as coreSubtractBusinessDays,\n} from '../core/scheduling/dateMath';\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 * Create a UTC-safe key for Set-based date lookup\n * @param date - Date object to create key from\n * @returns String key in \"YYYY-M-D\" format using UTC date components\n *\n * Example:\n * createDateKey(new Date(Date.UTC(2026, 2, 15))) // \"2026-2-15\"\n *\n * Note: Uses UTC methods to prevent DST and timezone issues.\n * Month is 0-indexed (0=January, 11=December) per JavaScript Date convention.\n */\nexport const createDateKey = (date: Date): string => {\n return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;\n};\n\n/**\n * Configuration for a single custom day\n */\nexport interface CustomDayConfig {\n /** The date to customize */\n date: Date;\n /** Type of day: 'weekend' marks as weekend, 'workday' marks as workday */\n type: 'weekend' | 'workday';\n}\n\n/**\n * Configuration for custom day predicate\n */\nexport interface CustomDayPredicateConfig {\n /** Array of custom day configurations with explicit types */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate (checked before customDays overrides) */\n isWeekend?: (date: Date) => boolean;\n}\n\n/**\n * Create a weekend predicate with unified custom day support\n *\n * Precedence order (highest to lowest):\n * 1. customDays.type='workday' - explicit workday (highest override)\n * 2. customDays.type='weekend' - explicit weekend (override)\n * 3. isWeekend (base predicate) - custom base logic\n * 4. default - Saturday (6) and Sunday (0)\n *\n * @param config - Custom day configuration with array and optional predicate\n * @returns Predicate function (date: Date) => boolean\n *\n * Example:\n * // Simple holidays + working Saturdays\n * const predicate = createCustomDayPredicate({\n * customDays: [\n * { date: new Date(Date.UTC(2026, 2, 15)), type: 'workday' }, // working Saturday\n * { date: new Date(Date.UTC(2026, 0, 1)), type: 'weekend' } // holiday Tuesday\n * ]\n * });\n *\n * // 4-day work week + occasional overrides\n * const predicate2 = createCustomDayPredicate({\n * isWeekend: (date) => {\n * const day = date.getUTCDay();\n * return day === 0 || day === 6 || day === 5; // Sun+Sat+Fri\n * },\n * customDays: [\n * { date: new Date(Date.UTC(2026, 2, 10)), type: 'workday' } // working Friday\n * ]\n * });\n */\nexport const createCustomDayPredicate = (\n config: CustomDayPredicateConfig\n): ((date: Date) => boolean) => {\n const { customDays, isWeekend: basePredicate } = config;\n\n // Build Set-based lookups for O(1) performance\n const workdaySet = new Set<string>();\n const weekendSet = new Set<string>();\n\n if (customDays && customDays.length > 0) {\n for (const item of customDays) {\n const key = createDateKey(item.date);\n if (item.type === 'workday') {\n workdaySet.add(key);\n } else { // weekend\n weekendSet.add(key);\n }\n }\n }\n\n return (date: Date): boolean => {\n const key = createDateKey(date);\n\n // Priority 1: customDays workdays (highest override)\n if (workdaySet.has(key)) {\n return false; // Explicitly a workday\n }\n\n // Priority 2: customDays weekends (override)\n if (weekendSet.has(key)) {\n return true; // Explicitly a weekend\n }\n\n // Priority 3: base predicate (if provided)\n if (basePredicate) {\n return basePredicate(date);\n }\n\n // Priority 4: default Saturday/Sunday\n const dayOfWeek = date.getUTCDay();\n return dayOfWeek === 0 || dayOfWeek === 6;\n };\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\n/**\n * Russian month abbreviations (genitive case for dates)\n */\nconst MONTH_ABBR = [\n 'янв', 'фев', 'мар', 'апр', 'мая', 'июн',\n 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'\n];\n\n/**\n * Format date range smartly in Russian.\n * Examples:\n * - Same month: \"1-3 мая\"\n * - Different months same year: \"15 апр - 7 июн\"\n * - Different years: \"15 дек 2025 - 7 янв 2026\"\n *\n * @param startDate - Start date\n * @param endDate - End date\n * @returns Formatted date range string\n */\nexport const formatDateRangeLabel = (\n startDate: Date | string,\n endDate: Date | string\n): string => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n\n const startDay = start.getUTCDate();\n const endDay = end.getUTCDate();\n const startMonth = start.getUTCMonth();\n const endMonth = end.getUTCMonth();\n const startYear = start.getUTCFullYear();\n const endYear = end.getUTCFullYear();\n\n // Same month and year: \"1-3 мая\"\n if (startMonth === endMonth && startYear === endYear) {\n if (startDay === endDay) {\n return `${startDay} ${MONTH_ABBR[startMonth]}`;\n }\n return `${startDay}–${endDay} ${MONTH_ABBR[startMonth]}`;\n }\n\n // Same year: \"15 апр–7 июн\"\n if (startYear === endYear) {\n return `${startDay} ${MONTH_ABBR[startMonth]}–${endDay} ${MONTH_ABBR[endMonth]}`;\n }\n\n // Different years: \"15 дек 2025–7 янв 2026\"\n return `${startDay} ${MONTH_ABBR[startMonth]} ${startYear}–${endDay} ${MONTH_ABBR[endMonth]} ${endYear}`;\n};\n\n/**\n * Return block boundaries for week-view, splitting on month boundaries.\n * Each block represents a column in the week-view header.\n * Blocks are typically 7 days, but split on month boundaries so\n * the first/last block of a month may be smaller.\n *\n * @param days - Array of dates from getMultiMonthDays\n * @returns Array of start dates for each block, with actual block sizes\n */\nexport interface WeekBlock {\n /** Start date of this block */\n startDate: Date;\n /** Number of days in this block (≤7, splits on month boundaries) */\n days: number;\n}\n\n/**\n * Split the date range into blocks, primarily 7-day weeks,\n * but splitting blocks on month boundaries for accurate month spans.\n */\nexport const getWeekBlocks = (days: Date[]): WeekBlock[] => {\n if (days.length === 0) return [];\n\n const blocks: WeekBlock[] = [];\n let blockStart = 0;\n\n while (blockStart < days.length) {\n // Target: 7-day block, but check for month boundary within\n const maxBlockEnd = Math.min(blockStart + 7, days.length);\n const startMonthYear = `${days[blockStart].getUTCFullYear()}-${days[blockStart].getUTCMonth()}`;\n\n let actualBlockEnd = blockStart + 7; // Default to full week\n if (actualBlockEnd > days.length) {\n actualBlockEnd = days.length;\n }\n\n // Check if month boundary falls within the 7-day window\n for (let i = blockStart + 1; i < maxBlockEnd; i++) {\n const monthYear = `${days[i].getUTCFullYear()}-${days[i].getUTCMonth()}`;\n if (monthYear !== startMonthYear) {\n // Split at month boundary\n actualBlockEnd = i;\n break;\n }\n }\n\n blocks.push({\n startDate: days[blockStart],\n days: actualBlockEnd - blockStart,\n });\n\n blockStart = actualBlockEnd;\n }\n\n return blocks;\n};\n\n/**\n * Represents a month span in week-view header row 1.\n * In week-view, the width is calculated from actual day counts,\n * not from a fixed column count.\n */\nexport interface WeekSpan {\n /** First day of the calendar month (UTC) */\n month: Date;\n /** Total number of days this month occupies across all blocks */\n days: number;\n /** Start index in the blocks array */\n startIndex: number;\n}\n\n/**\n * Calculate month spans based on week-block boundaries.\n * Groups consecutive blocks that belong to the same month.\n */\nexport const getWeekSpans = (days: Date[]): WeekSpan[] => {\n const blocks = getWeekBlocks(days);\n if (blocks.length === 0) return [];\n\n const spans: WeekSpan[] = [];\n let currentMonthYear = `${blocks[0].startDate.getUTCFullYear()}-${blocks[0].startDate.getUTCMonth()}`;\n let startIndex = 0;\n let totalDays = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n const monthYear = `${block.startDate.getUTCFullYear()}-${block.startDate.getUTCMonth()}`;\n\n if (monthYear !== currentMonthYear) {\n // Finalize previous month span\n spans.push({\n month: new Date(Date.UTC(\n blocks[startIndex].startDate.getUTCFullYear(),\n blocks[startIndex].startDate.getUTCMonth(),\n 1\n )),\n days: totalDays,\n startIndex,\n });\n currentMonthYear = monthYear;\n startIndex = i;\n totalDays = 0;\n }\n\n totalDays += block.days;\n\n if (i === blocks.length - 1) {\n spans.push({\n month: new Date(Date.UTC(\n block.startDate.getUTCFullYear(),\n block.startDate.getUTCMonth(),\n 1\n )),\n days: totalDays,\n startIndex,\n });\n }\n }\n\n return spans;\n};\n\nexport interface MonthBlock {\n /** Первый день месяца (UTC) */\n startDate: Date;\n /** Количество дней в этом месяце внутри dateRange (может быть меньше при обрезке) */\n days: number;\n}\n\n/**\n * Разбивает dateRange на блоки по месяцам.\n * Каждый блок = один месяц (колонка в строке 2 month-view шапки).\n * Блок на краях может быть неполным если dateRange начинается/заканчивается не с 1-го числа.\n */\nexport const getMonthBlocks = (days: Date[]): MonthBlock[] => {\n if (days.length === 0) return [];\n // Переиспользуем getMonthSpans — его структура совпадает с MonthBlock\n return getMonthSpans(days).map(span => ({\n startDate: span.month,\n days: span.days,\n }));\n};\n\nexport interface YearSpan {\n /** 1 января года (UTC) */\n year: Date;\n /** Суммарное кол-во дней этого года внутри dateRange */\n days: number;\n /** Начальный индекс в массиве monthBlocks */\n startIndex: number;\n}\n\n/**\n * Группирует month-блоки по годам.\n * Используется в строке 1 month-view шапки (year label).\n */\nexport const getYearSpans = (days: Date[]): YearSpan[] => {\n const blocks = getMonthBlocks(days);\n if (blocks.length === 0) return [];\n\n const spans: YearSpan[] = [];\n let currentYear = blocks[0].startDate.getUTCFullYear();\n let startIndex = 0;\n let totalDays = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const blockYear = blocks[i].startDate.getUTCFullYear();\n if (blockYear !== currentYear) {\n spans.push({\n year: new Date(Date.UTC(currentYear, 0, 1)),\n days: totalDays,\n startIndex,\n });\n currentYear = blockYear;\n startIndex = i;\n totalDays = 0;\n }\n totalDays += blocks[i].days;\n if (i === blocks.length - 1) {\n spans.push({\n year: new Date(Date.UTC(currentYear, 0, 1)),\n days: totalDays,\n startIndex,\n });\n }\n }\n\n return spans;\n};\n\n/**\n * Normalize task dates to ensure startDate is always before or equal to endDate.\n * If dates are swapped (endDate < startDate), they are automatically swapped.\n * @param startDate - Task start date (string or Date)\n * @param endDate - Task end date (string or Date)\n * @returns Object with normalized startDate and endDate as ISO date strings (YYYY-MM-DD)\n */\nexport const normalizeTaskDates = (\n startDate: string | Date,\n endDate: string | Date\n): { startDate: string; endDate: string } => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n\n // If dates are swapped, return them in correct order\n if (end.getTime() < start.getTime()) {\n return {\n startDate: end.toISOString().split('T')[0],\n endDate: start.toISOString().split('T')[0],\n };\n }\n\n // Dates are already in correct order\n return {\n startDate: start.toISOString().split('T')[0],\n endDate: end.toISOString().split('T')[0],\n };\n};\n\n/**\n * Count business days between two dates (inclusive), excluding weekends\n * Delegates to core/scheduling/dateMath for implementation.\n * @param startDate - Start date (string or Date)\n * @param endDate - End date (string or Date)\n * @param weekendPredicate - Function that returns true for weekends\n * @returns Number of business days (minimum 1)\n */\nexport function getBusinessDaysCount(\n startDate: string | Date,\n endDate: string | Date,\n weekendPredicate: (date: Date) => boolean\n): number {\n return coreGetBusinessDaysCount(startDate, endDate, weekendPredicate);\n}\n\n/**\n * Calculate end date by adding business days to start date.\n * Delegates to core/scheduling/dateMath, converts Date result to string.\n * @returns End date as YYYY-MM-DD string\n */\nexport function addBusinessDays(\n startDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): string {\n const result = coreAddBusinessDays(startDate, businessDays, weekendPredicate);\n return result.toISOString().split('T')[0];\n}\n\n/**\n * Subtract business days from a date (inverse of addBusinessDays).\n * Delegates to core/scheduling/dateMath, converts Date result to string.\n * @returns Start date as YYYY-MM-DD string\n */\nexport function subtractBusinessDays(\n endDate: string | Date,\n businessDays: number,\n weekendPredicate: (date: Date) => boolean\n): string {\n const result = coreSubtractBusinessDays(endDate, businessDays, weekendPredicate);\n return result.toISOString().split('T')[0];\n}\n","'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// Filters\nexport * from './filters';\n\n// TaskList Column API\nexport type {\n BuiltInTaskListColumnId,\n TaskListColumn,\n TaskListColumnContext,\n} from './components/TaskList/columns/types';\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, createCustomDayPredicate, type CustomDayConfig, type CustomDayPredicateConfig } from '../../utils/dateUtils';\nimport { calculateGridWidth } from '../../utils/geometry';\nimport { validateDependencies, cascadeByLinks, universalCascade, computeParentDates, computeParentProgress, getChildren, removeDependenciesBetweenTasks, isTaskParent } from '../../core/scheduling';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport type { ValidationResult } from '../../types';\nimport { TaskPredicate } from '../../filters';\nimport type { TaskListColumn } from '../TaskList/columns/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\nconst SCROLL_TO_ROW_CONTEXT_ROWS = 2;\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 /**\n * Optional task subtype. Milestones are single-date tasks and default to\n * regular 'task' behavior when omitted.\n */\n type?: 'task' | 'milestone';\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 required (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 /** Lag in days */\n lag: number;\n}\n\nexport interface GanttChartProps<TTask extends Task = Task> {\n /** Array of tasks to display */\n tasks: TTask[];\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. Receives ONLY the changed tasks as full objects with all properties. */\n onTasksChange?: (tasks: TTask[]) => 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: TTask[]) => 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: TTask) => 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: TTask) => void;\n /** Callback when tasks are reordered via drag in the task list */\n onReorder?: (tasks: TTask[], movedTaskId?: string, inferredParentId?: string) => void;\n /** Callback when a task is promoted (parentId removed). If not provided, default internal logic is used. */\n onPromoteTask?: (taskId: string) => void;\n /** Callback when a task is demoted (parentId set). If not provided, default internal logic is used. */\n onDemoteTask?: (taskId: string, newParentId: string) => void;\n /** Enable add task button at bottom of task list (default: true) */\n enableAddTask?: boolean;\n /** View mode: 'day' renders one column per day, 'week' renders one column per 7 days, 'month' renders one column per month (default: 'day') */\n viewMode?: 'day' | 'week' | 'month';\n /** Custom day configurations with explicit type (weekend or workday) */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate (checked before customDays overrides) */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях, исключая выходные (default: true) */\n businessDays?: boolean;\n /**\n * Optional predicate to mark tasks in the current view.\n * Matching tasks stay visible and are highlighted in the chart and task list.\n * Dependencies are still computed on ALL tasks (normalizedTasks).\n */\n taskFilter?: TaskPredicate;\n /** Filter mode: 'highlight' shows all tasks with yellow highlight on matches, 'hide' hides non-matching tasks (default: 'highlight') */\n filterMode?: 'highlight' | 'hide';\n /** Set of collapsed parent task IDs for controlled mode */\n collapsedParentIds?: Set<string>;\n /** Callback when collapse/expand button is clicked (controlled mode) */\n onToggleCollapse?: (parentId: string) => void;\n /** Task IDs to highlight in the task list (for search results) */\n highlightedTaskIds?: Set<string>;\n /** Disable task drag and resize on the calendar grid (default: false) */\n disableTaskDrag?: boolean;\n /** Show calendar chart area (default: true) */\n showChart?: boolean;\n /** Additional custom columns to render in the TaskList after built-in columns */\n additionalColumns?: TaskListColumn<TTask>[];\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 scrollToRow: (taskId: string) => void;\n collapseAll: () => void;\n expandAll: () => 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 */\nfunction GanttChartInner<TTask extends Task = Task>(\n props: GanttChartProps<TTask>,\n ref: React.ForwardedRef<GanttChartHandle>\n) {\n const {\n tasks,\n dayWidth = 40,\n rowHeight = 40,\n headerHeight = 40,\n containerHeight,\n onTasksChange,\n onValidateDependencies,\n enableAutoSchedule,\n disableConstraints,\n onCascade,\n showTaskList = false,\n taskListWidth = 660,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n highlightExpiredTasks = false,\n onAdd,\n onDelete,\n onInsertAfter,\n onReorder,\n onPromoteTask,\n onDemoteTask,\n enableAddTask = true,\n viewMode = 'day',\n customDays,\n isWeekend,\n businessDays = true,\n taskFilter,\n filterMode = 'highlight',\n collapsedParentIds: externalCollapsedParentIds,\n onToggleCollapse: externalOnToggleCollapse,\n highlightedTaskIds,\n disableTaskDrag = false,\n showChart = true,\n additionalColumns,\n } = props;\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 const [taskListHasRightShadow, setTaskListHasRightShadow] = useState(false);\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 (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 // 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 // Create custom weekend predicate from props (memoized for performance)\n const isCustomWeekend = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\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 // Visible tasks are determined by collapsed parent state and optionally by filter mode.\n // Checks the full ancestor chain so grandchildren are hidden when any ancestor is collapsed.\n const visibleTasks = useMemo(() => {\n const parentMap = new Map(normalizedTasks.map(t => [t.id, t.parentId]));\n\n function isAnyAncestorCollapsed(parentId: string | undefined): boolean {\n let current = parentId;\n while (current) {\n if (collapsedParentIds.has(current)) return true;\n current = parentMap.get(current);\n }\n return false;\n }\n\n let tasks = normalizedTasks.filter(task => !isAnyAncestorCollapsed(task.parentId));\n\n // In 'hide' mode with active filter, only show matching tasks\n if (filterMode === 'hide' && taskFilter) {\n tasks = tasks.filter(taskFilter);\n }\n\n return tasks;\n }, [normalizedTasks, collapsedParentIds, filterMode, taskFilter]);\n\n const matchedTaskIds = useMemo(() => {\n if (!taskFilter) return new Set<string>();\n return new Set(visibleTasks.filter(taskFilter).map(task => task!.id));\n }, [visibleTasks, taskFilter]);\n\n const taskListHighlightedTaskIds = useMemo(() => {\n // In hide mode, no highlighting needed - all visible tasks already match the filter\n if (filterMode === 'hide') {\n return new Set<string>();\n }\n if ((!highlightedTaskIds || highlightedTaskIds.size === 0) && matchedTaskIds.size === 0) {\n return new Set<string>();\n }\n\n const mergedHighlightedTaskIds = new Set(highlightedTaskIds ?? []);\n matchedTaskIds.forEach((taskId) => mergedHighlightedTaskIds.add(taskId));\n return mergedHighlightedTaskIds;\n }, [filterMode, highlightedTaskIds, matchedTaskIds]);\n\n // Calculate total grid height from currently visible rows.\n const totalGridHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.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 // Position today at ~30% of visible area (closer to task list side)\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset + (dayWidth / 2) - containerWidth * 0.3);\n\n container.scrollLeft = Math.max(0, scrollLeft);\n }, []); // Empty deps array - run only on mount\n\n useEffect(() => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const updateShadow = () => {\n setTaskListHasRightShadow(container.scrollLeft > 0);\n };\n\n updateShadow();\n container.addEventListener('scroll', updateShadow, { passive: true });\n return () => {\n container.removeEventListener('scroll', updateShadow);\n };\n }, []);\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 // Position today at ~30% of visible area (closer to task list side)\n const todayOffset = todayIndex * dayWidth;\n const containerWidth = container.clientWidth;\n const scrollLeft = Math.round(todayOffset + (dayWidth / 2) - containerWidth * 0.3);\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 const scrollToRow = useCallback((taskId: string) => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const task = tasks.find(t => t.id === taskId);\n if (!task) return;\n\n const rowIndex = visibleTasks.findIndex(visibleTask => visibleTask.id === task.id);\n if (rowIndex === -1) return;\n\n const paddedRowIndex = Math.max(0, rowIndex - SCROLL_TO_ROW_CONTEXT_ROWS);\n const scrollTop = Math.max(0, rowHeight * paddedRowIndex);\n setSelectedTaskId(taskId);\n container.scrollTo({ top: scrollTop, behavior: 'smooth' });\n }, [tasks, visibleTasks, rowHeight]);\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 const [previewTasksById, setPreviewTasksById] = useState<Map<string, Task>>(new Map());\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 * Callback when tasks are modified.\n * Always receives ONLY the changed tasks as full objects with all properties.\n * Single task = array of 1 element (batch of size 1).\n */\n const handleTaskChange = useCallback((updatedTasks: Task[]) => {\n const updatedTask = updatedTasks[0];\n if (!updatedTask) return;\n const originalTask = tasks.find(t => t.id === updatedTask.id);\n if (!originalTask) {\n // New task or task not found - pass all tasks as-is\n onTasksChange?.(updatedTasks as TTask[]);\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 // Special case: parent progress cascade (multiple tasks, no date changes)\n if (updatedTasks.length > 1) {\n onTasksChange?.(updatedTasks as TTask[]);\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n // Single task without date changes - compute parent progress if needed\n const taskParentId = (updatedTask as any).parentId;\n if (taskParentId) {\n const parentProgress = computeParentProgress(taskParentId, tasks.map(t => t.id === updatedTask.id ? updatedTask : t));\n const parentTask = tasks.find(t => t.id === taskParentId);\n if (parentTask) {\n const updatedParent = { ...parentTask, progress: parentProgress };\n onTasksChange?.([updatedTask, updatedParent] as TTask[]);\n } else {\n onTasksChange?.([updatedTask] as TTask[]);\n }\n } else {\n onTasksChange?.([updatedTask] as TTask[]);\n }\n if (editingTaskId === updatedTask.id) {\n setEditingTaskId(null);\n }\n return;\n }\n\n // Date edits should behave the same across chart drag and task-list picker:\n // moving a parent shifts its descendants, and parent dates are then re-derived\n // from the shifted children inside universalCascade.\n const sourceTasks = tasks.map((task) => (\n task.id === updatedTask.id ? updatedTask : task\n ));\n\n const cascadedTasks = disableConstraints\n ? [updatedTask]\n : universalCascade(updatedTask, newStart, newEnd, sourceTasks, businessDays, isCustomWeekend);\n\n onTasksChange?.(cascadedTasks as TTask[]);\n }, [tasks, onTasksChange, disableConstraints, editingTaskId, businessDays, isCustomWeekend]);\n\n /**\n * Handle task deletion: collect all changed tasks (with cleaned dependencies),\n * emit onTasksChange with them, then emit onDelete for each deleted task ID\n * (original + all descendants) so the consumer can remove all of them.\n * For parent tasks, cascade delete to all children.\n */\n const handleDelete = useCallback((taskId: string) => {\n const toDelete = new Set<string>([taskId]);\n\n function collectDescendants(parentId: string) {\n const children = getChildren(parentId, tasks);\n children.forEach(child => {\n toDelete.add(child.id);\n collectDescendants(child.id);\n });\n }\n\n collectDescendants(taskId);\n\n const changedTasks: Task[] = [];\n tasks.forEach(task => {\n if (toDelete.has(task.id)) return;\n\n if (task.dependencies && task.dependencies.some(dep => toDelete.has(dep.taskId))) {\n changedTasks.push({\n ...task,\n dependencies: task.dependencies.filter(dep => !toDelete.has(dep.taskId))\n });\n }\n });\n\n if (changedTasks.length > 0) {\n onTasksChange?.(changedTasks as TTask[]);\n }\n\n // Call onDelete for each task in the cascade set (original + all descendants)\n // so the consumer removes all of them, not just the root.\n toDelete.forEach(id => onDelete?.(id));\n }, [tasks, onTasksChange, onDelete]);\n\n /**\n * Handle task insertion after inline draft confirmation.\n * The task name is already confirmed inside TaskList, so no auto-edit is needed here.\n */\n const handleInsertAfter = useCallback((taskId: string, newTask: Task) => {\n onInsertAfter?.(taskId, newTask as TTask);\n }, [onInsertAfter]);\n\n /**\n * Handle task reordering.\n *\n * Preferred path: emit a single onReorder callback with the full normalized task array.\n * Backward-compatibility path: if onReorder is not provided, fall back to onTasksChange.\n *\n * This avoids duplicate reorder notifications for consumers that already opted into\n * the dedicated reorder API while preserving legacy consumers that only listen to\n * onTasksChange.\n */\n const handleReorder = useCallback((reorderedTasks: Task[], movedTaskId?: string, inferredParentId?: string) => {\n let updated = reorderedTasks;\n if (movedTaskId) {\n updated = updated.map(t => {\n if (t.id === movedTaskId) {\n return { ...t, parentId: inferredParentId || undefined };\n }\n return t;\n });\n }\n\n const normalized = normalizeHierarchyTasks(updated);\n if (onReorder) {\n onReorder(normalized as TTask[], movedTaskId, inferredParentId);\n return;\n }\n\n onTasksChange?.(normalized as TTask[]);\n }, [onTasksChange, 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((\n overrides: Map<string, { left: number; width: number }>,\n previewTasks: Task[] = []\n ) => {\n setCascadeOverrides(new Map(overrides));\n setPreviewTasksById(new Map(previewTasks.map(task => [task.id, task])));\n }, []);\n\n const previewNormalizedTasks = useMemo(() => {\n if (previewTasksById.size === 0) return normalizedTasks;\n return normalizedTasks.map(task => previewTasksById.get(task.id) ?? task);\n }, [normalizedTasks, previewTasksById]);\n\n const previewVisibleTasks = useMemo(() => {\n if (previewTasksById.size === 0) return visibleTasks;\n return visibleTasks.map(task => previewTasksById.get(task.id) ?? task);\n }, [visibleTasks, previewTasksById]);\n\n /**\n * Handle cascade completion — emit all changed tasks.\n * Parent tasks are computed from children - don't send them in batch.\n */\n const handleCascade = useCallback((cascadedTasks: Task[]) => {\n // Backend should compute parent dates from children\n onTasksChange?.(cascadedTasks as TTask[]);\n }, [tasks, onTasksChange]);\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 // 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 // Get all parent task IDs (tasks that have children)\n const allParentIds = useMemo(() => {\n return new Set(\n normalizedTasks\n .filter(t => isTaskParent(t.id, normalizedTasks))\n .map(t => t.id)\n );\n }, [normalizedTasks]);\n\n const handleCollapseAll = useCallback(() => {\n if (externalCollapsedParentIds) return; // Don't modify external state\n setInternalCollapsedParentIds(allParentIds);\n }, [allParentIds, externalCollapsedParentIds]);\n\n const handleExpandAll = useCallback(() => {\n if (externalCollapsedParentIds) return; // Don't modify external state\n setInternalCollapsedParentIds(new Set());\n }, [externalCollapsedParentIds]);\n\n // Expose collapse/expand methods via ref (must be after handlers are defined)\n useImperativeHandle(\n ref,\n () => ({\n scrollToToday,\n scrollToTask,\n scrollToRow,\n collapseAll: handleCollapseAll,\n expandAll: handleExpandAll,\n }),\n [scrollToToday, scrollToTask, scrollToRow, handleCollapseAll, handleExpandAll]\n );\n\n /**\n * Calculate the depth of a task in the hierarchy.\n * Root tasks have depth 0, their children have depth 1, etc.\n */\n function getTaskDepth(taskId: string, tasks: Task[]): number {\n let depth = 0;\n let current: Task | undefined = tasks.find(t => t.id === taskId);\n while (current) {\n if (!current.parentId) break;\n depth++;\n const parentId: string = current.parentId;\n current = tasks.find(t => t.id === parentId);\n }\n return depth;\n }\n\n const handlePromoteTask = useCallback((taskId: string) => {\n // If consumer provided custom callback, use it\n if (onPromoteTask) {\n onPromoteTask(taskId);\n return;\n }\n\n // Default internal logic\n const taskToPromote = tasks.find(t => t.id === taskId);\n if (!taskToPromote || !taskToPromote.parentId) {\n return;\n }\n\n // Calculate current depth and determine new parent for single-level promotion\n const depth = getTaskDepth(taskId, tasks);\n const grandparentId = depth > 1\n ? tasks.find(t => t.id === taskToPromote.parentId)?.parentId\n : undefined;\n\n const currentParentId = taskToPromote.parentId;\n const siblings = tasks.filter(t => t.parentId === currentParentId);\n\n const promotedTask = { ...taskToPromote, parentId: grandparentId };\n\n if (siblings.length <= 1) {\n onTasksChange?.([promotedTask] as TTask[]);\n return;\n }\n\n // Reorder: place after last sibling of the old parent group\n const lastSiblingIndex = tasks\n .map((t, i) => ({ task: t, index: i }))\n .filter(({ task }) => task.parentId === currentParentId)\n .sort((a, b) => b.index - a.index)[0];\n\n if (!lastSiblingIndex) {\n onTasksChange?.([promotedTask] as TTask[]);\n return;\n }\n\n const reorderedTasks = normalizeHierarchyTasks([\n ...tasks.filter(t => t.id !== taskId).slice(0, lastSiblingIndex.index + 1),\n promotedTask,\n ...tasks.filter(t => t.id !== taskId).slice(lastSiblingIndex.index + 1)\n ]);\n\n onTasksChange?.(reorderedTasks as TTask[]);\n }, [tasks, onTasksChange, onPromoteTask]);\n\n const handleDemoteTask = useCallback((taskId: string, newParentId: string) => {\n // If consumer provided custom callback, use it\n if (onDemoteTask) {\n onDemoteTask(taskId, newParentId);\n return;\n }\n\n // Default internal logic\n const wouldCreateCircular = (targetId: string, parentId: string, tasks: Task[]): boolean => {\n if (targetId === parentId) return true;\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, tasks)) {\n return;\n }\n\n let updatedTasks = removeDependenciesBetweenTasks(taskId, newParentId, tasks);\n\n const demotedTask = updatedTasks.find(t => t.id === taskId);\n if (!demotedTask) return;\n\n // If task was a parent (had children), save computed dates as its own dates\n // These become the task's \"own\" dates after demotion\n const wasParent = getChildren(taskId, tasks).length > 0;\n let taskDates = { startDate: demotedTask.startDate, endDate: demotedTask.endDate };\n\n if (wasParent) {\n const computedDates = computeParentDates(taskId, tasks);\n taskDates = {\n startDate: computedDates.startDate.toISOString().split('T')[0],\n endDate: computedDates.endDate.toISOString().split('T')[0]\n };\n }\n\n const updatedDemotedTask = {\n ...demotedTask,\n parentId: newParentId,\n startDate: taskDates.startDate,\n endDate: taskDates.endDate\n };\n\n // Only send the demoted task - parent dates are computed from children\n onTasksChange?.([updatedDemotedTask] as TTask[]);\n }, [tasks, onTasksChange, onDemoteTask]);\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 onTasksChange={handleTaskChange}\n selectedTaskId={selectedTaskId ?? undefined}\n onTaskSelect={handleTaskSelect}\n show={showTaskList}\n hasRightShadow={taskListHasRightShadow}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n onScrollToTask={scrollToTask}\n onSelectedChipChange={setSelectedChip}\n onAdd={onAdd as ((task: Task) => void) | undefined}\n onDelete={handleDelete}\n onInsertAfter={handleInsertAfter as ((taskId: string, newTask: Task) => void) | undefined}\n onReorder={handleReorder as ((tasks: Task[], movedTaskId?: string, inferredParentId?: string) => void) | undefined}\n editingTaskId={editingTaskId}\n enableAddTask={enableAddTask}\n collapsedParentIds={collapsedParentIds}\n onToggleCollapse={handleToggleCollapse}\n onPromoteTask={onPromoteTask ?? handlePromoteTask}\n onDemoteTask={onDemoteTask ?? handleDemoteTask}\n highlightedTaskIds={taskListHighlightedTaskIds}\n customDays={customDays}\n isWeekend={isWeekend}\n businessDays={businessDays}\n filterMode={filterMode}\n filteredTaskIds={matchedTaskIds}\n isFilterActive={!!taskFilter}\n additionalColumns={additionalColumns}\n />\n\n {/* Chart area */}\n <div className={showChart ? '' : 'gantt-chart-hidden'} 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 viewMode={viewMode}\n isCustomWeekend={isCustomWeekend}\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 viewMode={viewMode}\n isCustomWeekend={isCustomWeekend}\n />\n\n {todayInRange && <TodayIndicator monthStart={monthStart} dayWidth={dayWidth} />}\n\n {/* Dependency lines SVG overlay */}\n <DependencyLines\n tasks={previewVisibleTasks}\n allTasks={previewNormalizedTasks}\n collapsedParentIds={collapsedParentIds}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n gridWidth={gridWidth}\n dragOverrides={dependencyOverrides}\n selectedDep={selectedChip}\n businessDays={businessDays}\n weekendPredicate={isCustomWeekend}\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 {visibleTasks.map((task, index) => (\n <TaskRow\n key={task.id}\n task={task}\n monthStart={monthStart}\n dayWidth={dayWidth}\n rowHeight={rowHeight}\n onTasksChange={handleTaskChange as (tasks: Task[]) => void}\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 as (overrides: Map<string, { left: number; width: number }>, previewTasks?: Task[]) => void}\n onCascade={handleCascade as (cascadedTasks: Task[]) => void}\n highlightExpiredTasks={highlightExpiredTasks}\n isFilterMatch={filterMode === 'highlight' ? matchedTaskIds.has(task.id) : false}\n businessDays={businessDays}\n customDays={customDays}\n isWeekend={isWeekend}\n disableTaskDrag={disableTaskDrag}\n />\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport const GanttChart = forwardRef(GanttChartInner) as <TTask extends Task = Task>(\n props: GanttChartProps<TTask> & { ref?: React.Ref<GanttChartHandle> }\n) => React.ReactElement;\n\n(GanttChart as React.FC).displayName = 'GanttChart';\n\nexport default GanttChart;\n","/**\n * Core scheduling module — runtime-agnostic scheduling logic.\n * Zero React/DOM/date-fns dependencies.\n */\nexport * from './types';\nexport * from './dateMath';\nexport * from './dependencies';\nexport * from './cascade';\nexport * from './commands';\nexport * from './execute';\nexport * from './validation';\nexport * from './hierarchy';\n","/**\n * Dependency calculation functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { LinkType, TaskDependency, Task } from './types';\nimport {\n getBusinessDayOffset,\n shiftBusinessDayOffset,\n DAY_MS,\n getTaskDuration,\n} from './dateMath';\n\n/**\n * Normalize predecessor dates for scheduling calculations.\n * For milestone tasks, the scheduling \"finish\" anchor is treated as the day\n * before startDate. This preserves the standard inclusive FS formula\n * (`predEnd + lag + 1`) while making milestone FS lag=0 land on the same day.\n */\nexport function normalizePredecessorDates(\n predecessor: Pick<Task, 'startDate' | 'endDate' | 'type'>,\n parseDateFn: (d: string | Date) => Date\n): { predStart: Date; predEnd: Date } {\n const predStart = parseDateFn(predecessor.startDate);\n const isMilestone = predecessor.type === 'milestone';\n const predEnd = isMilestone\n ? new Date(predStart.getTime() - DAY_MS)\n : parseDateFn(predecessor.endDate);\n return { predStart, predEnd };\n}\n\n/**\n * Get lag value from dependency, defaulting to 0.\n */\nexport function getDependencyLag(dep: Pick<TaskDependency, 'lag'>): number {\n return Number.isFinite(dep.lag) ? dep.lag : 0;\n}\n\n/**\n * Normalize lag for FS links — clamp to >= -predecessorDuration.\n */\nexport function normalizeDependencyLag(\n linkType: LinkType,\n lag: number,\n predecessorStart: Date,\n predecessorEnd: Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\n if (linkType !== 'FS') {\n return lag;\n }\n\n const predecessorDuration = getTaskDuration(\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n\n return Math.max(-predecessorDuration, lag);\n}\n\n/**\n * Compute lag (in days) from actual predecessor/successor dates.\n * This is the single source of truth for lag semantics.\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 businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): number {\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\n // Calendar days (original logic)\n if (!businessDays || !weekendPredicate) {\n switch (linkType) {\n case 'FS':\n return normalizeDependencyLag(\n linkType,\n Math.round((sS - pE) / DAY_MS) - 1,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate\n );\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 const anchorDate = linkType === 'SS' || linkType === 'SF' ? predStart : predEnd;\n const targetDate = linkType === 'FS' || linkType === 'SS' ? succStart : succEnd;\n const businessOffset = getBusinessDayOffset(anchorDate, targetDate, weekendPredicate);\n\n switch (linkType) {\n case 'FS':\n return normalizeDependencyLag(\n linkType,\n businessOffset - 1,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate\n );\n case 'SS': return businessOffset;\n case 'FF': return businessOffset;\n case 'SF': return businessOffset + 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 businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): Date {\n const normalizedLag = normalizeDependencyLag(\n linkType,\n lag,\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n\n // Calendar days (original logic)\n if (!businessDays || !weekendPredicate) {\n switch (linkType) {\n case 'FS':\n return new Date(predecessorEnd.getTime() + (normalizedLag + 1) * DAY_MS);\n case 'SS':\n return new Date(predecessorStart.getTime() + normalizedLag * DAY_MS);\n case 'FF':\n return new Date(predecessorEnd.getTime() + normalizedLag * DAY_MS);\n case 'SF':\n return new Date(predecessorStart.getTime() + (normalizedLag - 1) * DAY_MS);\n }\n }\n\n const anchorDate = (linkType === 'FS' || linkType === 'FF') ? predecessorEnd : predecessorStart;\n let offset: number;\n switch (linkType) {\n case 'FS':\n offset = normalizedLag + 1;\n break;\n case 'SS':\n offset = normalizedLag;\n break;\n case 'FF':\n offset = normalizedLag;\n break;\n case 'SF':\n offset = normalizedLag - 1;\n break;\n }\n return shiftBusinessDayOffset(anchorDate, offset, weekendPredicate);\n}\n","/**\n * Cascade engine functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, LinkType } from './types';\nimport {\n normalizeUTCDate,\n getTaskDuration,\n alignToWorkingDay,\n} from './dateMath';\nimport {\n calculateSuccessorDate,\n getDependencyLag,\n normalizePredecessorDates,\n} from './dependencies';\nimport {\n getChildren,\n isTaskParent,\n computeParentDates,\n} from './hierarchy';\nimport {\n buildTaskRangeFromStart,\n buildTaskRangeFromEnd,\n moveTaskRange,\n} from './commands';\n\nfunction parseCascadeDateInput(date: string | Date): Date {\n if (date instanceof Date) {\n return normalizeUTCDate(date);\n }\n return normalizeUTCDate(new Date(`${date.split('T')[0]}T00:00:00.000Z`));\n}\n\n/**\n * Get successor tasks of a dragged task using BFS, filtered by link type(s).\n */\nexport function getSuccessorChain(\n draggedTaskId: string,\n allTasks: Task[],\n linkTypes: LinkType[] = ['FS']\n): Task[] {\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);\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;\n}\n\n/**\n * Cascade successors by actual link constraints (BFS, constraint-based).\n */\nexport function cascadeByLinks(\n movedTaskId: string,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[],\n skipChildCascade: boolean = false\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\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 if (!skipChildCascade) {\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (visited.has(child.id) || child.locked) continue;\n\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 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\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 duration = getTaskDuration(origStart, origEnd);\n const currentTask = taskById.get(currentId)!;\n const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(\n {\n startDate: predStart,\n endDate: predEnd,\n type: currentTask.type,\n },\n parseCascadeDateInput\n );\n const constraintDate = calculateSuccessorDate(\n normalizedPredStart,\n normalizedPredEnd,\n dep.type,\n getDependencyLag(dep)\n );\n\n let newSuccStart: Date;\n let newSuccEnd: Date;\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n ({ start: newSuccStart, end: newSuccEnd } = buildTaskRangeFromStart(constraintDate, duration));\n } else {\n ({ start: newSuccStart, end: newSuccEnd } = buildTaskRangeFromEnd(constraintDate, duration));\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;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get transitive closure of successors for cascading.\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 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 * Arrival mode for universal cascade BFS entries.\n */\ntype ArrivalMode = 'direct' | 'child-delta' | 'parent-recalc' | 'dependency';\n\n/**\n * Universal cascade engine that propagates a moved task's new position through\n * the entire dependency+hierarchy graph using BFS with change detection.\n */\nexport function universalCascade(\n movedTask: Task,\n newStart: Date,\n newEnd: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): Task[] {\n const taskById = new Map(allTasks.map(t => [t.id, t]));\n\n const updatedDates = new Map<string, { start: Date; end: Date }>();\n updatedDates.set(movedTask.id, { start: newStart, end: newEnd });\n\n const resultMap = new Map<string, Task>();\n resultMap.set(movedTask.id, {\n ...movedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n });\n\n const queue: Array<[string, ArrivalMode]> = [[movedTask.id, 'direct']];\n\n const childShifted = new Set<string>();\n\n let iterations = 0;\n const MAX_ITERATIONS = allTasks.length * 3;\n\n while (queue.length > 0 && iterations < MAX_ITERATIONS) {\n iterations++;\n const [currentId, arrivalMode] = queue.shift()!;\n const { start: currStart, end: currEnd } = updatedDates.get(currentId)!;\n const currentOriginal = taskById.get(currentId)!;\n\n // RULE 1: Hierarchy children follow their parent\n if (arrivalMode !== 'parent-recalc') {\n const children = getChildren(currentId, allTasks);\n for (const child of children) {\n if (childShifted.has(child.id) || child.locked) continue;\n\n const parentOrigStart = new Date(currentOriginal.startDate as string);\n const parentOrigEnd = new Date(currentOriginal.endDate as string);\n\n const childOrigStart = new Date(child.startDate as string);\n const childOrigEnd = new Date(child.endDate as string);\n\n const startDeltaMs = currStart.getTime() - parentOrigStart.getTime();\n const endDeltaMs = currEnd.getTime() - parentOrigEnd.getTime();\n\n let childNewStart: Date;\n let childNewEnd: Date;\n\n if (businessDays && weekendPredicate) {\n const proposedStart = new Date(childOrigStart.getTime() + startDeltaMs);\n const snapDirection: 1 | -1 = currStart.getTime() >= parentOrigStart.getTime() ? 1 : -1;\n const movedRange = moveTaskRange(\n child.startDate,\n child.endDate,\n proposedStart,\n true,\n weekendPredicate,\n snapDirection\n );\n childNewStart = movedRange.start;\n childNewEnd = movedRange.end;\n } else {\n childNewStart = new Date(childOrigStart.getTime() + startDeltaMs);\n childNewEnd = new Date(childOrigEnd.getTime() + endDeltaMs);\n }\n\n const prev = updatedDates.get(child.id);\n if (prev && prev.start.getTime() === childNewStart.getTime() && prev.end.getTime() === childNewEnd.getTime()) {\n continue;\n }\n\n updatedDates.set(child.id, { start: childNewStart, end: childNewEnd });\n childShifted.add(child.id);\n queue.push([child.id, 'child-delta']);\n resultMap.set(child.id, {\n ...child,\n startDate: childNewStart.toISOString().split('T')[0],\n endDate: childNewEnd.toISOString().split('T')[0],\n });\n }\n }\n\n // RULE 2: Parent task is recomputed from its children\n const parentId = (currentOriginal as any).parentId as string | undefined;\n if (parentId) {\n const parent = taskById.get(parentId);\n if (parent && !parent.locked) {\n const siblings = getChildren(parentId, allTasks);\n\n const siblingPositions = siblings.map(sib => {\n if (updatedDates.has(sib.id)) return updatedDates.get(sib.id)!;\n return { start: new Date(sib.startDate as string), end: new Date(sib.endDate as string) };\n });\n\n const minStart = new Date(Math.min(...siblingPositions.map(p => p.start.getTime())));\n const maxEnd = new Date(Math.max(...siblingPositions.map(p => p.end.getTime())));\n\n const prev = updatedDates.get(parentId);\n if (!prev || prev.start.getTime() !== minStart.getTime() || prev.end.getTime() !== maxEnd.getTime()) {\n updatedDates.set(parentId, { start: minStart, end: maxEnd });\n queue.push([parentId, 'parent-recalc']);\n resultMap.set(parentId, {\n ...parent,\n startDate: minStart.toISOString().split('T')[0],\n endDate: maxEnd.toISOString().split('T')[0],\n });\n }\n }\n }\n\n // RULE 3: Dependency successors are repositioned\n for (const task of allTasks) {\n if (task.locked || !task.dependencies) continue;\n\n const dep = task.dependencies.find(d => d.taskId === currentId);\n if (!dep) continue;\n\n const origStart = new Date(task.startDate as string);\n const origEnd = new Date(task.endDate as string);\n const { predStart: normalizedPredStart, predEnd: normalizedPredEnd } = normalizePredecessorDates(\n {\n startDate: currStart,\n endDate: currEnd,\n type: currentOriginal.type,\n },\n parseCascadeDateInput\n );\n const constraintDate = calculateSuccessorDate(\n normalizedPredStart, normalizedPredEnd, dep.type, getDependencyLag(dep),\n businessDays, weekendPredicate\n );\n\n let succNewStart: Date;\n let succNewEnd: Date;\n const duration = getTaskDuration(origStart, origEnd, businessDays, weekendPredicate);\n\n if (dep.type === 'FS' || dep.type === 'SS') {\n ({ start: succNewStart, end: succNewEnd } = buildTaskRangeFromStart(\n constraintDate,\n duration,\n businessDays,\n weekendPredicate\n ));\n } else {\n ({ start: succNewStart, end: succNewEnd } = buildTaskRangeFromEnd(\n constraintDate,\n duration,\n businessDays,\n weekendPredicate\n ));\n }\n\n const prev = updatedDates.get(task.id);\n if (prev && prev.start.getTime() === succNewStart.getTime() && prev.end.getTime() === succNewEnd.getTime()) {\n continue;\n }\n\n updatedDates.set(task.id, { start: succNewStart, end: succNewEnd });\n queue.push([task.id, 'dependency']);\n resultMap.set(task.id, {\n ...task,\n startDate: succNewStart.toISOString().split('T')[0],\n endDate: succNewEnd.toISOString().split('T')[0],\n });\n }\n }\n\n return Array.from(resultMap.values());\n}\n\n/**\n * Recalculate all task dates when switching between business/calendar day modes.\n */\nexport function reflowTasksOnModeSwitch(\n sourceTasks: Task[],\n toBusinessDays: boolean,\n weekendPredicate: (date: Date) => boolean\n): Task[] {\n const fromBusinessDays = !toBusinessDays;\n let tasks: Task[] = sourceTasks.map(t => ({ ...t }));\n\n const toISO = (d: Date) => d.toISOString().split('T')[0];\n\n for (const task of tasks) {\n if (isTaskParent(task.id, tasks)) continue;\n\n const start = normalizeUTCDate(new Date(`${task.startDate}T00:00:00.000Z`));\n const duration = getTaskDuration(task.startDate, task.endDate, fromBusinessDays, weekendPredicate);\n\n let range: { start: Date; end: Date };\n if (toBusinessDays) {\n const alignedStart = alignToWorkingDay(start, 1, weekendPredicate);\n range = buildTaskRangeFromStart(alignedStart, duration, true, weekendPredicate);\n } else {\n range = buildTaskRangeFromStart(start, duration, false);\n }\n\n task.startDate = toISO(range.start);\n task.endDate = toISO(range.end);\n }\n\n for (const task of tasks) {\n if (!isTaskParent(task.id, tasks)) continue;\n const { startDate, endDate } = computeParentDates(task.id, tasks);\n task.startDate = toISO(startDate);\n task.endDate = toISO(endDate);\n }\n\n if (toBusinessDays) {\n const rootSeeds = tasks.filter(\n t => !(t as any).parentId && (!t.dependencies || t.dependencies.length === 0)\n );\n\n for (const seed of rootSeeds) {\n const current = tasks.find(t => t.id === seed.id)!;\n const start = new Date(`${current.startDate}T00:00:00.000Z`);\n const end = new Date(`${current.endDate}T00:00:00.000Z`);\n\n const cascaded = universalCascade(current, start, end, tasks, toBusinessDays, weekendPredicate);\n const updates = new Map(cascaded.map((t): [string, Task] => [t.id, t]));\n tasks = tasks.map(t => updates.get(t.id) ?? t);\n }\n }\n\n return tasks;\n}\n","/**\n * Hierarchy scheduling functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task } from './types';\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 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 * Get all descendant tasks of a parent task (transitive closure of children).\n * Returns all tasks where task.parentId is in the hierarchy of the parent.\n */\nexport function getAllDescendants(parentId: string, tasks: Task[]): Task[] {\n const descendants: Task[] = [];\n const visited = new Set<string>();\n\n function collectChildren(taskId: string) {\n if (visited.has(taskId)) return;\n visited.add(taskId);\n\n const children = getChildren(taskId, tasks);\n for (const child of children) {\n descendants.push(child);\n collectChildren(child.id);\n }\n }\n\n collectChildren(parentId);\n return descendants;\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: 'FS' | 'SS' | 'FF' | 'SF';\n lag: number;\n}> {\n const edges: Array<{ predecessorId: string; successorId: string; type: 'FS' | 'SS' | 'FF' | 'SF'; 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 * Remove dependencies between two tasks in both directions.\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 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 */\nexport function findParentId(taskId: string, tasks: Task[]): string | undefined {\n const task = tasks.find(t => t.id === taskId);\n return task?.parentId;\n}\n\n/**\n * Returns true when ancestorId is an ancestor of taskId in the current hierarchy.\n */\nexport function isAncestorTask(ancestorId: string, taskId: string, tasks: Task[]): boolean {\n const taskById = new Map(tasks.map(task => [task.id, task]));\n const visited = new Set<string>();\n let current = taskById.get(taskId);\n\n while (current?.parentId) {\n if (current.parentId === ancestorId) {\n return true;\n }\n\n if (visited.has(current.parentId)) {\n return false;\n }\n\n visited.add(current.parentId);\n current = taskById.get(current.parentId);\n }\n\n return false;\n}\n\n/**\n * Returns true when tasks are in the same ancestry chain.\n */\nexport function areTasksHierarchicallyRelated(taskId1: string, taskId2: string, tasks: Task[]): boolean {\n if (taskId1 === taskId2) {\n return true;\n }\n\n return isAncestorTask(taskId1, taskId2, tasks) || isAncestorTask(taskId2, taskId1, tasks);\n}\n","/**\n * High-level schedule command functions.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task } from './types';\nimport {\n normalizeUTCDate,\n parseDateOnly,\n addBusinessDays,\n subtractBusinessDays,\n alignToWorkingDay,\n getTaskDuration,\n getBusinessDaysCount,\n} from './dateMath';\nimport {\n calculateSuccessorDate,\n getDependencyLag,\n normalizeDependencyLag,\n computeLagFromDates,\n normalizePredecessorDates,\n} from './dependencies';\n\n// Re-export for backward compat — these live in dateMath now\nexport { alignToWorkingDay, getTaskDuration };\n\n/**\n * Build a task range (start/end dates) from a start date and duration.\n */\nexport function buildTaskRangeFromStart(\n startDate: Date,\n duration: number,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = 1\n): { start: Date; end: Date } {\n const normalizedStart = businessDays && weekendPredicate\n ? alignToWorkingDay(startDate, snapDirection, weekendPredicate)\n : normalizeUTCDate(startDate);\n\n if (businessDays && weekendPredicate) {\n return {\n start: normalizedStart,\n end: parseDateOnly(addBusinessDays(normalizedStart, duration, weekendPredicate)),\n };\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n return {\n start: normalizedStart,\n end: new Date(normalizedStart.getTime() + (Math.max(1, duration) - 1) * DAY_MS),\n };\n}\n\n/**\n * Build a task range (start/end dates) from an end date and duration.\n */\nexport function buildTaskRangeFromEnd(\n endDate: Date,\n duration: number,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = -1\n): { start: Date; end: Date } {\n const normalizedEnd = businessDays && weekendPredicate\n ? alignToWorkingDay(endDate, snapDirection, weekendPredicate)\n : normalizeUTCDate(endDate);\n\n if (businessDays && weekendPredicate) {\n return {\n start: parseDateOnly(subtractBusinessDays(normalizedEnd, duration, weekendPredicate)),\n end: normalizedEnd,\n };\n }\n\n const DAY_MS = 24 * 60 * 60 * 1000;\n return {\n start: new Date(normalizedEnd.getTime() - (Math.max(1, duration) - 1) * DAY_MS),\n end: normalizedEnd,\n };\n}\n\n/**\n * Move a task range to a new start date, preserving duration.\n */\nexport function moveTaskRange(\n originalStart: string | Date,\n originalEnd: string | Date,\n proposedStart: Date,\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean,\n snapDirection: 1 | -1 = 1\n): { start: Date; end: Date } {\n return buildTaskRangeFromStart(\n proposedStart,\n getTaskDuration(originalStart, originalEnd, businessDays, weekendPredicate),\n businessDays,\n weekendPredicate,\n snapDirection\n );\n}\n\n/**\n * Clamp task range start date based on incoming FS dependencies.\n */\nexport function clampTaskRangeForIncomingFS(\n task: Pick<Task, 'dependencies'>,\n proposedStart: Date,\n proposedEnd: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n if (!task.dependencies?.length) {\n return { start: proposedStart, end: proposedEnd };\n }\n\n let minAllowedStart: Date | null = null;\n\n for (const dep of task.dependencies) {\n if (dep.type !== 'FS') {\n continue;\n }\n\n const predecessor = allTasks.find(candidate => candidate.id === dep.taskId);\n if (!predecessor) {\n continue;\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const predecessorDuration = getTaskDuration(\n predecessorStart,\n predecessorEnd,\n businessDays,\n weekendPredicate\n );\n const candidateMinStart = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n 'FS',\n -predecessorDuration,\n businessDays,\n weekendPredicate\n );\n\n if (!minAllowedStart || candidateMinStart.getTime() > minAllowedStart.getTime()) {\n minAllowedStart = candidateMinStart;\n }\n }\n\n if (!minAllowedStart || proposedStart.getTime() >= minAllowedStart.getTime()) {\n return { start: proposedStart, end: proposedEnd };\n }\n\n return buildTaskRangeFromStart(\n minAllowedStart,\n getTaskDuration(proposedStart, proposedEnd, businessDays, weekendPredicate),\n businessDays,\n weekendPredicate\n );\n}\n\n/**\n * Recalculate incoming dependency lags after a task's dates change.\n */\nexport function recalculateIncomingLags(\n task: Task,\n newStartDate: Date,\n newEndDate: Date,\n allTasks: Task[],\n businessDays: boolean = false,\n weekendPredicate?: (date: Date) => boolean\n): NonNullable<Task['dependencies']> {\n if (!task.dependencies) return [];\n return task.dependencies.map(dep => {\n const predecessor = allTasks.find(candidate => candidate.id === dep.taskId);\n if (!predecessor) {\n return { ...dep, lag: getDependencyLag(dep) };\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(\n predecessor,\n (d) => new Date(d instanceof Date ? d.getTime() : `${String(d).split('T')[0]}T00:00:00.000Z`)\n );\n const nextLag = computeLagFromDates(\n dep.type,\n predecessorStart,\n predecessorEnd,\n newStartDate,\n newEndDate,\n businessDays,\n weekendPredicate\n );\n\n return { ...dep, lag: nextLag };\n });\n}\n\n","/**\n * Command-level scheduling API.\n * High-level functions that compose low-level scheduling primitives.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, ScheduleCommandResult, ScheduleCommandOptions } from './types';\nimport { moveTaskRange, recalculateIncomingLags, buildTaskRangeFromEnd, buildTaskRangeFromStart, getTaskDuration } from './commands';\nimport { universalCascade } from './cascade';\nimport { parseDateOnly } from './dateMath';\nimport { calculateSuccessorDate, getDependencyLag, normalizePredecessorDates } from './dependencies';\nimport { computeParentDates, isTaskParent } from './hierarchy';\n\nfunction toIsoDate(date: Date): string {\n return date.toISOString().split('T')[0];\n}\n\nfunction createChangedResult(snapshot: Task[], nextTasks: Task[]): ScheduleCommandResult {\n const originalById = new Map(snapshot.map(task => [task.id, task]));\n const changedTasks = nextTasks.filter(task => JSON.stringify(originalById.get(task.id)) !== JSON.stringify(task));\n\n return {\n changedTasks,\n changedIds: changedTasks.map(task => task.id),\n };\n}\n\n/**\n * Move a task to a new start date with cascade and lag recalculation.\n * Identical to manual composition: moveTaskRange -> recalculateIncomingLags -> universalCascade.\n */\nexport function moveTaskWithCascade(\n taskId: string,\n newStart: Date,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n // Step 1: Calculate new range preserving duration\n const newRange = moveTaskRange(\n task.startDate,\n task.endDate,\n newStart,\n businessDays,\n weekendPredicate\n );\n\n // Step 2: Recalculate incoming dependency lags\n const updatedDependencies = recalculateIncomingLags(\n task,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Step 3: Create moved task with updated deps\n const movedTask: Task = {\n ...task,\n startDate: newRange.start.toISOString().split('T')[0],\n endDate: newRange.end.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n // Step 4: Cascade through dependency graph\n if (options?.skipCascade) {\n return {\n changedTasks: [movedTask],\n changedIds: [movedTask.id],\n };\n }\n\n const cascadeResult = universalCascade(\n movedTask,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Merge: movedTask + cascade results\n const resultMap = new Map<string, Task>();\n resultMap.set(movedTask.id, movedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Resize a task by changing its start or end date.\n * anchor='end': new end date, start stays fixed.\n * anchor='start': new start date, end stays fixed.\n */\nexport function resizeTaskWithCascade(\n taskId: string,\n anchor: 'start' | 'end',\n newDate: Date,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n const originalStart = parseDateOnly(task.startDate);\n const originalEnd = parseDateOnly(task.endDate);\n let newRange: { start: Date; end: Date };\n\n if (anchor === 'end') {\n // anchor='end': new end date, start stays fixed\n newRange = { start: originalStart, end: newDate };\n } else {\n // anchor='start': new start date, end stays fixed\n newRange = { start: newDate, end: originalEnd };\n }\n\n // Recalculate lags\n const updatedDependencies = recalculateIncomingLags(\n task,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n // Create resized task\n const resizedTask: Task = {\n ...task,\n startDate: newRange.start.toISOString().split('T')[0],\n endDate: newRange.end.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n if (options?.skipCascade) {\n return {\n changedTasks: [resizedTask],\n changedIds: [resizedTask.id],\n };\n }\n\n // Cascade through dependency graph\n const cascadeResult = universalCascade(\n resizedTask,\n newRange.start,\n newRange.end,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const resultMap = new Map<string, Task>();\n resultMap.set(resizedTask.id, resizedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Recalculate a task's dates based on its dependency constraints.\n * Finds all predecessors and computes the most constrained date.\n */\nexport function recalculateTaskFromDependencies(\n taskId: string,\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const task = snapshot.find(t => t.id === taskId);\n if (!task) {\n return { changedTasks: [], changedIds: [] };\n }\n\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n\n if (!task.dependencies || task.dependencies.length === 0) {\n // No dependencies — return the task as-is\n return {\n changedTasks: [task],\n changedIds: [task.id],\n };\n }\n\n // Find the most constrained start/end based on all predecessors\n let constrainedStart: Date | null = null;\n let constrainedEnd: Date | null = null;\n\n for (const dep of task.dependencies) {\n const predecessor = snapshot.find(t => t.id === dep.taskId);\n if (!predecessor) continue;\n\n const { predStart, predEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const constraintDate = calculateSuccessorDate(\n predStart,\n predEnd,\n dep.type,\n getDependencyLag(dep),\n businessDays,\n weekendPredicate\n );\n\n const duration = getTaskDuration(\n parseDateOnly(task.startDate),\n parseDateOnly(task.endDate),\n businessDays,\n weekendPredicate\n );\n\n let range: { start: Date; end: Date };\n if (dep.type === 'FS' || dep.type === 'SS') {\n range = buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate);\n } else {\n range = buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);\n }\n\n // Take the latest start as the effective constraint\n if (!constrainedStart || range.start.getTime() > constrainedStart.getTime()) {\n constrainedStart = range.start;\n constrainedEnd = range.end;\n }\n }\n\n if (!constrainedStart || !constrainedEnd) {\n return {\n changedTasks: [task],\n changedIds: [task.id],\n };\n }\n\n // Recalculate lags for the new position\n const updatedDependencies = recalculateIncomingLags(\n task,\n constrainedStart,\n constrainedEnd,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const recalculatedTask: Task = {\n ...task,\n startDate: constrainedStart.toISOString().split('T')[0],\n endDate: constrainedEnd.toISOString().split('T')[0],\n dependencies: updatedDependencies,\n };\n\n if (options?.skipCascade) {\n return {\n changedTasks: [recalculatedTask],\n changedIds: [recalculatedTask.id],\n };\n }\n\n // Cascade through dependency graph\n const cascadeResult = universalCascade(\n recalculatedTask,\n constrainedStart,\n constrainedEnd,\n snapshot,\n businessDays,\n weekendPredicate\n );\n\n const resultMap = new Map<string, Task>();\n resultMap.set(recalculatedTask.id, recalculatedTask);\n for (const t of cascadeResult) {\n resultMap.set(t.id, t);\n }\n\n const changedTasks = Array.from(resultMap.values());\n return {\n changedTasks,\n changedIds: changedTasks.map(t => t.id),\n };\n}\n\n/**\n * Full project schedule recalculation.\n * Recomputes the project against a continuously updated working snapshot.\n * Returns only tasks whose normalized state changed.\n */\nexport function recalculateProjectSchedule(\n snapshot: Task[],\n options?: ScheduleCommandOptions\n): ScheduleCommandResult {\n const businessDays = options?.businessDays ?? false;\n const weekendPredicate = options?.weekendPredicate;\n const workingMap = new Map(snapshot.map(task => [task.id, { ...task }]));\n const indegree = new Map<string, number>();\n const successorIdsByTask = new Map<string, string[]>();\n\n for (const task of snapshot) {\n indegree.set(task.id, 0);\n successorIdsByTask.set(task.id, []);\n }\n\n for (const task of snapshot) {\n for (const dep of task.dependencies ?? []) {\n if (!workingMap.has(dep.taskId)) {\n continue;\n }\n\n indegree.set(task.id, (indegree.get(task.id) ?? 0) + 1);\n successorIdsByTask.get(dep.taskId)?.push(task.id);\n }\n }\n\n const queue = snapshot\n .filter(task => (indegree.get(task.id) ?? 0) === 0)\n .map(task => task.id);\n\n while (queue.length > 0) {\n const currentId = queue.shift()!;\n\n for (const successorId of successorIdsByTask.get(currentId) ?? []) {\n const nextIndegree = (indegree.get(successorId) ?? 0) - 1;\n indegree.set(successorId, nextIndegree);\n\n if (nextIndegree !== 0) {\n continue;\n }\n\n const currentTask = workingMap.get(successorId);\n if (!currentTask || currentTask.locked || !currentTask.dependencies?.length) {\n queue.push(successorId);\n continue;\n }\n\n const duration = getTaskDuration(\n parseDateOnly(currentTask.startDate),\n parseDateOnly(currentTask.endDate),\n businessDays,\n weekendPredicate\n );\n\n let constrainedRange: { start: Date; end: Date } | null = null;\n\n for (const dep of currentTask.dependencies) {\n const predecessor = workingMap.get(dep.taskId);\n if (!predecessor) {\n continue;\n }\n\n const { predStart: predecessorStart, predEnd: predecessorEnd } = normalizePredecessorDates(predecessor, parseDateOnly);\n const constraintDate = calculateSuccessorDate(\n predecessorStart,\n predecessorEnd,\n dep.type,\n getDependencyLag(dep),\n businessDays,\n weekendPredicate\n );\n\n const candidateRange = dep.type === 'FS' || dep.type === 'SS'\n ? buildTaskRangeFromStart(constraintDate, duration, businessDays, weekendPredicate)\n : buildTaskRangeFromEnd(constraintDate, duration, businessDays, weekendPredicate);\n\n if (\n !constrainedRange ||\n candidateRange.start.getTime() > constrainedRange.start.getTime() ||\n (\n candidateRange.start.getTime() === constrainedRange.start.getTime() &&\n candidateRange.end.getTime() > constrainedRange.end.getTime()\n )\n ) {\n constrainedRange = candidateRange;\n }\n }\n\n if (!constrainedRange) {\n queue.push(successorId);\n continue;\n }\n\n workingMap.set(successorId, {\n ...currentTask,\n startDate: toIsoDate(constrainedRange.start),\n endDate: toIsoDate(constrainedRange.end),\n });\n queue.push(successorId);\n }\n }\n\n const parentsByDepth = snapshot\n .filter(task => isTaskParent(task.id, snapshot))\n .map(task => {\n let depth = 0;\n let current = task.parentId ? workingMap.get(task.parentId) : undefined;\n while (current) {\n depth++;\n current = current.parentId ? workingMap.get(current.parentId) : undefined;\n }\n return { taskId: task.id, depth };\n })\n .sort((left, right) => right.depth - left.depth);\n\n const workingTasks = () => Array.from(workingMap.values());\n\n for (const { taskId } of parentsByDepth) {\n const parent = workingMap.get(taskId);\n if (!parent || parent.locked) {\n continue;\n }\n\n const { startDate, endDate } = computeParentDates(taskId, workingTasks());\n workingMap.set(taskId, {\n ...parent,\n startDate: toIsoDate(startDate),\n endDate: toIsoDate(endDate),\n });\n }\n\n return createChangedResult(snapshot, Array.from(workingMap.values()));\n}\n","/**\n * Dependency validation and cycle detection.\n * Moved from dependencyUtils.ts — verbatim implementations.\n * Zero React/DOM/date-fns imports.\n */\n\nimport type { Task, DependencyError, ValidationResult } from './types';\nimport { areTasksHierarchicallyRelated } from './hierarchy';\n\n/**\n * Build adjacency list for dependency graph (task -> successors)\n */\nexport function buildAdjacencyList(tasks: Task[]): Map<string, string[]> {\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 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 * 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 invalid hierarchy links (ancestor <-> descendant)\n for (const task of tasks) {\n if (!task.dependencies) continue;\n\n for (const dep of task.dependencies) {\n if (!taskIds.has(dep.taskId)) {\n continue;\n }\n\n if (areTasksHierarchicallyRelated(task.id, dep.taskId, tasks)) {\n errors.push({\n type: 'constraint',\n taskId: task.id,\n message: `Dependencies between parent and child tasks are not allowed: ${dep.taskId} -> ${task.id}`,\n relatedTaskIds: [dep.taskId, task.id],\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","import type { Task } from '../types';\nimport { computeParentDates, computeParentProgress, isTaskParent } from '../core/scheduling';\nimport { normalizeTaskDates } from './dateUtils';\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 * Also normalizes task dates to ensure startDate is always before or equal to endDate.\n */\nexport function normalizeHierarchyTasks<T extends Task>(tasks: T[]): T[] {\n const orderedTasks = flattenHierarchy(tasks).map((task) => {\n // Normalize dates for all tasks (swap if endDate < startDate)\n const { startDate, endDate } = normalizeTaskDates(task.startDate, task.endDate);\n return { ...task, startDate: startDate as T['startDate'], endDate: endDate as T['endDate'] };\n }) 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, getWeekSpans, getWeekBlocks, getMonthBlocks, getYearSpans, type WeekBlock, type WeekSpan, type MonthBlock, type YearSpan } 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 /** View mode: 'day' renders individual day columns, 'week' renders 7-day week columns, 'month' renders one column per month */\n viewMode?: 'day' | 'week' | 'month';\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isCustomWeekend?: (date: Date) => boolean;\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/week columns\n * Bottom row: Day numbers (centered) in individual day columns OR week start day numbers\n *\n * Supports two view modes:\n * - day (default): each column = 1 day, shows month names + individual day numbers\n * - week: each column = 7 days, shows month names spanning week columns + week-start dates\n */\nconst TimeScaleHeader: React.FC<TimeScaleHeaderProps> = ({\n days,\n dayWidth,\n headerHeight,\n viewMode = 'day',\n isCustomWeekend,\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 // Week-view: blocks with variable width (split on month boundaries)\n const weekBlocks = useMemo(\n () => (viewMode === 'week' ? getWeekBlocks(days) : []),\n [days, viewMode]\n );\n\n // Week-view: month spans grouped over week-blocks (row 1 labels)\n const weekSpans = useMemo(\n () => (viewMode === 'week' ? getWeekSpans(days) : []),\n [days, viewMode]\n );\n\n // Calculate column widths for each block (for grid template)\n const weekColumnWidths = useMemo(\n () => weekBlocks.map(b => b.days * dayWidth),\n [weekBlocks, dayWidth]\n );\n\n // Calculate total width for grid template\n const weekGridTemplate = useMemo(\n () => weekColumnWidths.map(w => `${w}px`).join(' '),\n [weekColumnWidths]\n );\n\n // Month-view: one block per calendar month (row 2 columns)\n const monthBlocks = useMemo(\n () => (viewMode === 'month' ? getMonthBlocks(days) : []),\n [days, viewMode]\n );\n\n // Month-view: year spans over month blocks (row 1 labels)\n const yearSpans = useMemo(\n () => (viewMode === 'month' ? getYearSpans(days) : []),\n [days, viewMode]\n );\n\n // Month-view: grid template for row 2 (variable column widths = days * dayWidth)\n const monthGridTemplate = useMemo(\n () => monthBlocks.map(b => `${b.days * dayWidth}px`).join(' '),\n [monthBlocks, dayWidth]\n );\n\n // Separator positions — same Math.round formula as GridBackground to guarantee pixel alignment.\n // fullHeight=true → spans both header rows (thick boundary between spans in row 1).\n // fullHeight=false → spans row 2 only (thin sub-column divider, doesn't cut through row 1 spans).\n const separators = useMemo(() => {\n const result: Array<{ x: number; isThick: boolean; fullHeight: boolean }> = [];\n if (viewMode === 'day') {\n for (let i = 1; i < days.length; i++) {\n if (days[i].getUTCDate() === 1) {\n result.push({ x: Math.round(i * dayWidth), isThick: true, fullHeight: true });\n }\n }\n } else if (viewMode === 'week') {\n let dayIndex = 0;\n for (let i = 0; i < weekBlocks.length; i++) {\n if (i > 0) {\n const isMonth = weekBlocks[i - 1].startDate.getUTCMonth() !== weekBlocks[i].startDate.getUTCMonth();\n result.push({ x: Math.round(dayIndex * dayWidth), isThick: isMonth, fullHeight: isMonth });\n }\n dayIndex += weekBlocks[i].days;\n }\n } else if (viewMode === 'month') {\n let dayIndex = 0;\n for (let i = 0; i < monthBlocks.length; i++) {\n if (i > 0) {\n const isYear = monthBlocks[i].startDate.getUTCMonth() === 0;\n result.push({ x: Math.round(dayIndex * dayWidth), isThick: isYear, fullHeight: isYear });\n }\n dayIndex += monthBlocks[i].days;\n }\n }\n return result;\n }, [days, weekBlocks, monthBlocks, dayWidth, viewMode]);\n\n return (\n <div\n className=\"gantt-tsh-header\"\n style={{ height: `${headerHeight}px`, position: 'relative' }}\n >\n {/* Separator lines — pixel-aligned with GridBackground */}\n {separators.map((sep, i) => (\n <div\n key={`sep-${i}`}\n className={`gantt-tsh-separator${sep.isThick ? ' gantt-tsh-separator--thick' : ''}`}\n style={sep.fullHeight\n ? { left: `${sep.x}px`, top: 0, bottom: 0 }\n : { left: `${sep.x}px`, top: rowHeight, height: rowHeight }}\n />\n ))}\n\n {/* Month row - top */}\n <div\n className=\"gantt-tsh-monthRow\"\n style={{ height: `${rowHeight}px` }}\n >\n {viewMode === 'week' ? (\n // Week-view row 1: month names spanning week blocks\n weekSpans.map((span: WeekSpan, index: number) => (\n <div\n key={`wmonth-${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 ) : viewMode === 'month' ? (\n // Month-view row 1: year labels spanning all months of that year\n yearSpans.map((span: YearSpan, index: number) => (\n <div\n key={`year-${index}`}\n className=\"gantt-tsh-monthCell\"\n style={{ width: `${span.days * dayWidth}px` }}\n >\n {span.year.getUTCFullYear().toString()}\n </div>\n ))\n ) : (\n // Day-view row 1: month names spanning day columns (existing code)\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 )}\n </div>\n\n {/* Day/Week row - bottom */}\n <div\n className=\"gantt-tsh-dayRow\"\n style={{\n height: `${rowHeight}px`,\n gridTemplateColumns: viewMode === 'week'\n ? weekGridTemplate\n : viewMode === 'month'\n ? monthGridTemplate\n : dayGridTemplate,\n }}\n >\n {viewMode === 'week' ? (\n // Week-view row 2: week block start day numbers (variable width)\n weekBlocks.map((block, index) => {\n const prevBlock = weekBlocks[index - 1];\n const isMonthBoundary =\n index > 0 && prevBlock &&\n prevBlock.startDate.getUTCMonth() !== block.startDate.getUTCMonth();\n // Show date only for full weeks (7 days)\n const showDate = block.days === 7;\n return (\n <div\n key={`week-${index}`}\n className=\"gantt-tsh-dayCell gantt-tsh-weekCell\"\n >\n <span className=\"gantt-tsh-dayLabel\">\n {showDate ? String(block.startDate.getUTCDate()).padStart(2, '0') : ''}\n </span>\n </div>\n );\n })\n ) : viewMode === 'month' ? (\n // Month-view row 2: one column per month, shows abbreviated month name\n monthBlocks.map((block: MonthBlock, index: number) => {\n const MIN_DAYS_TO_SHOW_LABEL = 15;\n const showLabel = block.days >= MIN_DAYS_TO_SHOW_LABEL;\n const isYearBoundary = index > 0 && block.startDate.getUTCMonth() === 0;\n return (\n <div\n key={`mblock-${index}`}\n className=\"gantt-tsh-dayCell gantt-tsh-weekCell\"\n >\n <span className=\"gantt-tsh-dayLabel\">\n {showLabel\n ? (() => { const s = block.startDate.toLocaleString('ru-RU', { month: 'long', timeZone: 'UTC' }); return s.charAt(0).toUpperCase() + s.slice(1); })()\n : ''}\n </span>\n </div>\n );\n })\n ) : (\n // Day-view row 2: individual day numbers (existing code)\n days.map((day, index) => {\n const isWeekendDay = isCustomWeekend\n ? isCustomWeekend(day)\n : day.getUTCDay() === 0 || day.getUTCDay() === 6;\n const prevDay = days[index - 1];\n const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();\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 ${isWeekendDay ? 'gantt-tsh-weekendDay' : ''} ${isTodayDate ? 'gantt-tsh-today' : ''}`}>\n <span className=\"gantt-tsh-dayLabel\">{format(day, 'd')}</span>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n};\n\nexport default TimeScaleHeader;\n","'use client';\n\nimport React, { useMemo } from 'react';\nimport { parseUTCDate, formatDateRangeLabel, createCustomDayPredicate } from '../../utils/dateUtils';\nimport { calculateMilestoneGeometry, calculateTaskBar, pixelsToDate } from '../../utils/geometry';\nimport { isTaskExpired } from '../../utils/expired';\nimport { isMilestoneTask, normalizeTaskDatesForType } from '../../utils/taskType';\nimport { useTaskDrag } from '../../hooks/useTaskDrag';\nimport { isTaskParent, getChildren, getBusinessDaysCount } from '../../core/scheduling';\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. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => 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 /** Whether this row matches the active filter highlight */\n isFilterMatch?: boolean;\n /** Calculate duration in business days (excluding weekends) */\n businessDays?: boolean;\n /** Custom weekend configuration */\n customDays?: Array<{ date: Date; type: 'weekend' | 'workday' }>;\n /** Custom weekend predicate (overrides default Saturday/Sunday) */\n isWeekend?: (date: Date) => boolean;\n /** Disable task drag and resize (overrides task.locked) */\n disableTaskDrag?: 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: onTasksChange is intentionally excluded from this comparison because:\n * 1. The parent (GanttChart) wraps onTasksChange in useCallback for referential stability\n * 2. onTasksChange 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 onTasksChange —\n * callbacks excluded from comparison because GanttChart wraps them in useCallback).\n *\n * Excluding onTasksChange 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.type === nextProps.task.type &&\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 prevProps.isFilterMatch === nextProps.isFilterMatch &&\n prevProps.businessDays === nextProps.businessDays &&\n prevProps.customDays === nextProps.customDays &&\n prevProps.isWeekend === nextProps.isWeekend &&\n prevProps.disableTaskDrag === nextProps.disableTaskDrag\n // onTasksChange, 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, onTasksChange, onDragStateChange, rowIndex, allTasks, enableAutoSchedule, disableConstraints, overridePosition, onCascadeProgress, onCascade, divider, highlightExpiredTasks, isFilterMatch = false, businessDays, customDays, isWeekend, disableTaskDrag = false }) => {\n const defaultParentBarColor = '#782FC4';\n // Extract divider from task prop\n const { divider: taskDivider } = task;\n\n const normalizedTask = useMemo(() => normalizeTaskDatesForType(task), [task]);\n const milestone = useMemo(() => isMilestoneTask(normalizedTask), [normalizedTask]);\n\n // Parse dates as UTC\n const taskStartDate = useMemo(() => parseUTCDate(normalizedTask.startDate), [normalizedTask.startDate]);\n const taskEndDate = useMemo(() => parseUTCDate(normalizedTask.endDate), [normalizedTask.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 return isTaskExpired(normalizedTask);\n }, [normalizedTask.startDate, normalizedTask.endDate, normalizedTask.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 const milestoneGeometry = useMemo(\n () => calculateMilestoneGeometry(taskStartDate, monthStart, dayWidth),\n [taskStartDate, 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 // 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 const externalTaskNameColor = useMemo(() => {\n if (isExpired) {\n return 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)';\n }\n const baseColor = isParent\n ? (task.color || defaultParentBarColor)\n : (task.color || 'var(--gantt-task-bar-default-color)');\n return `color-mix(in srgb, ${baseColor} 40%, black)`;\n }, [defaultParentBarColor, isExpired, isParent, task.color]);\n\n // At 100% progress, tint the bar itself instead of rendering a fill overlay.\n const barStyle = useMemo(() => {\n const parentBarColor = task.color || defaultParentBarColor;\n if (isParent) {\n if (progressWidth >= 100) {\n const c = isExpired\n ? 'color-mix(in srgb, var(--gantt-expired-color) 40%, black)'\n : `color-mix(in srgb, ${parentBarColor} 40%, black)`;\n return { backgroundColor: c, '--gantt-parent-bar-color': c } as React.CSSProperties;\n }\n return { '--gantt-parent-bar-color': parentBarColor } as React.CSSProperties;\n }\n if (progressWidth >= 100) {\n return { backgroundColor: progressColor };\n }\n return { backgroundColor: barColor };\n }, [defaultParentBarColor, isExpired, isParent, progressWidth, barColor, progressColor, task.color]);\n\n // Handle drag end - call onTasksChange with updated task\n const handleDragEnd = (result: { id: string; startDate: Date; endDate: Date; updatedDependencies?: Task['dependencies'] }) => {\n const updatedTask: Task = {\n ...normalizedTask,\n startDate: result.startDate.toISOString(),\n endDate: result.endDate.toISOString(),\n ...(result.updatedDependencies !== undefined && { dependencies: result.updatedDependencies }),\n };\n onTasksChange?.([updatedTask]);\n };\n\n // Weekend predicate for business days calculation (must be before useTaskDrag)\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\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 disableTaskDrag,\n onCascadeProgress,\n onCascade,\n businessDays,\n weekendPredicate,\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 const displayMilestoneGeometry = useMemo(() => {\n // Milestones are always anchored to a single day cell even if some preview path\n // passes a wider width (for example, malformed input dates before normalization).\n const centerX = Math.round(displayLeft + dayWidth / 2);\n const halfSize = Math.round(milestoneGeometry.size / 2);\n return {\n centerX,\n left: centerX - halfSize,\n right: centerX + halfSize,\n size: milestoneGeometry.size,\n };\n }, [displayLeft, dayWidth, milestoneGeometry.size]);\n const visualLeft = milestone ? displayMilestoneGeometry.left : displayLeft;\n const visualWidth = milestone ? displayMilestoneGeometry.size : displayWidth;\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 ? (\n milestone\n ? pixelsToDate(displayLeft, monthStart, dayWidth)\n : pixelsToDate(displayLeft + displayWidth - dayWidth, monthStart, dayWidth)\n )\n : taskEndDate;\n\n const dateRangeLabel = formatDateRangeLabel(currentStartDate, currentEndDate);\n\n // Calculate duration in days (calendar or business)\n const durationDays = businessDays\n ? getBusinessDaysCount(currentStartDate, currentEndDate, weekendPredicate)\n : 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 // Parent bars have overflow: visible (for bracket ears), so threshold must be stricter:\n // \"X задач 100%\" ≈ 60–70px text + 16px padding = ~110px\n // Regular: \"15 д 100%\" ≈ 76px, \"1 д 100%\" ≈ 62px\n const estimatedTextWidth = isParent ? 120 : (durationDays >= 10 ? 76 : 62);\n const showProgressInside = !milestone && progressWidth > 0 && displayWidth > estimatedTextWidth;\n\n // Determine if duration fits inside the bar\n // For 1-day tasks: always show duration outside (too narrow)\n // Parent bars: child count label is longer — need more space\n const MIN_DURATION_WIDTH = isParent ? 80 : 50;\n const showDurationInside = !milestone && durationDays >= 2 && displayWidth > MIN_DURATION_WIDTH;\n\n return (\n <div\n data-filter-match={isFilterMatch ? 'true' : 'false'}\n className={`gantt-tr-row ${isFilterMatch ? 'gantt-tr-row-filter-match' : ''}`}\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' : ''} ${milestone ? 'gantt-tr-milestone' : ''}`}\n style={{\n left: `${visualLeft}px`,\n ...barStyle,\n ...(milestone\n ? {\n height: `${displayMilestoneGeometry.size}px`,\n width: `${displayMilestoneGeometry.size}px`,\n padding: 0,\n }\n : {\n width: `${visualWidth}px`,\n height: isParent ? 'var(--gantt-parent-bar-height, 14px)' : 'var(--gantt-task-bar-height)',\n }),\n cursor: dragHandleProps.style.cursor,\n userSelect: dragHandleProps.style.userSelect,\n }}\n onMouseDown={dragHandleProps.onMouseDown}\n >\n {!milestone && progressWidth > 0 && progressWidth < 100 && (\n <div\n className=\"gantt-tr-progressBar\"\n style={{\n width: `${progressWidth}%`,\n backgroundColor: progressColor,\n ...(isParent && {\n borderRadius: 'var(--gantt-parent-bar-radius, 8px) 0 0 0',\n }),\n }}\n />\n )}\n {!isParent && !milestone && <div className=\"gantt-tr-resizeHandle gantt-tr-resizeHandleLeft\" />}\n {showDurationInside && (\n <span className=\"gantt-tr-taskDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n )}\n {progressWidth > 0 && showProgressInside && (\n <span className=\"gantt-tr-progressText\">\n {progressWidth}%\n </span>\n )}\n {!isParent && !milestone && <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: `${visualLeft}px`\n }}\n >\n <span className=\"gantt-tr-dateLabel gantt-tr-dateLabelLeft\">\n {dateRangeLabel}\n </span>\n </div>\n {task.locked && (\n <svg\n className=\"gantt-tr-lockIcon\"\n style={{\n position: 'absolute',\n left: `${visualLeft - 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: `${visualLeft + Math.max(visualWidth, 20) - Math.min(6, Math.max(visualWidth, 20) / 2) + 8}px`,\n color: isParent ? (task.color || defaultParentBarColor) : barColor,\n }}\n >\n {!showDurationInside && !milestone && (\n <span className=\"gantt-tr-externalDuration\">\n {isParent ? getChildCountLabel(childCount) : `${durationDays} д`}\n </span>\n )}\n {progressWidth > 0 && !showProgressInside && (\n <span className=\"gantt-tr-externalProgress\">\n {progressWidth}%\n </span>\n )}\n <span\n className=\"gantt-tr-externalTaskName\"\n style={{ color: externalTaskNameColor }}\n >\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 * Calculate fixed-size milestone geometry centered on a single task day.\n */\nexport const calculateMilestoneGeometry = (\n taskDate: Date,\n monthStart: Date,\n dayWidth: number,\n size: number = 14\n): { centerX: number; left: number; right: number; size: number } => {\n const { left, width } = calculateTaskBar(taskDate, taskDate, monthStart, dayWidth);\n const centerX = Math.round(left + width / 2);\n const halfSize = Math.round(size / 2);\n\n return {\n centerX,\n left: centerX - halfSize,\n right: centerX + halfSize,\n size,\n };\n};\n\n/**\n * Resolve milestone connection points relative to the task day cell.\n * Anchors sit on the actual horizontal diamond vertices.\n */\nexport const calculateMilestoneConnectionBounds = (\n dayLeft: number,\n dayWidth: number,\n size: number = 14\n): { left: number; right: number } => {\n const halfDiagonal = Math.round(size / Math.SQRT2);\n const centerX = Math.round(dayLeft + dayWidth / 2);\n return {\n left: centerX - halfDiagonal,\n right: centerX + halfDiagonal,\n };\n};\n\ntype HorizontalGeometryTask = {\n startDate: string | Date;\n endDate: string | Date;\n type?: 'task' | 'milestone';\n};\n\n/**\n * Resolve horizontal task geometry with optional drag override.\n * Milestones always stay anchored to a single day even if an override carries a wider width.\n */\nexport const resolveTaskHorizontalGeometry = (\n task: HorizontalGeometryTask,\n monthStart: Date,\n dayWidth: number,\n override?: { left: number; width: number }\n): { left: number; right: number; centerX: number } => {\n const startDate = new Date(task.startDate);\n const endDate = new Date(task.endDate);\n\n if (task.type === 'milestone') {\n const size = 14;\n if (override) {\n const bounds = calculateMilestoneConnectionBounds(override.left, dayWidth, size);\n return {\n ...bounds,\n centerX: Math.round(override.left + dayWidth / 2),\n };\n }\n\n const bar = calculateTaskBar(startDate, startDate, monthStart, dayWidth);\n const bounds = calculateMilestoneConnectionBounds(bar.left, dayWidth, size);\n return {\n ...bounds,\n centerX: Math.round(bar.left + dayWidth / 2),\n };\n }\n\n if (override) {\n return {\n left: override.left,\n right: override.left + override.width,\n centerX: Math.round(override.left + override.width / 2),\n };\n }\n\n const bar = calculateTaskBar(startDate, endDate, monthStart, dayWidth);\n return {\n left: bar.left,\n right: bar.left + bar.width,\n centerX: Math.round(bar.left + bar.width / 2),\n };\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 * @param isCustomWeekend - Optional predicate for custom weekend logic (e.g., holidays, shift patterns)\n * @returns Array of weekend block objects with left position and width\n *\n * Example:\n * // Default behavior (Saturday/Sunday)\n * calculateWeekendBlocks(dateRange, dayWidth)\n *\n * // Custom weekends (holidays, shifted workdays)\n * const isCustomWeekend = createIsWeekendPredicate({\n * weekends: [new Date(Date.UTC(2026, 2, 8))], // March 8 holiday\n * workdays: [new Date(Date.UTC(2026, 2, 15))] // March 15 workday\n * });\n * calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend)\n */\nexport const calculateWeekendBlocks = (\n dateRange: Date[],\n dayWidth: number,\n isCustomWeekend?: (date: Date) => boolean\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 // Use custom predicate if provided, otherwise default Saturday/Sunday\n const isWeekend = isCustomWeekend\n ? isCustomWeekend(date)\n : date.getUTCDay() === 0 || date.getUTCDay() === 6;\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 // Same column: straight vertical line without chamfer.\n // This matters for stacked milestones where the diagonal corner looks wrong.\n if (fx === tx) {\n return `M ${fx} ${fy} V ${ty}`;\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 grid line positions for week-view mode.\n * Lines appear at every 7-day boundary (each week column edge).\n * Month boundaries are always rendered at the exact day position (day 1 of a new month),\n * even when the boundary falls in the middle of a week column.\n * No day-level lines; no weekend blocks.\n *\n * @param dateRange - Array of Date objects (from getMultiMonthDays, day-based)\n * @param dayWidth - Width of each day in pixels\n * @returns Array of grid line objects sorted by x position\n */\nexport const calculateWeekGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean }> => {\n // Import getWeekBlocks locally to avoid circular dependency\n const { getWeekBlocks } = require('./dateUtils');\n const blocks = getWeekBlocks(dateRange);\n\n const lines: Array<{ x: number; isMonthStart: boolean }> = [];\n let currentDayIndex = 0;\n\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n currentDayIndex += block.days;\n\n // Check if this block boundary is also a month boundary\n const blockEndMonth = dateRange[currentDayIndex - 1];\n const nextBlockMonth = currentDayIndex < dateRange.length\n ? dateRange[currentDayIndex]\n : null;\n\n const isMonthBoundary = nextBlockMonth &&\n blockEndMonth.getUTCMonth() !== nextBlockMonth.getUTCMonth();\n\n lines.push({\n x: Math.round(currentDayIndex * dayWidth),\n isMonthStart: isMonthBoundary || false,\n });\n }\n\n // Remove the last line if it's at the right edge (duplicates grid border)\n if (lines.length > 0 && lines[lines.length - 1].x === Math.round(dateRange.length * dayWidth)) {\n lines.pop();\n }\n\n return lines;\n};\n\n/**\n * Calculate grid line positions for month-view mode.\n * Thin line (isMonthStart=false) at each month boundary (1st of every month).\n * Thick line (isMonthStart=true) at each year boundary (1st of January).\n * No day-level or week-level lines.\n *\n * @param dateRange - Array of Date objects (from getMultiMonthDays)\n * @param dayWidth - Width of each day in pixels\n * @returns Array of grid line objects sorted by x position\n */\nexport const calculateMonthGridLines = (\n dateRange: Date[],\n dayWidth: number\n): Array<{ x: number; isMonthStart: boolean }> => {\n const lines: Array<{ x: number; isMonthStart: boolean }> = [];\n\n for (let i = 1; i < dateRange.length; i++) {\n const date = dateRange[i];\n // Линия только на 1-м числе месяца\n if (date.getUTCDate() === 1) {\n const x = Math.round(i * dayWidth);\n // Толстая линия на 1 января (граница года)\n const isYearBoundary = date.getUTCMonth() === 0;\n lines.push({ x, isMonthStart: isYearBoundary });\n }\n }\n\n return lines;\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","import type { Task } from '../types';\nimport { parseUTCDate } from './dateUtils';\n\n/**\n * Checks whether a task is behind the expected progress for the current date.\n * Uses the same progress-based rule as expired task highlighting in TaskRow.\n */\nexport const isTaskExpired = (\n task: Task | undefined,\n referenceDate: Date = new Date(),\n): boolean => {\n if (!task) return false;\n\n const actualProgress = task.progress ?? 0;\n if (actualProgress >= 100) return false;\n\n // Align the day boundary to local time, then compare using UTC-safe task dates.\n const today = new Date(Date.UTC(\n referenceDate.getFullYear(),\n referenceDate.getMonth(),\n referenceDate.getDate(),\n ));\n\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n\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 expectedProgress = (elapsed / duration) * 100;\n\n return actualProgress < expectedProgress;\n};\n","import { parseUTCDate } from './dateUtils';\n\nexport type TaskType = 'task' | 'milestone';\n\nexport type TaskWithType = {\n startDate: string | Date;\n endDate: string | Date;\n type?: TaskType;\n};\n\nexport const TASK_TYPE_DEFAULT = 'task';\n\nexport function getTaskType(task: { type?: TaskType }): TaskType {\n return task.type ?? TASK_TYPE_DEFAULT;\n}\n\nexport function isMilestoneTask(task: { type?: TaskType }): boolean {\n return getTaskType(task) === 'milestone';\n}\n\nfunction normalizeMilestoneStartDate(startDateInput: string | Date): string | Date {\n const parsedStartDate = parseUTCDate(startDateInput);\n\n if (startDateInput instanceof Date) {\n return new Date(Date.UTC(\n parsedStartDate.getUTCFullYear(),\n parsedStartDate.getUTCMonth(),\n parsedStartDate.getUTCDate()\n ));\n }\n\n return parsedStartDate.toISOString().split('T')[0];\n}\n\nexport function normalizeTaskDatesForType<\n TTask extends { startDate: string | Date; endDate: string | Date; type?: 'task' | 'milestone' }\n>(task: TTask): TTask {\n if (!isMilestoneTask(task)) {\n return task;\n }\n\n const startDate = normalizeMilestoneStartDate(task.startDate);\n\n return {\n ...task,\n endDate: startDate,\n } as TTask;\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 { isMilestoneTask, normalizeTaskDatesForType } from '../utils/taskType';\n// Domain scheduling functions\nimport {\n buildTaskRangeFromEnd,\n buildTaskRangeFromStart,\n calculateSuccessorDate,\n clampTaskRangeForIncomingFS,\n getDependencyLag,\n getTransitiveCascadeChain,\n moveTaskRange,\n recalculateIncomingLags,\n getChildren,\n isTaskParent,\n universalCascade,\n} from '../core/scheduling';\n\n// UI adapter functions (pixel-to-date conversion)\nimport { resolveDateRangeFromPixels, clampDateRangeForIncomingFS } from '../adapters/scheduling';\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, finalMode: 'move' | 'resize-left' | 'resize-right') => 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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => void;\n businessDays?: boolean;\n weekendPredicate?: (date: Date) => boolean;\n}\n\nlet globalActiveDrag: ActiveDragState | null = null;\nlet globalRafId: number | null = null;\n\nfunction getDayOffsetFromMonthStart(date: Date, monthStart: Date): number {\n return Math.round(\n (Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) -\n Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth(), monthStart.getUTCDate())) /\n (24 * 60 * 60 * 1000)\n );\n}\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, mode } = globalActiveDrag;\n globalActiveDrag = null;\n onComplete(currentLeft, currentWidth, mode);\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 // For milestones, force width to single day regardless of stored dates\n const draggedTask = allTasks.find(t => t.id === activeDrag.taskId);\n const effectiveWidth = draggedTask && isMilestoneTask(draggedTask) ? dayWidth : initialWidth;\n\n let newLeft = initialLeft;\n let newWidth = effectiveWidth;\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 // Incoming dependency lag is editable by dragging the successor itself.\n // Do not clamp successor movement/resize by its current dependency dates;\n // the new lag will be recomputed from the final dates on drop.\n\n if (activeDrag.businessDays && activeDrag.weekendPredicate && draggedTask) {\n const previewRange = clampDateRangeForIncomingFS(\n draggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n activeDrag.monthStart,\n dayWidth,\n draggedTask,\n true,\n activeDrag.weekendPredicate\n ),\n allTasks,\n mode,\n true,\n activeDrag.weekendPredicate\n );\n const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);\n const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);\n newLeft = Math.round(alignedStartDay * dayWidth);\n newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);\n } else if (draggedTask) {\n const previewRange = clampDateRangeForIncomingFS(\n draggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n activeDrag.monthStart,\n dayWidth,\n draggedTask\n ),\n allTasks,\n mode\n );\n const alignedStartDay = getDayOffsetFromMonthStart(previewRange.start, activeDrag.monthStart);\n const alignedEndDay = getDayOffsetFromMonthStart(previewRange.end, activeDrag.monthStart);\n newLeft = Math.round(alignedStartDay * dayWidth);\n newWidth = Math.round((alignedEndDay - alignedStartDay + 1) * dayWidth);\n }\n\n // Milestone: force single-day width after all date recalculations\n if (draggedTask && isMilestoneTask(draggedTask)) {\n newWidth = dayWidth;\n }\n\n // ── Universal preview cascade ──────────────────────────────────────────\n // Same algorithm as handleComplete — converts pixels→dates, runs\n // universalCascade, converts dates→pixels for overrides.\n\n // Universal preview: convert pixels → dates → universalCascade → pixels\n if (!activeDrag.disableConstraints && activeDrag.onCascadeProgress) {\n const { dayWidth, monthStart: mStart, taskId: dragId } = activeDrag;\n const originalDraggedTask = draggedTask ?? allTasks.find(t => t.id === dragId);\n const previewRange = originalDraggedTask\n ? clampDateRangeForIncomingFS(\n originalDraggedTask,\n resolveDateRangeFromPixels(\n mode,\n newLeft,\n newWidth,\n mStart,\n dayWidth,\n originalDraggedTask,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n ),\n allTasks,\n mode,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n )\n : (() => {\n const previewStartDay = Math.round(newLeft / dayWidth);\n const previewEndDay = previewStartDay + Math.round(newWidth / dayWidth) - 1;\n return {\n start: new Date(Date.UTC(\n mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate() + previewStartDay\n )),\n end: new Date(Date.UTC(\n mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate() + previewEndDay\n )),\n };\n })();\n const previewStartDate = previewRange.start;\n const isMilestone = originalDraggedTask ? isMilestoneTask(originalDraggedTask) : false;\n const previewEndDate = isMilestone ? previewRange.start : previewRange.end;\n\n const movedTaskData = originalDraggedTask ?? { id: dragId, name: '', startDate: '', endDate: '' };\n const cascadeResult = universalCascade(\n { ...movedTaskData, startDate: previewStartDate.toISOString(), endDate: previewEndDate.toISOString() },\n previewStartDate,\n previewEndDate,\n allTasks,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n );\n\n const mergedPreviewTasks = allTasks.map(task => {\n const previewTask = cascadeResult.find(candidate => candidate.id === task.id);\n return previewTask ?? task;\n });\n\n const previewTasks = cascadeResult.map(task => {\n const previewStart = new Date(task.startDate as string);\n const previewEnd = new Date(task.endDate as string);\n return {\n ...task,\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n previewStart,\n previewEnd,\n mergedPreviewTasks,\n activeDrag.businessDays,\n activeDrag.weekendPredicate\n ),\n }),\n };\n });\n\n // Convert cascaded tasks → pixel overrides\n const overrides = new Map<string, { left: number; width: number }>();\n // Always include the dragged task itself\n overrides.set(dragId, { left: newLeft, width: newWidth });\n\n for (const task of cascadeResult) {\n if (task.id === dragId) continue;\n const taskStart = new Date(task.startDate as string);\n const taskEnd = new Date(task.endDate as string);\n const startOff = Math.round(\n (Date.UTC(taskStart.getUTCFullYear(), taskStart.getUTCMonth(), taskStart.getUTCDate()) -\n Date.UTC(mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n const endOff = Math.round(\n (Date.UTC(taskEnd.getUTCFullYear(), taskEnd.getUTCMonth(), taskEnd.getUTCDate()) -\n Date.UTC(mStart.getUTCFullYear(), mStart.getUTCMonth(), mStart.getUTCDate()))\n / (24 * 60 * 60 * 1000)\n );\n overrides.set(task.id, {\n left: Math.round(startOff * dayWidth),\n width: Math.round((endOff - startOff + 1) * dayWidth),\n });\n }\n\n activeDrag.onCascadeProgress(overrides, previewTasks);\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?: (\n overrides: Map<string, { left: number; width: number }>,\n previewTasks?: Task[]\n ) => 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 /** When true, drag is disabled globally for all tasks (shows grab cursor instead of not-allowed) */\n disableTaskDrag?: boolean;\n /** If true, dependency cascade calculations skip weekends */\n businessDays?: boolean;\n /** Function that returns true for weekends (for businessDays mode) */\n weekendPredicate?: (date: Date) => 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 locked = false,\n disableTaskDrag = false,\n businessDays = true,\n weekendPredicate,\n } = options;\n const rawHookTask = allTasks.find(t => t.id === taskId);\n const hookTask = rawHookTask ? normalizeTaskDatesForType(rawHookTask) : undefined;\n const hookTaskIsMilestone = hookTask ? isMilestoneTask(hookTask) : false;\n\n // Track if this hook instance owns the current global drag\n const isOwnerRef = useRef<boolean>(false);\n const effectiveLocked = locked || disableTaskDrag;\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 = hookTaskIsMilestone\n ? 0\n : 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, hookTaskIsMilestone]);\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, finalMode: 'move' | 'resize-left' | 'resize-right') => {\n const wasOwner = isOwnerRef.current;\n isOwnerRef.current = false;\n\n const currentTaskRaw = allTasks.find(t => t.id === taskId);\n const currentTask = currentTaskRaw ? normalizeTaskDatesForType(currentTaskRaw) : undefined;\n const finalRange = currentTask\n ? clampDateRangeForIncomingFS(\n currentTask,\n resolveDateRangeFromPixels(\n finalMode,\n finalLeft,\n finalWidth,\n monthStart,\n dayWidth,\n currentTask,\n businessDays,\n weekendPredicate\n ),\n allTasks,\n finalMode,\n businessDays,\n weekendPredicate\n )\n : (() => {\n const dayOffset = Math.round(finalLeft / dayWidth);\n const durationDays = Math.round(finalWidth / dayWidth) - 1;\n return {\n start: new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n )),\n end: new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset + durationDays\n )),\n };\n })();\n\n const newStartDate = finalRange.start;\n const newEndDate = currentTask && isMilestoneTask(currentTask)\n ? finalRange.start\n : finalRange.end;\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 // Skip if position didn't actually change (e.g. click without drag)\n const startUnchanged = newStartDate.getTime() === Date.UTC(\n initialStartDate.getUTCFullYear(), initialStartDate.getUTCMonth(), initialStartDate.getUTCDate()\n );\n const baselineEndDate = hookTaskIsMilestone ? initialStartDate : initialEndDate;\n const endUnchanged = newEndDate.getTime() === Date.UTC(\n baselineEndDate.getUTCFullYear(), baselineEndDate.getUTCMonth(), baselineEndDate.getUTCDate()\n );\n if (startUnchanged && endUnchanged) {\n // Reset position from dates (in case pixel rounding drifted)\n const { left, width } = getInitialPosition();\n setCurrentLeft(left);\n setCurrentWidth(width);\n return;\n }\n\n if (!disableConstraints && onCascade && allTasks.length > 0) {\n // Hard mode with onCascade: use universalCascade for all cases\n // (parent drag, child drag, root task drag — all handled uniformly)\n const draggedTaskData = currentTask;\n\n const movedTask: Task = {\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, businessDays, weekendPredicate),\n }),\n };\n\n const cascadeResult = universalCascade(movedTask, newStartDate, newEndDate, allTasks, businessDays, weekendPredicate);\n\n if (cascadeResult.length > 0) {\n onCascade([movedTask, ...cascadeResult]);\n return; // Don't call onDragEnd — cascade covers the dragged task too\n }\n\n // No dependent tasks to cascade — still call onCascade with just the moved task\n // so the state update is consistent\n onCascade([movedTask]);\n return;\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 updatedDependencies = currentTask?.dependencies\n ? recalculateIncomingLags(currentTask, newStartDate, newEndDate, allTasks, businessDays, weekendPredicate)\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 }, [\n dayWidth,\n monthStart,\n onDragEnd,\n onDragStateChange,\n taskId,\n disableConstraints,\n onCascade,\n allTasks,\n businessDays,\n weekendPredicate,\n initialStartDate,\n initialEndDate,\n hookTaskIsMilestone,\n ]);\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 (effectiveLocked) 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 if (currentTask && isMilestoneTask(currentTask)) {\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 businessDays,\n weekendPredicate,\n };\n }, [edgeZoneWidth, currentLeft, currentWidth, dayWidth, monthStart, taskId, onDragStateChange, handleProgress, handleComplete, handleCancel, allTasks, disableConstraints, onCascadeProgress, onCascade, effectiveLocked]);\n\n /**\n * Get cursor style based on current position\n */\n const getCursorStyle = useCallback((): string => {\n if (disableTaskDrag) return 'grab'; // Global disable - allow pan\n if (locked) return 'not-allowed'; // Task-specific locked\n if (isDragging) {\n return 'grabbing';\n }\n return 'grab';\n }, [disableTaskDrag, 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","/**\n * UI adapter: converts pixel coordinates to date ranges for drag interactions.\n * @module adapters/scheduling\n *\n * These functions bridge the chart's pixel-space (left, width, dayWidth)\n * with the scheduling domain's date-space. They depend on core scheduling\n * primitives but are NOT part of the domain core themselves.\n */\n\nimport type { Task } from '../../core/scheduling/types';\nimport {\n moveTaskRange,\n buildTaskRangeFromStart,\n buildTaskRangeFromEnd,\n} from '../../core/scheduling/commands';\nimport {\n alignToWorkingDay,\n getBusinessDaysCount,\n} from '../../core/scheduling/dateMath';\nimport { clampTaskRangeForIncomingFS } from '../../core/scheduling/commands';\n\n/**\n * Convert pixel coordinates to a date range, applying business-day alignment\n * when businessDays mode is active. This is the pure scheduling core of\n * drag-to-date conversion.\n *\n * Extracted from useTaskDrag.ts resolveDraggedRange.\n */\nexport function resolveDateRangeFromPixels(\n mode: 'move' | 'resize-left' | 'resize-right',\n left: number,\n width: number,\n monthStart: Date,\n dayWidth: number,\n task: Task,\n businessDays?: boolean,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n const dayOffset = Math.round(left / dayWidth);\n const rawStartDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + dayOffset\n ));\n const rawEndOffset = dayOffset + Math.round(width / dayWidth) - 1;\n const rawEndDate = new Date(Date.UTC(\n monthStart.getUTCFullYear(),\n monthStart.getUTCMonth(),\n monthStart.getUTCDate() + rawEndOffset\n ));\n const isMilestone = task.type === 'milestone';\n\n // Milestone type has priority over incoming date span.\n // During drag, milestones are always treated as zero-duration (single date).\n if (isMilestone) {\n const anchorDate = mode === 'resize-right' ? rawEndDate : rawStartDate;\n if (businessDays && weekendPredicate) {\n const originalAnchor = mode === 'resize-right'\n ? new Date(task.endDate as string)\n : new Date(task.startDate as string);\n const snapDirection: 1 | -1 = anchorDate.getTime() >= originalAnchor.getTime() ? 1 : -1;\n const alignedDate = alignToWorkingDay(anchorDate, snapDirection, weekendPredicate);\n return { start: alignedDate, end: alignedDate };\n }\n return { start: anchorDate, end: anchorDate };\n }\n\n if (!(businessDays && weekendPredicate)) {\n return { start: rawStartDate, end: rawEndDate };\n }\n\n if (mode === 'move') {\n const originalStart = new Date(task.startDate as string);\n const snapDirection = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;\n return moveTaskRange(\n task.startDate,\n task.endDate,\n rawStartDate,\n true,\n weekendPredicate,\n snapDirection\n );\n }\n\n if (mode === 'resize-right') {\n const fixedStart = new Date(task.startDate as string);\n const originalEnd = new Date(task.endDate as string);\n const snapDirection: 1 | -1 = rawEndDate.getTime() >= originalEnd.getTime() ? 1 : -1;\n const alignedEnd = alignToWorkingDay(rawEndDate, snapDirection, weekendPredicate);\n const duration = Math.max(1, getBusinessDaysCount(fixedStart, alignedEnd, weekendPredicate));\n return buildTaskRangeFromStart(fixedStart, duration, true, weekendPredicate);\n }\n\n const fixedEnd = new Date(task.endDate as string);\n const originalStart = new Date(task.startDate as string);\n const snapDirection: 1 | -1 = rawStartDate.getTime() >= originalStart.getTime() ? 1 : -1;\n const alignedStart = alignToWorkingDay(rawStartDate, snapDirection, weekendPredicate);\n const duration = Math.max(1, getBusinessDaysCount(alignedStart, fixedEnd, weekendPredicate));\n return buildTaskRangeFromEnd(fixedEnd, duration, true, weekendPredicate);\n}\n\n/**\n * Clamp a proposed date range based on incoming FS dependencies.\n * For resize-right mode, returns range unchanged (only start is clamped).\n *\n * Extracted from useTaskDrag.ts clampDraggedRangeForIncomingFS.\n */\nexport function clampDateRangeForIncomingFS(\n task: Task,\n range: { start: Date; end: Date },\n allTasks: Task[],\n mode: 'move' | 'resize-left' | 'resize-right',\n businessDays?: boolean,\n weekendPredicate?: (date: Date) => boolean\n): { start: Date; end: Date } {\n if (mode === 'resize-right') {\n return range;\n }\n\n return clampTaskRangeForIncomingFS(\n task,\n range.start,\n range.end,\n allTasks,\n businessDays,\n weekendPredicate\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, calculateWeekGridLines, calculateMonthGridLines } 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 /** View mode: 'day' renders per-day lines with weekend blocks, 'week' renders per-week lines only, 'month' renders per-month lines only */\n viewMode?: 'day' | 'week' | 'month';\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isCustomWeekend?: (date: Date) => boolean;\n}\n\n/**\n * Custom comparison function for React.memo\n *\n * Performance optimization: Re-renders when dateRange length, dayWidth, totalHeight, or viewMode change.\n * Returns true (skip re-render) only when all four 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 prevProps.viewMode === nextProps.viewMode &&\n prevProps.isCustomWeekend === nextProps.isCustomWeekend\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 (day-view only)\n * - React.memo optimization for performance\n * - Pointer events disabled (clicks pass through to tasks)\n *\n * View modes:\n * - day (default): per-day grid lines + weekend background blocks\n * - week: per-week grid lines only (no weekend blocks, lines every 7 days)\n */\nconst GridBackground: React.FC<GridBackgroundProps> = React.memo(\n ({ dateRange, dayWidth, totalHeight, viewMode = 'day', isCustomWeekend }) => {\n // Week-view: grid lines at each 7-day boundary\n const weekGridLines = useMemo(() => {\n if (viewMode !== 'week') return [];\n return calculateWeekGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Day-view: grid line positions per day (existing logic)\n const gridLines = useMemo<GridLine[]>(() => {\n if (viewMode === 'week' || viewMode === 'month') return [];\n return calculateGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Month-view: grid lines at each month/year boundary\n const monthGridLines = useMemo(() => {\n if (viewMode !== 'month') return [];\n return calculateMonthGridLines(dateRange, dayWidth);\n }, [dateRange, dayWidth, viewMode]);\n\n // Weekend background blocks: only in day-view (locked decision from RESEARCH.md)\n const weekendBlocks = useMemo(() => {\n if (viewMode === 'week' || viewMode === 'month') return []; // No weekend highlighting in week/month-view\n return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);\n }, [dateRange, dayWidth, viewMode, isCustomWeekend]);\n\n // Calculate total grid width (formula must not change — Pitfall 3)\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) — day-view only */}\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 {viewMode === 'week' ? (\n // Week-view: one line per week column boundary\n weekGridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : 'gantt-gb-weekSeparator';\n return (\n <div\n key={`wgridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{ left: `${line.x}px` }}\n />\n );\n })\n ) : viewMode === 'month' ? (\n // Month-view: thin line at each month boundary, thick at year boundary\n monthGridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : 'gantt-gb-weekSeparator';\n return (\n <div\n key={`mgridline-${index}`}\n className={`gantt-gb-gridLine ${lineClass}`}\n style={{ left: `${line.x}px` }}\n />\n );\n })\n ) : (\n // Day-view: existing code (unchanged)\n gridLines.map((line, index) => {\n const lineClass = line.isMonthStart\n ? 'gantt-gb-monthSeparator'\n : line.isWeekStart\n ? 'gantt-gb-weekSeparator'\n : 'gantt-gb-dayLine';\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 )}\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 { calculateDependencyPath, resolveTaskHorizontalGeometry } from '../../utils/geometry';\nimport { isMilestoneTask } from '../../utils/taskType';\nimport { getAllDependencyEdges, detectCycles } from '../../utils/dependencyUtils';\nimport './DependencyLines.css';\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 businessDays?: boolean;\n weekendPredicate?: (date: Date) => boolean;\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 businessDays = true,\n weekendPredicate,\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; centerX: 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 // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);\n\n indices.set(task.id, index);\n positions.set(task.id, {\n left: computed.left,\n right: computed.right,\n centerX: computed.centerX,\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 // Use real-time pixel override if available (during drag)\n const override = dragOverrides?.get(task.id);\n const computed = resolveTaskHorizontalGeometry(task, monthStart, dayWidth, override);\n\n // Store virtual position using ancestor's rowTop\n positions.set(task.id, {\n left: computed.left,\n right: computed.right,\n centerX: computed.centerX,\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 taskMap = new Map(tasksForEdges.map(task => [task.id, task]));\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 const predecessorTask = taskMap.get(edge.predecessorId);\n const successorTask = taskMap.get(edge.successorId);\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 let fromX = predecessorTask && isMilestoneTask(predecessorTask)\n ? predecessor.centerX\n : (edge.type === 'SS' || edge.type === 'SF')\n ? predecessor.left\n : predecessor.right;\n\n const toX = successorTask && isMilestoneTask(successorTask)\n ? successor.centerX\n : (edge.type === 'FF' || edge.type === 'SF')\n ? successor.right\n : successor.left;\n\n const stackedMilestonesSameDay = Boolean(\n predecessorTask &&\n successorTask &&\n isMilestoneTask(predecessorTask) &&\n isMilestoneTask(successorTask) &&\n edge.lag === 0 &&\n new Date(predecessorTask.startDate).toISOString().split('T')[0] ===\n new Date(successorTask.startDate).toISOString().split('T')[0] &&\n predecessor.rowTop !== successor.rowTop &&\n edge.type === 'FS'\n );\n\n const finalToX = stackedMilestonesSameDay\n ? Math.round((predecessor.centerX + successor.centerX) / 2)\n : toX;\n if (stackedMilestonesSameDay) {\n fromX = finalToX;\n }\n const arrivesFromRight = edge.type === 'FF' || edge.type === 'SF';\n\n const from = { x: fromX, y: fromY };\n const to = { x: finalToX, 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 lines.push({\n id: `${edge.predecessorId}-${edge.successorId}-${edge.type}`,\n path,\n hasCycle,\n lag: edge.lag,\n fromX,\n toX: finalToX,\n fromY,\n reverseOrder,\n isVirtual,\n });\n }\n\n return lines;\n }, [tasks, allTasks, taskPositions, taskIndices, cycleInfo, collapsedParentIds]);\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 data-testid=\"dependency-lines-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 type { CustomDayConfig } from '../../utils/dateUtils';\nimport { createCustomDayPredicate } from '../../utils/dateUtils';\nimport { validateDependencies, calculateSuccessorDate, buildTaskRangeFromEnd, buildTaskRangeFromStart, getTaskDuration, isTaskParent, areTasksHierarchicallyRelated, getChildren } from '../../core/scheduling';\nimport { normalizeHierarchyTasks } from '../../utils/hierarchyOrder';\nimport { getVisibleReorderPosition } from '../../utils/taskListReorder';\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 type { TaskListColumn } from './columns/types';\nimport { createBuiltInColumns, BUILT_IN_COLUMN_WIDTHS } from './columns/createBuiltInColumns';\nimport { resolveTaskListColumns } from './columns/resolveTaskListColumns';\nimport type { TaskListColumn as NewTaskListColumn } from './columns/types';\nimport './TaskList.css';\n\nexport { LINK_TYPE_ICONS };\n\nconst LINK_TYPE_ORDER: LinkType[] = ['FS', 'SS', 'FF', 'SF'];\ntype DependencyPickMode = 'predecessor' | 'successor';\nconst MIN_TASK_LIST_WIDTH = 530;\n\nconst BUILT_IN_CSS_CLASSES: Record<string, string> = {\n number: 'gantt-tl-cell-number',\n name: 'gantt-tl-cell-name',\n startDate: 'gantt-tl-cell-date',\n endDate: 'gantt-tl-cell-date',\n duration: 'gantt-tl-cell-duration',\n progress: 'gantt-tl-cell-progress',\n};\n\n/**\n * Get all descendant tasks of a parent task (recursively).\n * Returns an array of all tasks where task.parentId is in the parent chain.\n *\n * @param parentId - ID of the parent task\n * @param tasks - All tasks array\n * @returns Array of descendant tasks (not including the parent itself)\n */\nfunction getAllDescendants(parentId: string, tasks: Task[]): Task[] {\n const descendants: Task[] = [];\n const visited = new Set<string>();\n\n function collectChildren(taskId: string) {\n if (visited.has(taskId)) return;\n visited.add(taskId);\n\n const children = getChildren(taskId, tasks);\n for (const child of children) {\n descendants.push(child);\n collectChildren(child.id);\n }\n }\n\n collectChildren(parentId);\n return descendants;\n}\n\nfunction duplicateTaskSubtree(anchorTaskId: string, orderedTasks: Task[]): Task[] {\n const anchorTask = orderedTasks.find(task => task.id === anchorTaskId);\n if (!anchorTask) return orderedTasks;\n\n const descendants = getAllDescendants(anchorTaskId, orderedTasks);\n const sourceIds = new Set([anchorTaskId, ...descendants.map(task => task.id)]);\n const sourceSubtree = orderedTasks.filter(task => sourceIds.has(task.id));\n const cloneIdMap = new Map(sourceSubtree.map(task => [task.id, crypto.randomUUID()]));\n\n const clonedSubtree = sourceSubtree.map(task => {\n const clonedDependencies = task.dependencies\n ?.map(dep => ({\n ...dep,\n taskId: cloneIdMap.get(dep.taskId) ?? dep.taskId,\n }));\n\n return {\n ...task,\n id: cloneIdMap.get(task.id)!,\n name: task.id === anchorTaskId ? `${task.name} (копия)` : task.name,\n parentId: task.parentId ? (cloneIdMap.get(task.parentId) ?? task.parentId) : undefined,\n dependencies: clonedDependencies,\n };\n });\n\n const anchorIndex = orderedTasks.findIndex(task => task.id === anchorTaskId);\n const insertIndex = anchorIndex + sourceSubtree.length;\n return [\n ...orderedTasks.slice(0, insertIndex),\n ...clonedSubtree,\n ...orderedTasks.slice(insertIndex),\n ];\n}\n\n/**\n * Вычисляет иерархический номер задачи на основе позиции в списке visibleTasks.\n * Корневые задачи: 1, 2, 3...\n * Дочерние задачи: 1.1, 1.2, 2.1, 2.1.1 и т.д.\n *\n * @param tasks - Массив видимых задач (уже отсортированных в иерархическом порядке)\n * @param taskIndex - Индекс задачи в массиве visibleTasks\n * @returns Иерархический номер в виде строки\n */\nfunction getTaskNumber(tasks: Task[], taskIndex: number): string {\n const task = tasks[taskIndex];\n if (!task) return '';\n\n // Если это корневая задача (нет parentId)\n if (!task.parentId) {\n // Найти порядковый номер среди корневых задач\n let rootIndex = 0;\n for (let i = 0; i < taskIndex; i++) {\n if (!tasks[i].parentId) {\n rootIndex++;\n }\n }\n return String(rootIndex + 1);\n }\n\n // Для дочерней задачи - найти родительский номер\n const parentIndex = tasks.findIndex(t => t.id === task.parentId);\n if (parentIndex === -1) {\n // Родитель не найден - fallback на плоский номер\n return String(taskIndex + 1);\n }\n\n const parentNumber = getTaskNumber(tasks, parentIndex);\n\n // Найти порядковый номер среди детей этого родителя\n let siblingIndex = 0;\n for (let i = 0; i < taskIndex; i++) {\n if (tasks[i].parentId === task.parentId) {\n siblingIndex++;\n }\n }\n\n return `${parentNumber}.${siblingIndex + 1}`;\n}\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. Values below MIN_TASK_LIST_WIDTH are clamped. */\n taskListWidth?: number;\n /** Callback when tasks are modified via inline edit. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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 /** Show right-side shadow when chart content is horizontally scrolled */\n hasRightShadow?: 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 /** Custom day configurations for date picker */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate for date picker */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях */\n businessDays?: boolean;\n /** Task IDs highlighted by the active filter */\n highlightedTaskIds?: Set<string>;\n /** Filter mode: 'highlight' shows yellow highlight on matches, 'hide' hides non-matching tasks */\n filterMode?: 'highlight' | 'hide';\n /** Task IDs that match the filter (used for hide mode). When undefined, no filtering is applied */\n filteredTaskIds?: Set<string>;\n /** Whether filter is currently active (needed to distinguish \"no filter\" from \"filter with no matches\") */\n isFilterActive?: boolean;\n /** Additional columns to display after built-in columns */\n additionalColumns?: TaskListColumn<any>[];\n}\n\ninterface PendingInsertState {\n anchorTaskId: string;\n insertAfterTaskId: string;\n parentId?: string;\n startDate: string | Date;\n endDate: string | Date;\n nestingDepth: number;\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, Duration, Progress, 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 = MIN_TASK_LIST_WIDTH,\n onTasksChange,\n selectedTaskId,\n onTaskSelect,\n show = true,\n hasRightShadow = false,\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 customDays,\n isWeekend,\n businessDays,\n highlightedTaskIds = new Set(),\n filterMode = 'highlight',\n filteredTaskIds = new Set(),\n isFilterActive = false,\n additionalColumns,\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(() => {\n return normalizeHierarchyTasks(tasks);\n }, [tasks]);\n\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\n\n // Filter tasks to hide children of collapsed parents.\n // Checks the full ancestor chain so grandchildren are hidden when any ancestor is collapsed.\n const visibleTasks = useMemo(() => {\n const parentMap = new Map(orderedTasks.map(t => [t.id, (t as any).parentId as string | undefined]));\n\n function isAnyAncestorCollapsed(parentId: string | undefined): boolean {\n let current = parentId;\n while (current) {\n if (collapsedParentIds.has(current)) return true;\n current = parentMap.get(current);\n }\n return false;\n }\n\n let tasks = orderedTasks.filter(task => !isAnyAncestorCollapsed((task as any).parentId));\n\n // In 'hide' mode with active filter, only show matching tasks\n if (filterMode === 'hide' && isFilterActive) {\n tasks = tasks.filter(task => filteredTaskIds.has(task.id));\n }\n\n return tasks;\n }, [orderedTasks, collapsedParentIds, filterMode, filteredTaskIds, isFilterActive]);\n\n const totalHeight = useMemo(\n () => visibleTasks.length * rowHeight,\n [visibleTasks.length, rowHeight]\n );\n const visibleTaskNumberMap = useMemo(\n () =>\n Object.fromEntries(\n visibleTasks.map((task, index) => [task.id, String(getTaskNumber(visibleTasks, index))])\n ) as Record<string, string>,\n [visibleTasks]\n );\n\n // Оригинальные номера задач на основе полного списка (до фильтрации)\n // Используются для сохранения нумерации при скрытии задач\n const originalTaskNumberMap = useMemo(\n () => {\n const numberMap = new Map<string, string>();\n for (let i = 0; i < orderedTasks.length; i++) {\n numberMap.set(orderedTasks[i].id, getTaskNumber(orderedTasks, i));\n }\n return Object.fromEntries(numberMap) as Record<string, string>;\n },\n [orderedTasks]\n );\n\n // Compute nesting depth for each task (0 = root, 1 = child, 2 = grandchild, etc.)\n const nestingDepthMap = useMemo(() => {\n const depthMap = new Map<string, number>();\n const taskById = new Map(tasks.map(t => [t.id, t]));\n\n function getDepth(taskId: string): number {\n if (depthMap.has(taskId)) return depthMap.get(taskId)!;\n const task = taskById.get(taskId);\n if (!task || !(task as any).parentId || !taskById.has((task as any).parentId)) {\n depthMap.set(taskId, 0);\n return 0;\n }\n const depth = getDepth((task as any).parentId) + 1;\n depthMap.set(taskId, depth);\n return depth;\n }\n\n for (const task of tasks) {\n getDepth(task.id);\n }\n return depthMap;\n }, [tasks]);\n\n // For each child task, determine if it's the last visible child of its parent\n const lastChildIds = useMemo(() => {\n const last = new Set<string>();\n const seenParents = new Set<string>();\n for (let i = visibleTasks.length - 1; i >= 0; i--) {\n const t = visibleTasks[i] as Task;\n if (t.parentId && !seenParents.has(t.parentId)) {\n last.add(t.id);\n seenParents.add(t.parentId);\n }\n }\n return last;\n }, [visibleTasks]);\n\n const visibleParentIds = useMemo(() => {\n const parentIds = new Set<string>();\n for (const task of visibleTasks) {\n if (task.parentId) parentIds.add(task.parentId);\n }\n return parentIds;\n }, [visibleTasks]);\n\n // For each visible task, determine whether each ancestor line above the direct parent\n // should continue through the full row or terminate at the row midpoint.\n const ancestorLineModesMap = useMemo(() => {\n const taskById = new Map(tasks.map(t => [t.id, t]));\n\n const isDescendantOf = (taskId: string, ancestorId: string): boolean => {\n let current: any = taskById.get(taskId);\n while (current?.parentId && taskById.has(current.parentId)) {\n if (current.parentId === ancestorId) return true;\n current = taskById.get(current.parentId);\n }\n return false;\n };\n\n const map = new Map<string, (\"full\" | \"half\")[]>();\n for (let index = 0; index < visibleTasks.length; index++) {\n const task = visibleTasks[index];\n const ancestorIds: string[] = [];\n let current: any = taskById.get(task.id);\n while (current?.parentId && taskById.has(current.parentId)) {\n ancestorIds.unshift(current.parentId as string);\n current = taskById.get(current.parentId);\n }\n\n const ancestorsAboveParent = ancestorIds.slice(0, -1);\n const modes = ancestorsAboveParent.map((ancestorId) => {\n const hasLaterVisibleDescendant = visibleTasks\n .slice(index + 1)\n .some((laterTask) => isDescendantOf(laterTask.id, ancestorId));\n return hasLaterVisibleDescendant ? \"full\" : \"half\";\n });\n\n map.set(task.id, modes);\n }\n return map;\n }, [tasks, visibleTasks]);\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 [dependencyPickMode, setDependencyPickMode] = useState<DependencyPickMode>('successor');\n const [typeMenuOpen, setTypeMenuOpen] = useState(false);\n const [dependencyError, setDependencyError] = useState<string | null>(null);\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, chip selection, and task row selection\n useEffect(() => {\n if (!selectingPredecessorFor && !selectedChip && !selectedTaskId) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setSelectingPredecessorFor(null);\n setSelectedChip(null);\n onSelectedChipChange?.(null);\n onTaskSelect?.(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 onTaskSelect?.(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, selectedTaskId, onTaskSelect, 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 links between ancestors and descendants in either direction\n if (areTasksHierarchicallyRelated(successorTaskId, predecessorTaskId, tasks)) {\n setDependencyError('Связи между родителем и потомком запрещены');\n setTimeout(() => setDependencyError(null), 3000);\n setSelectingPredecessorFor(null);\n return;\n }\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 const hasHierarchyConstraint = validation.errors.some(error => error.type === 'constraint');\n setDependencyError(\n hasHierarchyConstraint\n ? 'Связи между родителем и потомком запрещены'\n : 'Цикл зависимостей!'\n );\n setTimeout(() => setDependencyError(null), 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(\n predStart,\n predEnd,\n linkType,\n 0,\n businessDays ?? true,\n weekendPredicate\n );\n\n const origSuccessor = tasks.find(t => t.id === successorTaskId)!;\n const duration = getTaskDuration(\n origSuccessor.startDate,\n origSuccessor.endDate,\n businessDays ?? true,\n weekendPredicate\n );\n\n let newStart: Date;\n let newEnd: Date;\n\n if (linkType === 'FS' || linkType === 'SS') {\n ({ start: newStart, end: newEnd } = buildTaskRangeFromStart(\n constraintDate,\n duration,\n businessDays ?? true,\n weekendPredicate\n ));\n } else {\n ({ start: newStart, end: newEnd } = buildTaskRangeFromEnd(\n constraintDate,\n duration,\n businessDays ?? true,\n weekendPredicate\n ));\n }\n\n const snappedTask: Task = {\n ...updatedTask,\n startDate: newStart.toISOString().split('T')[0],\n endDate: newEnd.toISOString().split('T')[0],\n };\n onTasksChange?.([snappedTask]);\n } else {\n // Predecessor not found — emit without snap (graceful fallback)\n onTasksChange?.([updatedTask]);\n }\n\n setSelectingPredecessorFor(null);\n }, [tasks, onTasksChange]);\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 onTasksChange?.([{ ...task, dependencies: updatedDeps }]);\n }, [tasks, onTasksChange]);\n\n // New task creation state\n const [isCreating, setIsCreating] = useState(false);\n const [pendingInsert, setPendingInsert] = useState<PendingInsertState | null>(null);\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 const dragTaskIdRef = useRef<string | null>(null);\n\n // Helper: check if a parent task can be dropped at a specific position\n // Parent tasks cannot be dropped:\n // 1. Between their own children\n // 2. Between another parent's children (would make them a child)\n // 3. Under their own descendants (would create a cycle)\n const isValidParentDrop = useCallback((draggedTaskId: string, dropIndex: number): boolean => {\n // If not a parent, allow all drops\n if (!isTaskParent(draggedTaskId, tasks)) {\n return true;\n }\n\n const dropTarget = visibleTasks[dropIndex];\n if (!dropTarget) return true;\n\n // Scenario 1: Dropping parent between its own children\n if (dropTarget.parentId === draggedTaskId) {\n return false;\n }\n\n // Scenario 2: Dropping parent between another parent's children\n // Allow this for unlimited nesting — parent can become nested under another task.\n // Scenarios 1 and 3 still protect against circular references and self-nesting.\n\n // Scenario 3: Dropping parent under one of its own descendants\n // This would create a cycle (parent becomes child of its descendant)\n // Check if dropTarget is a descendant of draggedTaskId\n const draggedTask = orderedTasks.find(t => t.id === draggedTaskId);\n if (!draggedTask) return true;\n\n const descendants = getAllDescendants(draggedTaskId, orderedTasks);\n const descendantIds = new Set(descendants.map(d => d.id));\n\n if (descendantIds.has(dropTarget.id)) {\n return false;\n }\n\n // Allow dropping on other root tasks (parents or non-parents)\n return true;\n }, [tasks, visibleTasks, orderedTasks]);\n\n const handleDragStart = useCallback((index: number, e: React.DragEvent) => {\n e.dataTransfer.effectAllowed = 'move';\n setDraggingIndex(index);\n dragOriginIndexRef.current = index;\n dragTaskIdRef.current = visibleTasks[index]?.id ?? null;\n }, [visibleTasks]);\n\n const handleDragOver = useCallback((index: number, e: React.DragEvent) => {\n e.preventDefault();\n\n const draggedTaskId = dragTaskIdRef.current;\n if (!draggedTaskId) return;\n\n // Don't show drop indication if this is an invalid parent drop\n if (!isValidParentDrop(draggedTaskId, index)) {\n setDragOverIndex(null);\n e.dataTransfer.dropEffect = 'none';\n return;\n }\n\n e.dataTransfer.dropEffect = 'move';\n setDragOverIndex(index);\n }, [isValidParentDrop]);\n\n const handleDrop = useCallback((dropIndex: number, e: React.DragEvent) => {\n e.preventDefault();\n const originVisibleIndex = dragOriginIndexRef.current;\n const movedTaskId = dragTaskIdRef.current;\n\n // No-op: same position (line is already where the row is)\n if (originVisibleIndex === null || movedTaskId === null || originVisibleIndex === dropIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n // Reject invalid parent drops (parent being dragged into children or another parent)\n if (!isValidParentDrop(movedTaskId, dropIndex)) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const reorderPosition = getVisibleReorderPosition(\n orderedTasks,\n visibleTasks,\n movedTaskId,\n originVisibleIndex,\n dropIndex,\n );\n\n if (!reorderPosition) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const { originOrderedIndex, insertIndex } = reorderPosition;\n\n // Early exit: if insertIndex equals originOrderedIndex, the subtree would be removed\n // and re-inserted at the exact same position - a true no-op. Skip the callback.\n if (insertIndex === originOrderedIndex) {\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n return;\n }\n\n const moved = orderedTasks[originOrderedIndex];\n\n // Check if this is a parent task with children\n const hasChildren = isTaskParent(moved.id, orderedTasks);\n\n // Extract the subtree to move (parent + all descendants, if any)\n let subtree: Task[];\n let subtreeCount: number;\n\n if (hasChildren) {\n // Get all descendants of the parent\n const descendants = getAllDescendants(moved.id, orderedTasks);\n subtree = [moved, ...descendants];\n subtreeCount = subtree.length;\n } else {\n // Single task (not a parent)\n subtree = [moved];\n subtreeCount = 1;\n }\n\n const reordered = [...orderedTasks];\n\n // Remove the entire subtree from its original position\n reordered.splice(originOrderedIndex, subtreeCount);\n\n // CRITICAL: insertIndex is already relative to reorderedWithoutMoved\n // After the splice, reordered === reorderedWithoutMoved (same array, same order)\n // So we should use insertIndex directly, NOT insertIndex - subtreeCount\n // The old code was subtracting subtreeCount again, which was incorrect\n const adjustedInsertIndex = insertIndex;\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 if (parentIndex === -1) {\n // Parent not found - should not happen, but handle gracefully\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 // If adjustedInsertIndex is <= parent (at or above parent position) or > groupEnd (below all siblings)\n // Note: adjustedInsertIndex == 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 (adjustedInsertIndex <= parentIndex || adjustedInsertIndex > groupEnd) {\n inferredParentId = undefined; // Exit group - become root\n } else {\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 after splicing\n }\n\n // Now splice the entire subtree into its final position\n reordered.splice(adjustedInsertIndex, 0, ...subtree);\n\n // For root tasks, check if they should join a group (need reordered for this)\n // IMPORTANT: Parent tasks (hasChildren === true) must NEVER be reparented during drag-drop.\n // They always stay at root level regardless of where they are dropped.\n // Only leaf/child tasks (non-parents) can be adopted into a group by neighboring tasks.\n if (!moved.parentId && !hasChildren) {\n const taskAbove = adjustedInsertIndex > 0 ? reordered[adjustedInsertIndex - 1] : null;\n const taskBelow = adjustedInsertIndex < reordered.length - 1 ? reordered[adjustedInsertIndex + 1] : null;\n\n // Join a group ONLY if placed between parent and its first child,\n // or between two children of the same parent.\n // Dropping after the last child of a group keeps the task at root level.\n if (taskAbove && taskBelow && taskBelow.parentId === taskAbove.id) {\n // Placed between a parent and its first child\n inferredParentId = taskAbove.id;\n } else if (taskAbove && taskBelow && taskAbove.parentId && taskAbove.parentId === taskBelow.parentId) {\n // Placed between two children of the same parent\n inferredParentId = taskAbove.parentId;\n } else if (!taskAbove && taskBelow && taskBelow.parentId) {\n // Placed at the very top, above a child — join that group\n inferredParentId = taskBelow.parentId;\n }\n }\n\n onReorder?.(reordered, moved.id, inferredParentId);\n onTaskSelect?.(moved.id);\n setDraggingIndex(null);\n setDragOverIndex(null);\n dragOriginIndexRef.current = null;\n dragTaskIdRef.current = null;\n }, [orderedTasks, visibleTasks, 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 dragTaskIdRef.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 const findInsertAfterTaskId = useCallback((anchorTaskId: string): string => {\n const anchorIndex = orderedTasks.findIndex(task => task.id === anchorTaskId);\n if (anchorIndex === -1) {\n return anchorTaskId;\n }\n\n const taskById = new Map(orderedTasks.map(task => [task.id, task]));\n let insertAfterTaskId = anchorTaskId;\n\n for (let index = anchorIndex + 1; index < orderedTasks.length; index += 1) {\n let currentParentId = orderedTasks[index]?.parentId;\n let isDescendant = false;\n\n while (currentParentId) {\n if (currentParentId === anchorTaskId) {\n isDescendant = true;\n break;\n }\n currentParentId = taskById.get(currentParentId)?.parentId;\n }\n\n if (!isDescendant) {\n break;\n }\n\n insertAfterTaskId = orderedTasks[index].id;\n }\n\n return insertAfterTaskId;\n }, [orderedTasks]);\n\n const pendingInsertDisplayTaskId = useMemo(() => {\n if (!pendingInsert) {\n return null;\n }\n\n const taskById = new Map(visibleTasks.map(task => [task.id, task]));\n if (!taskById.has(pendingInsert.anchorTaskId)) {\n return null;\n }\n\n let displayTaskId = pendingInsert.anchorTaskId;\n\n for (const task of visibleTasks) {\n let currentParentId = task.parentId;\n while (currentParentId) {\n if (currentParentId === pendingInsert.anchorTaskId) {\n displayTaskId = task.id;\n break;\n }\n currentParentId = taskById.get(currentParentId)?.parentId;\n }\n }\n\n return displayTaskId;\n }, [pendingInsert, visibleTasks]);\n\n const handleStartInsertAfter = useCallback((taskId: string, newTask: Task) => {\n const anchorTask = orderedTasks.find(task => task.id === taskId);\n if (!anchorTask) {\n return;\n }\n\n setIsCreating(false);\n setPendingInsert({\n anchorTaskId: taskId,\n insertAfterTaskId: findInsertAfterTaskId(taskId),\n parentId: anchorTask.parentId,\n startDate: newTask.startDate,\n endDate: newTask.endDate,\n nestingDepth: nestingDepthMap.get(taskId) ?? 0,\n });\n }, [findInsertAfterTaskId, nestingDepthMap, orderedTasks]);\n\n const handleConfirmInsertedTask = useCallback((name: string) => {\n if (!pendingInsert) {\n return;\n }\n\n const newTask: Task = {\n id: crypto.randomUUID(),\n name,\n startDate: pendingInsert.startDate,\n endDate: pendingInsert.endDate,\n parentId: pendingInsert.parentId,\n };\n\n onInsertAfter?.(pendingInsert.insertAfterTaskId, newTask);\n setPendingInsert(null);\n }, [onInsertAfter, pendingInsert]);\n\n const handleCancelInsertedTask = useCallback(() => setPendingInsert(null), []);\n\n /**\n * Calculate the depth of a task in the hierarchy.\n * Root tasks have depth 0, their children have depth 1, etc.\n */\n function getTaskDepth(task: Task | undefined, tasks: Task[]): number {\n if (!task) return 0;\n let depth = 0;\n let current: Task | undefined = task;\n while (current) {\n if (!current.parentId) break;\n depth++;\n const parentId: string = current.parentId;\n current = tasks.find(t => t.id === parentId);\n }\n return depth;\n }\n\n /**\n * Demote wrapper — move task down one level in hierarchy.\n *\n * Rules:\n * 1. Find the PREVIOUS task at the SAME depth level (same hierarchy level)\n * 2. Make that task the parent of the current task\n * 3. If no previous task at same level exists (first task), create \"Новый раздел\"\n *\n * Example:\n * - Task 1.1 (depth 1)\n * - Task 1.2 (depth 1)\n * - [Task to demote] (depth 1) → becomes child of Task 1.2\n *\n * Result:\n * - Task 1.1 (depth 1)\n * - Task 1.2 (depth 1)\n * - Task to demote (depth 2, child of 1.2)\n *\n * The `_newParentId` argument from TaskListRow is ignored — we compute the correct parent here.\n */\n const handleDemoteWrapper = useCallback((taskId: string, _newParentId: string) => {\n const taskIndex = visibleTasks.findIndex(t => t.id === taskId);\n const currentTask = visibleTasks[taskIndex];\n const currentDepth = getTaskDepth(currentTask, orderedTasks);\n\n if (taskIndex > 0) {\n // Search backwards for the previous task at the same depth level\n for (let i = taskIndex - 1; i >= 0; i--) {\n const previousTask = visibleTasks[i];\n const previousDepth = getTaskDepth(previousTask, orderedTasks);\n\n // Found a task at the same level - use it as parent\n if (previousDepth === currentDepth) {\n onDemoteTask?.(taskId, previousTask.id);\n return;\n }\n\n // If we encounter a task at a shallower depth, stop searching\n // (no same-level task exists before this point)\n if (previousDepth < currentDepth) {\n break;\n }\n }\n\n // No same-level task found - cannot demote\n return;\n }\n\n // First-task case: create \"Новый раздел\" as a new root parent\n const demotedTask = orderedTasks.find(t => t.id === taskId);\n if (!demotedTask) return;\n\n const newSectionTask: Task = {\n id: crypto.randomUUID(),\n name: 'Новый раздел',\n startDate: demotedTask.startDate,\n endDate: demotedTask.endDate,\n };\n\n const updatedTasks: Task[] = [\n newSectionTask,\n ...orderedTasks.map(t =>\n t.id === taskId ? { ...t, parentId: newSectionTask.id } : t\n ),\n ];\n\n onReorder?.(updatedTasks, taskId, newSectionTask.id);\n }, [visibleTasks, orderedTasks, onDemoteTask, onReorder]);\n\n const handleDuplicateTask = useCallback((taskId: string) => {\n const duplicatedTasks = duplicateTaskSubtree(taskId, orderedTasks);\n onReorder?.(duplicatedTasks);\n }, [orderedTasks, onReorder]);\n\n // ---- Column resolution ----\n const builtInColumns = useMemo(() => createBuiltInColumns<Task>({ businessDays }), [businessDays]);\n const resolvedColumns = useMemo(\n () => resolveTaskListColumns(builtInColumns, (additionalColumns ?? []) as NewTaskListColumn<Task>[]),\n [builtInColumns, additionalColumns]\n );\n const resolvedColumnWidthTotal = useMemo(\n () => resolvedColumns.reduce((sum, col) => sum + (col.width ?? 120), 0),\n [resolvedColumns]\n );\n\n const effectiveTaskListWidth = Math.max(taskListWidth, MIN_TASK_LIST_WIDTH, resolvedColumnWidthTotal);\n\n return (\n <div\n ref={overlayRef}\n className={`gantt-tl-overlay${show ? '' : ' gantt-tl-hidden'}${hasRightShadow ? ' gantt-tl-overlay-shadowed' : ''}`}\n style={{ '--tasklist-width': `${effectiveTaskListWidth}px` } as React.CSSProperties}\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 {resolvedColumns.map(col => {\n // Dependencies header has special Popover UI\n if (col.id === 'dependencies') {\n return (\n <div key={col.id} className=\"gantt-tl-headerCell gantt-tl-cell-deps\"\n data-column-id=\"dependencies\"\n 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 {dependencyError && (\n <div className=\"gantt-tl-dep-error\">{dependencyError}</div>\n )}\n </div>\n );\n }\n // Built-in columns use CSS classes for width (same as body cells — no inline width override)\n const builtInClass = BUILT_IN_CSS_CLASSES[col.id];\n if (builtInClass !== undefined) {\n return (\n <div key={col.id}\n className={`gantt-tl-headerCell ${builtInClass}`}\n data-column-id={col.id}>\n {col.header}\n </div>\n );\n }\n // Custom columns\n return (\n <div key={col.id}\n className=\"gantt-tl-headerCell gantt-tl-headerCell-custom\"\n data-column-id={`custom:${col.id}`}\n data-custom-column-id={col.id}\n style={{ width: col.width, minWidth: col.width, flexShrink: 0 }}>\n {col.header}\n </div>\n );\n })}\n </div>\n\n {/* Data rows */}\n <div className=\"gantt-tl-body\" style={{ height: `${totalHeight}px` }}>\n {visibleTasks.map((task, index) => {\n const previousVisibleTask = index > 0 ? visibleTasks[index - 1] : undefined;\n const canDemoteTask = index === 0\n || !task.parentId\n || previousVisibleTask?.id !== task.parentId;\n\n return (\n <React.Fragment key={task.id}>\n <TaskListRow\n task={task}\n rowIndex={index}\n taskNumber={originalTaskNumberMap[task.id] || ''}\n taskNumberMap={originalTaskNumberMap}\n rowHeight={rowHeight}\n onTasksChange={onTasksChange}\n selectedTaskId={selectedTaskId}\n onRowClick={handleRowClick}\n disableTaskNameEditing={disableTaskNameEditing}\n disableDependencyEditing={disableDependencyEditing}\n allTasks={tasks}\n activeLinkType={activeLinkType}\n onSetActiveLinkType={setActiveLinkType}\n selectingPredecessorFor={selectingPredecessorFor}\n dependencyPickMode={dependencyPickMode}\n onSetDependencyPickMode={setDependencyPickMode}\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={handleStartInsertAfter}\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 ? handleDemoteWrapper : undefined}\n onDuplicateTask={onReorder ? handleDuplicateTask : undefined}\n canDemoteTask={canDemoteTask}\n isLastChild={lastChildIds.has(task.id)}\n nestingDepth={nestingDepthMap.get(task.id) ?? 0}\n hasVisibleChildren={visibleParentIds.has(task.id)}\n ancestorLineModes={ancestorLineModesMap.get(task.id) ?? []}\n customDays={customDays}\n isWeekend={isWeekend}\n businessDays={businessDays}\n isFilterMatch={filterMode === 'highlight' ? highlightedTaskIds.has(task.id) : false}\n isFilterHideMode={filterMode === 'hide' && isFilterActive}\n resolvedColumns={resolvedColumns}\n />\n {pendingInsertDisplayTaskId === task.id && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmInsertedTask}\n onCancel={handleCancelInsertedTask}\n nestingDepth={pendingInsert?.nestingDepth ?? 0}\n />\n )}\n </React.Fragment>\n );\n })}\n </div>\n\n {/* Ghost row for new task creation — positioned OUTSIDE body div to avoid height desync */}\n {isCreating && !pendingInsert && (\n <NewTaskRow\n rowHeight={rowHeight}\n onConfirm={handleConfirmNewTask}\n onCancel={handleCancelNewTask}\n nestingDepth={0}\n />\n )}\n\n {/* Add task button - also serves as drop target for moving tasks to end */}\n {enableAddTask && onAdd && !isCreating && !pendingInsert && (\n <button\n className={`gantt-tl-add-btn${dragOverIndex === visibleTasks.length ? ' gantt-tl-add-btn-drag-over' : ''}`}\n onClick={() => {\n setPendingInsert(null);\n setIsCreating(true);\n }}\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","import type { Task } from '../components/GanttChart';\n\ntype TaskLike = { id: string };\n\nexport interface VisibleReorderPosition {\n originOrderedIndex: number;\n insertIndex: number;\n}\n\n/**\n * Get all descendant IDs of a task (recursively).\n * Used to identify the entire subtree that must move together when dragging a parent.\n */\nfunction getDescendantIds(taskId: string, tasks: TaskLike[]): string[] {\n const descendants: string[] = [];\n const visited = new Set<string>();\n\n function collect(id: string) {\n if (visited.has(id)) return;\n visited.add(id);\n\n // Find all direct children of this task\n for (const task of tasks) {\n if ((task as any).parentId === id && !visited.has(task.id)) {\n descendants.push(task.id);\n collect(task.id);\n }\n }\n }\n\n collect(taskId);\n return descendants;\n}\n\n/**\n * Map visible drag/drop positions to indices in the full ordered task list.\n * This keeps collapsed descendants attached to their parent row.\n *\n * When dragging a parent task, all its descendants are included in the move,\n * so they are all filtered out before calculating the insert position.\n */\nexport function getVisibleReorderPosition(\n orderedTasks: TaskLike[],\n visibleTasks: TaskLike[],\n movedTaskId: string,\n originVisibleIndex: number,\n dropVisibleIndex: number,\n): VisibleReorderPosition | null {\n const originOrderedIndex = orderedTasks.findIndex((task) => task.id === movedTaskId);\n if (originOrderedIndex === -1) {\n return null;\n }\n\n // Get all descendant IDs if this is a parent task\n const descendantIds = getDescendantIds(movedTaskId, orderedTasks);\n const allMovedIds = new Set([movedTaskId, ...descendantIds]);\n\n // Filter out ALL tasks that will move (parent + descendants)\n const reorderedWithoutMoved = orderedTasks.filter((task) => !allMovedIds.has(task.id));\n const visibleWithoutMoved = visibleTasks.filter((task) => !allMovedIds.has(task.id));\n\n if (visibleWithoutMoved.length === 0) {\n return { originOrderedIndex, insertIndex: 0 };\n }\n\n // CRITICAL: dropVisibleIndex is an index into the ORIGINAL visibleTasks, NOT into\n // visibleWithoutMoved (which has fewer items after removing the moved subtree).\n // We must look up the actual drop target task by its ID from the original list,\n // then find it in visibleWithoutMoved.\n\n // Look up the actual task at the drop position in the ORIGINAL visible list\n const dropTargetTask = visibleTasks[dropVisibleIndex];\n\n if (!dropTargetTask) {\n // dropVisibleIndex is beyond the end of the original list - append at end\n return {\n originOrderedIndex,\n insertIndex: reorderedWithoutMoved.length,\n };\n }\n\n // Find the drop target in the filtered array (visibleWithoutMoved has the moved subtree removed)\n const filteredDropIndex = visibleWithoutMoved.findIndex((t) => t.id === dropTargetTask.id);\n\n if (filteredDropIndex === -1) {\n // Drop target was part of the moved subtree - should not happen after isValidParentDrop check\n // Append at end as fallback\n return {\n originOrderedIndex,\n insertIndex: reorderedWithoutMoved.length,\n };\n }\n\n const targetVisibleTask = visibleWithoutMoved[filteredDropIndex];\n\n // Find the target in reorderedWithoutMoved.\n // The drop indicator semantics: indicator at position N shows the TOP border of row N,\n // meaning the task will be inserted ABOVE row N.\n // We use the drop target's position directly without skipping past its group.\n // This preserves \"drop at top of родитель2 = insert before родитель2\" semantics.\n // To move a parent PAST родитель2's entire group, the user must drag to the end of the list\n // (past all of родитель2's children), which triggers the \"append at end\" path above.\n const insertIndex = reorderedWithoutMoved.findIndex((task) => task.id === targetVisibleTask.id);\n\n return {\n originOrderedIndex,\n insertIndex,\n };\n}\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, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useMemo,\n} from \"react\";\nimport type { Task } from \"../GanttChart\";\nimport type { LinkType } from \"../../types\";\nimport type { CustomDayConfig } from \"../../utils/dateUtils\";\nimport { parseUTCDate, normalizeTaskDates, createCustomDayPredicate } from \"../../utils/dateUtils\";\nimport { isMilestoneTask, normalizeTaskDatesForType } from \"../../utils/taskType\";\nimport {\n getBusinessDaysCount,\n addBusinessDays,\n subtractBusinessDays,\n alignToWorkingDay,\n buildTaskRangeFromEnd,\n buildTaskRangeFromStart,\n getDependencyLag,\n calculateSuccessorDate,\n clampTaskRangeForIncomingFS,\n normalizeDependencyLag,\n isTaskParent,\n findParentId,\n getChildren,\n recalculateIncomingLags,\n} from \"../../core/scheduling\";\nimport { Input } from \"../ui/Input\";\nimport { DatePicker } from \"../ui/DatePicker\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/Popover\";\nimport { LINK_TYPE_ICONS } from \"./DepIcons\";\nimport type { TaskListColumn as NewTaskListColumn } from \"./columns/types\";\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst LINK_TYPE_ORDER: LinkType[] = [\"FS\", \"SS\", \"FF\", \"SF\"];\n\nconst getInclusiveDurationDays = (\n startDate: string | Date,\n endDate: string | Date,\n): number => {\n const start = parseUTCDate(startDate);\n const end = parseUTCDate(endDate);\n return Math.max(\n 1,\n Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1,\n );\n};\n\nconst getEndDateFromDuration = (\n startDate: string | Date,\n durationDays: number,\n): string => {\n const start = parseUTCDate(startDate);\n return new Date(start.getTime() + (durationDays - 1) * DAY_MS)\n .toISOString()\n .split(\"T\")[0];\n};\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 taskNumber?: string;\n taskNumberMap?: Record<string, string>;\n predecessorName?: string;\n predecessorTaskNumber?: 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 /** The successor task (needed for lag date computation) */\n task: Task;\n /** All tasks (needed to find predecessor dates) */\n allTasks: Task[];\n /** Callback to save date changes after lag modification */\n onTasksChange?: TaskListRowProps[\"onTasksChange\"];\n businessDays?: boolean;\n weekendPredicate: (date: Date) => boolean;\n}\n\nconst TrashIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\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\nconst VerticalDotsIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"19\" r=\"2\" />\n </svg>\n);\n\nconst CopyIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n);\n\nconst TASK_COLOR_PALETTE = [\n // { label: \"Палисандр\", value: \"#A61E4D\" },\n // { label: \"Киноварь\", value: \"#E8590C\" },\n // { label: \"Жёлт\", value: \"#eec45c\" },\n { label: \"Киноварь2\", value: \"#fe724e\" },\n // { label: \"Оранжевый\", value: \"#F08C00\" },\n { label: \"Оранжевый2\", value: \"#ff991f\" },\n { label: \"Золотой\", value: \"#e5c800\" },\n { label: \"Бирюза\", value: \"#58d8a3\" },\n { label: \"Палисандр\", value: \"#d64a7b\" },\n { label: \"Песочный\", value: \"#997B10\" },\n { label: \"Шартрез\", value: \"#A3BE00\" },\n { label: \"Голубой\", value: \"#03c7e6\" },\n { label: \"Виноград2\", value: \"#8678d9\" },\n { label: \"Серый2\", value: \"#6b778c\" },\n { label: \"Лесной\", value: \"#2B8A3E\" },\n // { label: \"Лесной3\", value: \"#60b838\" },\n // { label: \"Бирюза\", value: \"#0B7285\" },\n // { label: \"Серый\", value: \"#495057\" },\n // { label: \"Океан\", value: \"#5244ff\" },\n // { label: \"Океан2\", value: \"#0626ba\" },\n // { label: \"Виноград\", value: \"#AE3EC9\" },\n] as const;\n\nconst ChevronRightIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst LINK_TYPE_LABELS_RU: Record<LinkType, string> = {\n FS: \"ОН\",\n SS: \"НН\",\n FF: \"ОО\",\n SF: \"НО\",\n};\n\nfunction formatTaskNumberLabel(taskNumber?: string): string {\n return taskNumber ? `${taskNumber}. ` : \"\";\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 /** Row index - first row cannot demote */\n rowIndex: number;\n /** Whether demote action should be shown for this row */\n canDemote: boolean;\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 ArrowLeft = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m12 19-7-7 7-7\" />\n <path d=\"M19 12H5\" />\n </svg>\n);\n\nconst ArrowRight = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n);\n\nconst HierarchyButton: React.FC<HierarchyButtonProps> = ({\n isChild,\n rowIndex: _rowIndex,\n canDemote,\n onPromote,\n onDemote,\n}) => {\n const canPromote = isChild && onPromote;\n const showDemote = canDemote && !!onDemote;\n\n if (!canPromote && !showDemote) return null;\n\n return (\n <>\n {canPromote && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={(e) => {\n e.stopPropagation();\n onPromote!(e);\n }}\n title=\"Повысить уровень\"\n >\n <ArrowLeft />\n </button>\n )}\n {showDemote && (\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-hierarchy\"\n onClick={(e) => {\n e.stopPropagation();\n onDemote!(e);\n }}\n title=\"Понизить уровень\"\n >\n <ArrowRight />\n </button>\n )}\n </>\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)\n return `Начать через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0)\n return `Начать за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Начать сразу после окончания`;\n }\n if (type === \"FF\") {\n if (effectiveLag > 0)\n return `Завершить через ${effectiveLag} дн. после окончания`;\n if (effectiveLag < 0)\n return `Завершить за ${Math.abs(effectiveLag)} дн. до окончания`;\n return `Завершить после окончания`;\n }\n if (type === \"SS\") {\n if (effectiveLag > 0)\n return `Начать через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0)\n return `Начать за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Начать вместе с началом`;\n }\n if (type === \"SF\") {\n if (effectiveLag > 0)\n return `Завершить через ${effectiveLag} дн. после начала`;\n if (effectiveLag < 0)\n return `Завершить за ${Math.abs(effectiveLag)} дн. до начала`;\n return `Завершить до начала`;\n }\n return \"\";\n}\n\nconst DepChip: React.FC<DepChipProps> = ({\n lag,\n dep,\n taskId,\n taskNumber,\n predecessorName,\n predecessorTaskNumber,\n selectedChip,\n disableDependencyEditing,\n onChipSelect,\n onRowClick,\n onScrollToTask,\n onRemoveDependency,\n onChipSelectClear,\n task,\n allTasks,\n onTasksChange,\n businessDays = true,\n weekendPredicate,\n}) => {\n const [popoverOpen, setPopoverOpen] = useState(false);\n const lagAbs = Math.abs(lag ?? 0);\n const [inputAbs, setInputAbs] = useState(lagAbs === 0 ? \"\" : String(lagAbs));\n useEffect(() => {\n const abs = Math.abs(lag ?? 0);\n setInputAbs(abs === 0 ? \"\" : String(abs));\n }, [lag]);\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 // Toggle popover and chip selection together\n const nextOpen = !popoverOpen;\n setPopoverOpen(nextOpen);\n if (nextOpen) {\n onChipSelect?.({\n successorId: taskId,\n predecessorId: dep.taskId,\n linkType: dep.type,\n });\n onScrollToTask?.(taskId);\n } else {\n // Only clear selection when explicitly closing via chip click\n onChipSelect?.(null);\n }\n };\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n setPopoverOpen(open);\n // Don't clear selectedChip on automatic popover close (e.g. focus loss, escape)\n // Only clear when user explicitly closes via chip click or trash button\n },\n [],\n );\n\n const handleTrashClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onRemoveDependency?.(taskId, dep.taskId, dep.type);\n onChipSelectClear();\n setPopoverOpen(false);\n };\n\n const handleLagChange = useCallback(\n (newLag: number) => {\n if (!onTasksChange || !allTasks) return;\n const taskById = new Map(allTasks.map((t) => [t.id, t]));\n const predecessor = taskById.get(dep.taskId);\n if (!predecessor) return;\n\n const predStart = parseUTCDate(predecessor.startDate);\n // Milestone predecessors have zero duration — treat end = start\n const predEnd = predecessor.type === 'milestone' ? predStart : parseUTCDate(predecessor.endDate);\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n const normalizedLag = normalizeDependencyLag(\n dep.type,\n newLag,\n predStart,\n predEnd,\n businessDays,\n weekendPredicate,\n );\n\n const constraintDate = calculateSuccessorDate(\n predStart,\n predEnd,\n dep.type,\n normalizedLag,\n businessDays,\n weekendPredicate,\n );\n\n let newStart: Date, newEnd: Date;\n if (dep.type === \"FS\" || dep.type === \"SS\") {\n newStart = constraintDate;\n if (businessDays) {\n const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);\n newEnd = addBusinessDays(constraintDate, businessDuration, weekendPredicate);\n } else {\n newEnd = new Date(constraintDate.getTime() + durationMs);\n }\n } else {\n newEnd = constraintDate;\n if (businessDays) {\n const businessDuration = getBusinessDaysCount(origStart, origEnd, weekendPredicate);\n newStart = subtractBusinessDays(constraintDate, businessDuration, weekendPredicate);\n } else {\n newStart = new Date(constraintDate.getTime() - durationMs);\n }\n }\n\n onTasksChange([\n {\n ...task,\n startDate: newStart.toISOString().split(\"T\")[0],\n endDate: newEnd.toISOString().split(\"T\")[0],\n dependencies: (task.dependencies ?? []).map((existingDep) =>\n existingDep.taskId === dep.taskId && existingDep.type === dep.type\n ? { ...existingDep, lag: normalizedLag }\n : existingDep\n ),\n },\n ]);\n },\n [dep, task, allTasks, onTasksChange, businessDays, weekendPredicate],\n );\n\n const handleInputCommit = useCallback(\n (raw: string) => {\n if (raw === \"\") {\n handleLagChange(0);\n return;\n }\n const parsed = parseInt(raw, 10);\n const effectiveLag = lag ?? 0;\n if (isNaN(parsed)) {\n const abs = Math.abs(effectiveLag);\n setInputAbs(abs === 0 ? \"\" : String(abs));\n return;\n }\n let newLag: number;\n if (parsed === 0) {\n newLag = 0;\n } else if (dep.type === \"SF\") {\n newLag = -Math.abs(parsed);\n } else {\n // sign comes from what the user typed: \"-4\" → negative, \"4\" → positive\n newLag = parsed; // parseInt preserves the sign from input\n }\n if (newLag !== effectiveLag) handleLagChange(newLag);\n },\n [lag, dep.type, handleLagChange],\n );\n\n const Icon = LINK_TYPE_ICONS[dep.type];\n const depName = predecessorName ?? dep.taskId;\n const effectiveLag = lag ?? 0;\n\n // Derive action verb, preWord and afterWhat (sign-dependent for FS/FF/SS)\n const actionVerb =\n dep.type === \"FS\" || dep.type === \"SS\" ? \"начать\" : \"завершить\";\n const zeroPlaceholder =\n dep.type === \"SF\"\n ? \"чётко\"\n : dep.type === \"FF\"\n ? \"вместе\"\n : dep.type === \"SS\"\n ? \"вместе\"\n : \"сразу\";\n let afterWhat: string;\n let preWord: string | null = null;\n if (dep.type === \"SF\") {\n afterWhat =\n effectiveLag < 0\n ? \"до начала\"\n : effectiveLag === 0\n ? \"с началом\"\n : \"после начала\";\n if (effectiveLag > 0) preWord = \"через\";\n else if (effectiveLag < 0) preWord = \"за\";\n } else if (dep.type === \"SS\") {\n afterWhat =\n effectiveLag < 0\n ? \"до начала\"\n : effectiveLag === 0\n ? \"с началом\"\n : \"после начала\";\n if (effectiveLag > 0) preWord = \"через\";\n else if (effectiveLag < 0) preWord = \"за\";\n } else {\n // FS, FF\n if (effectiveLag > 0) {\n preWord = \"через\";\n afterWhat = \"после окончания\";\n } else if (effectiveLag < 0) {\n preWord = \"за\";\n afterWhat = \"до окончания\";\n } else {\n afterWhat = \"после окончания\";\n }\n }\n\n return (\n <Popover open={popoverOpen} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n <span\n className={`gantt-tl-dep-chip${isSelected ? \" gantt-tl-dep-chip-selected\" : \"\"}`}\n onClick={handleClick}\n title={`[${LINK_TYPE_LABELS_RU[dep.type]}] ${formatTaskNumberLabel(predecessorTaskNumber)}${depName}`}\n >\n <Icon />\n {effectiveLag !== 0\n ? effectiveLag > 0\n ? `+${effectiveLag}`\n : `${effectiveLag}`\n : \"\"}\n </span>\n </PopoverTrigger>\n <PopoverContent\n className=\"gantt-tl-dep-edit-popover\"\n portal={true}\n align=\"start\"\n >\n <div onClick={(e) => e.stopPropagation()}>\n <div className=\"gantt-tl-dep-edit-task\">\n {formatTaskNumberLabel(taskNumber)}\n {task.name}\n </div>\n <div className=\"gantt-tl-dep-edit-row\">\n <span className=\"gantt-tl-dep-edit-label\">\n {actionVerb}\n {preWord ? ` ${preWord}` : \"\"}\n </span>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-btn\"\n onClick={() => handleLagChange(effectiveLag - 1)}\n >\n −\n </button>\n <input\n type=\"number\"\n className=\"gantt-tl-dep-edit-input\"\n value={inputAbs}\n placeholder={zeroPlaceholder}\n min=\"0\"\n onChange={(e) => setInputAbs(e.target.value)}\n onFocus={(e) => e.target.select()}\n onBlur={(e) => handleInputCommit(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleInputCommit(inputAbs);\n }}\n />\n {!(dep.type === \"SF\" && effectiveLag === 0) && (\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-btn\"\n onClick={() => handleLagChange(effectiveLag + 1)}\n >\n +\n </button>\n )}\n {effectiveLag !== 0 && <span>д.</span>}\n <span>{afterWhat}</span>\n </div>\n <div className=\"gantt-tl-dep-edit-pred\">\n {formatTaskNumberLabel(predecessorTaskNumber)}\n {depName}\n </div>\n {!disableDependencyEditing && (\n <>\n <hr className=\"gantt-tl-dep-edit-divider\" />\n <div className=\"gantt-tl-dep-edit-actions\">\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-close\"\n onClick={() => {\n setPopoverOpen(false);\n onChipSelectClear();\n }}\n >\n Закрыть\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-dep-edit-delete\"\n onClick={handleTrashClick}\n >\n Удалить связь\n </button>\n </div>\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\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 /** Hierarchical task number (e.g., \"1.2.3\") */\n taskNumber?: string;\n /** Visible task-list numbers by task id */\n taskNumberMap?: Record<string, string>;\n /** Height of the task row in pixels */\n rowHeight: number;\n /** Callback when task is modified via inline edit. Receives array of changed tasks. */\n onTasksChange?: (tasks: 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 /** Callback to change active link type for new dependencies */\n onSetActiveLinkType?: (linkType: LinkType) => void;\n /** Current dependency picking direction */\n dependencyPickMode?: \"predecessor\" | \"successor\";\n /** Callback to change dependency picking direction */\n onSetDependencyPickMode?: (mode: \"predecessor\" | \"successor\") => void;\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?: (\n successorTaskId: string,\n predecessorTaskId: string,\n linkType: LinkType,\n ) => void;\n /** Callback to remove a dependency link */\n onRemoveDependency?: (\n taskId: string,\n predecessorTaskId: string,\n linkType: LinkType,\n ) => void;\n /** Currently selected chip (for predecessor-side delete) */\n selectedChip?: {\n successorId: string;\n predecessorId: string;\n linkType: string;\n } | null;\n /** Callback when a chip is clicked (selects it) */\n onChipSelect?: (\n chip: {\n successorId: string;\n predecessorId: string;\n linkType: LinkType;\n } | null,\n ) => 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 /** Callback when task or task group should be duplicated */\n onDuplicateTask?: (taskId: string) => void;\n /** Whether demote action should be shown for this row */\n canDemoteTask?: boolean;\n /** Whether this child is the last sibling (affects connector icon shape) */\n isLastChild?: boolean;\n /** Nesting depth (0 = root, 1 = child, 2 = grandchild, etc.) */\n nestingDepth?: number;\n /** Whether this row currently has visible children in the rendered task list */\n hasVisibleChildren?: boolean;\n /** For each ancestor above the direct parent: whether its vertical line is full or ends at mid-row */\n ancestorLineModes?: (\"full\" | \"half\")[];\n /** Custom day configurations for date picker */\n customDays?: CustomDayConfig[];\n /** Optional base weekend predicate for date picker */\n isWeekend?: (date: Date) => boolean;\n /** Считать duration в рабочих днях */\n businessDays?: boolean;\n /** Whether this row matches the active filter highlight */\n isFilterMatch?: boolean;\n /** Whether filter is in hide mode (simplifies hierarchy rendering to avoid confusion) */\n isFilterHideMode?: boolean;\n /** Resolved columns (built-in + custom) for unified rendering */\n resolvedColumns?: NewTaskListColumn<Task>[];\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\"))\n 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 taskNumber,\n taskNumberMap = {},\n rowHeight,\n onTasksChange,\n selectedTaskId,\n onRowClick,\n disableTaskNameEditing = false,\n disableDependencyEditing = false,\n allTasks = [],\n activeLinkType,\n onSetActiveLinkType,\n dependencyPickMode = \"successor\",\n onSetDependencyPickMode,\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 onDuplicateTask,\n canDemoteTask = true,\n isLastChild = true,\n nestingDepth = 0,\n hasVisibleChildren = false,\n ancestorLineModes = [],\n customDays,\n isWeekend,\n businessDays,\n isFilterMatch = false,\n isFilterHideMode = false,\n resolvedColumns,\n }) => {\n const [editingColumnId, setEditingColumnId] = useState<string | null>(null);\n const editingName = editingColumnId === 'name';\n const editingDuration = editingColumnId === 'duration';\n const editingProgress = editingColumnId === 'progress';\n const normalizedTask = useMemo(() => normalizeTaskDatesForType(task), [task]);\n const isMilestone = useMemo(() => isMilestoneTask(normalizedTask), [normalizedTask]);\n const [nameValue, setNameValue] = useState(\"\");\n const nameInputRef = useRef<HTMLInputElement>(null);\n const [durationValue, setDurationValue] = useState(() =>\n getInclusiveDurationDays(normalizedTask.startDate, normalizedTask.endDate),\n );\n const durationInputRef = useRef<HTMLInputElement>(null);\n const dependencySearchInputRef = useRef<HTMLInputElement>(null);\n const dependencySearchListRef = useRef<HTMLDivElement>(null);\n const [progressValue, setProgressValue] = useState(0);\n const progressInputRef = useRef<HTMLInputElement>(null);\n const [overflowOpen, setOverflowOpen] = useState(false);\n const [contextMenuOpen, setContextMenuOpen] = useState(false);\n const [colorMenuOpen, setColorMenuOpen] = useState(false);\n const nameConfirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const durationConfirmedRef = useRef(false); // Prevent double-save on Enter + blur\n const progressConfirmedRef = 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\">(\n \"doubleclick\",\n ); // How editing was started\n\n const isSelected = selectedTaskId === task.id;\n\n // Hierarchy computed values\n const isParent = useMemo(\n () => isTaskParent(task.id, allTasks),\n [task.id, allTasks],\n );\n const isChild = task.parentId !== undefined;\n\n // Create custom weekend predicate from props (memoized for performance)\n const weekendPredicate = useMemo(\n () => createCustomDayPredicate({ customDays, isWeekend }),\n [customDays, isWeekend]\n );\n\n // Memoized duration calculation function (business days vs calendar days)\n const getDuration = useCallback(\n (start: string | Date, end: string | Date) => {\n return businessDays\n ? getBusinessDaysCount(start, end, weekendPredicate)\n : getInclusiveDurationDays(start, end);\n },\n [businessDays, weekendPredicate]\n );\n\n // Memoized end date calculation function (business days vs calendar days)\n const getEndDate = useCallback(\n (start: string | Date, duration: number) => {\n return businessDays\n ? addBusinessDays(start, duration, weekendPredicate).toISOString().split('T')[0]\n : getEndDateFromDuration(start, duration);\n },\n [businessDays, weekendPredicate]\n );\n\n const isCollapsed = collapsedParentIds.has(task.id);\n\n const getHierarchyLineColor = useCallback((columnDepth: number) => {\n return columnDepth % 2 === 0\n ? \"#93c5fd\"\n : \"var(--gantt-hierarchy-line-color)\";\n }, []);\n\n // Picker mode flags for this row\n const isPicking = selectingPredecessorFor != null;\n const isSourceRow = isPicking && selectingPredecessorFor === task.id;\n const [dependencySearchQuery, setDependencySearchQuery] = useState(\"\");\n const [highlightedDependencyIndex, setHighlightedDependencyIndex] = useState(0);\n\n // Chip data: always reflect the persisted business lag, not the visual calendar gap.\n const chips = useMemo(() => {\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 = getDependencyLag(dep);\n return { dep, lag, predecessorName: pred?.name ?? dep.taskId };\n });\n }, [task.dependencies, allTasks]);\n\n const linkWord = chips.length <= 4 ? \"связи\" : \"связей\";\n\n const dependencySearchCandidates = useMemo(() => {\n if (!isSourceRow) return [];\n\n const normalizedQuery = dependencySearchQuery.trim().toLowerCase();\n return allTasks\n .filter((candidate) => candidate.id !== task.id)\n .map((candidate) => {\n const number = taskNumberMap[candidate.id];\n const label = `${formatTaskNumberLabel(number)}${candidate.name}`;\n const matchingDependencies = dependencyPickMode === \"predecessor\"\n ? (task.dependencies ?? []).filter((dep) => dep.taskId === candidate.id)\n : (candidate.dependencies ?? []).filter((dep) => dep.taskId === task.id);\n return {\n task: candidate,\n label,\n linkedTypes: matchingDependencies.map((dep) => dep.type),\n isAlreadyLinked: matchingDependencies.length > 0,\n searchable: `${number ?? \"\"} ${candidate.name}`.toLowerCase(),\n };\n })\n .filter((candidate) =>\n normalizedQuery === \"\" ? true : candidate.searchable.includes(normalizedQuery)\n );\n }, [\n isSourceRow,\n dependencySearchQuery,\n allTasks,\n task.id,\n activeLinkType,\n dependencyPickMode,\n taskNumberMap,\n task.dependencies,\n ]);\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 useEffect(() => {\n if (!isSourceRow && dependencySearchQuery !== \"\") {\n setDependencySearchQuery(\"\");\n }\n }, [isSourceRow, dependencySearchQuery]);\n\n useEffect(() => {\n setHighlightedDependencyIndex(0);\n }, [dependencySearchQuery, isSourceRow, dependencyPickMode]);\n\n useEffect(() => {\n if (dependencySearchCandidates.length === 0) {\n setHighlightedDependencyIndex(0);\n return;\n }\n\n if (highlightedDependencyIndex > dependencySearchCandidates.length - 1) {\n setHighlightedDependencyIndex(dependencySearchCandidates.length - 1);\n }\n }, [dependencySearchCandidates, highlightedDependencyIndex]);\n\n useEffect(() => {\n if (isSourceRow && dependencySearchInputRef.current) {\n dependencySearchInputRef.current.focus();\n dependencySearchInputRef.current.select();\n }\n }, [isSourceRow, dependencyPickMode, activeLinkType]);\n\n useEffect(() => {\n if (!isSourceRow || dependencySearchCandidates.length === 0) {\n return;\n }\n\n const listElement = dependencySearchListRef.current;\n const activeElement = listElement?.querySelector<HTMLElement>(\n `.gantt-tl-dep-source-option[data-index=\"${highlightedDependencyIndex}\"]`\n );\n\n activeElement?.scrollIntoView({\n block: \"nearest\",\n });\n }, [isSourceRow, highlightedDependencyIndex, dependencySearchCandidates]);\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 → onTasksChange → 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 nameConfirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = \"autoedit\";\n setNameValue(task.name);\n setEditingColumnId('name');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editingTaskId, task.id, disableTaskNameEditing]);\n\n const handleNameClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n onScrollToTask?.(task.id);\n },\n [task.id, onRowClick, onScrollToTask],\n );\n\n const handleNameDoubleClick = useCallback(\n (e: React.MouseEvent) => {\n if (disableTaskNameEditing) return;\n e.stopPropagation();\n nameConfirmedRef.current = false; // Reset stale flag from any previous Enter-key save\n editTriggerRef.current = \"doubleclick\";\n setNameValue(task.name);\n setEditingColumnId('name');\n },\n [task.name, disableTaskNameEditing],\n );\n\n const handleRowKeyDown = useCallback(\n (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 nameConfirmedRef.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 setEditingColumnId('name');\n return;\n }\n },\n [editingName, disableTaskNameEditing, task.name],\n );\n\n const handleNameSave = useCallback(() => {\n if (nameConfirmedRef.current) {\n // Already saved via Enter key, skip blur handler\n nameConfirmedRef.current = false;\n return;\n }\n if (nameValue.trim()) {\n onTasksChange?.([{ ...task, name: nameValue.trim() }]);\n }\n setEditingColumnId(null);\n }, [nameValue, task, onTasksChange]);\n\n const handleNameCancel = useCallback(() => {\n setEditingColumnId(null);\n }, []);\n\n const handleNameKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n nameConfirmedRef.current = true; // Mark as saved to prevent blur from triggering again\n if (nameValue.trim()) {\n onTasksChange?.([{ ...task, name: nameValue.trim() }]);\n }\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleNameCancel();\n }\n },\n [nameValue, task, onTasksChange, handleNameCancel],\n );\n\n const handleDurationClick = useCallback(\n (e: React.MouseEvent) => {\n if (task.locked) return;\n e.stopPropagation();\n durationConfirmedRef.current = false;\n setDurationValue(\n isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate),\n );\n setEditingColumnId('duration');\n },\n [task.locked, normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone],\n );\n\n const applyDurationChange = useCallback((nextDuration: number) => {\n const normalizedDuration = Math.max(0, Math.round(nextDuration) || 0);\n setDurationValue(normalizedDuration);\n }, []);\n\n const handleDurationSave = useCallback(() => {\n if (durationConfirmedRef.current) {\n durationConfirmedRef.current = false;\n return;\n }\n const rounded = Math.round(durationValue) || 0;\n if (isMilestone && rounded > 0) {\n // Convert milestone → task\n onTasksChange?.([\n { ...task, type: 'task' as const, endDate: getEndDate(task.startDate, rounded) },\n ]);\n } else if (!isMilestone && rounded === 0) {\n // Convert task → milestone\n onTasksChange?.([\n { ...task, type: 'milestone' as const, endDate: task.startDate },\n ]);\n } else if (!isMilestone && rounded > 0) {\n onTasksChange?.([\n { ...task, endDate: getEndDate(task.startDate, rounded) },\n ]);\n }\n // isMilestone && rounded === 0 → no-op, just close\n setEditingColumnId(null);\n }, [durationValue, task, onTasksChange, getEndDate, isMilestone]);\n\n const handleDurationCancel = useCallback(() => {\n setDurationValue(isMilestone ? 0 : getDuration(normalizedTask.startDate, normalizedTask.endDate));\n setEditingColumnId(null);\n }, [normalizedTask.startDate, normalizedTask.endDate, getDuration, isMilestone]);\n\n const handleDurationAdjust = useCallback(\n (delta: number) => {\n applyDurationChange(durationValue + delta);\n },\n [applyDurationChange, durationValue],\n );\n\n const handleDurationKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (e.key === \"Enter\") {\n durationConfirmedRef.current = true;\n const rounded = Math.round(durationValue) || 0;\n if (isMilestone && rounded > 0) {\n // Convert milestone → task\n onTasksChange?.([\n { ...task, type: 'task' as const, endDate: getEndDate(task.startDate, rounded) },\n ]);\n } else if (!isMilestone && rounded === 0) {\n // Convert task → milestone\n onTasksChange?.([\n { ...task, type: 'milestone' as const, endDate: task.startDate },\n ]);\n } else if (!isMilestone && rounded > 0) {\n onTasksChange?.([\n { ...task, endDate: getEndDate(task.startDate, rounded) },\n ]);\n }\n // isMilestone && rounded === 0 → no-op, just close\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleDurationCancel();\n }\n },\n [durationValue, task, onTasksChange, handleDurationCancel, getEndDate, isMilestone],\n );\n\n const handleProgressClick = useCallback(\n (e: React.MouseEvent) => {\n if (task.locked) return;\n e.stopPropagation();\n progressConfirmedRef.current = false;\n setProgressValue(task.progress ?? 0);\n setEditingColumnId('progress');\n },\n [task.progress, task.locked],\n );\n\n const handleProgressSave = useCallback(() => {\n if (progressConfirmedRef.current) {\n progressConfirmedRef.current = false;\n return;\n }\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n\n // Cascade 100% or 0% progress to all children when parent is marked complete/reset\n if (\n (clampedValue === 100 || clampedValue === 0) &&\n isTaskParent(task.id, allTasks)\n ) {\n const children = getChildren(task.id, allTasks);\n const updatedTasks = [\n { ...task, progress: clampedValue },\n ...children.map((child) => ({ ...child, progress: clampedValue })),\n ];\n onTasksChange?.(updatedTasks);\n } else {\n onTasksChange?.([{ ...task, progress: clampedValue }]);\n }\n setEditingColumnId(null);\n }, [progressValue, task, onTasksChange, allTasks]);\n\n const handleProgressCancel = useCallback(() => {\n setEditingColumnId(null);\n }, []);\n\n const handleProgressAdjust = useCallback((delta: number) => {\n setProgressValue((current) =>\n Math.max(0, Math.min(100, current + delta)),\n );\n }, []);\n\n const handleProgressKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n e.stopPropagation(); // Prevent row-level keyboard handler from interfering\n if (e.key === \"Enter\") {\n progressConfirmedRef.current = true;\n const clampedValue = Math.max(0, Math.min(100, progressValue));\n\n // Cascade 100% or 0% progress to all children when parent is marked complete/reset\n if (\n (clampedValue === 100 || clampedValue === 0) &&\n isTaskParent(task.id, allTasks)\n ) {\n const children = getChildren(task.id, allTasks);\n const updatedTasks = [\n { ...task, progress: clampedValue },\n ...children.map((child) => ({\n ...child,\n progress: clampedValue,\n })),\n ];\n onTasksChange?.(updatedTasks);\n } else {\n onTasksChange?.([{ ...task, progress: clampedValue }]);\n }\n setEditingColumnId(null);\n } else if (e.key === \"Escape\") {\n handleProgressCancel();\n }\n },\n [progressValue, task, onTasksChange, handleProgressCancel, allTasks],\n );\n\n useEffect(() => {\n if (editingProgress && progressInputRef.current) {\n progressInputRef.current.focus();\n progressInputRef.current.select();\n }\n }, [editingProgress]);\n\n useEffect(() => {\n setDurationValue(getDuration(normalizedTask.startDate, normalizedTask.endDate));\n }, [normalizedTask.startDate, normalizedTask.endDate, getDuration]);\n\n useEffect(() => {\n if (editingDuration && durationInputRef.current) {\n durationInputRef.current.focus();\n durationInputRef.current.select();\n }\n }, [editingDuration]);\n\n const emitMilestoneDateChange = useCallback((nextDateISO: string) => {\n const alignedDate = businessDays\n ? alignToWorkingDay(new Date(`${nextDateISO}T00:00:00.000Z`), 1, weekendPredicate)\n : new Date(`${nextDateISO}T00:00:00.000Z`);\n\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n alignedDate,\n alignedDate,\n allTasks,\n businessDays,\n weekendPredicate\n );\n const normalized = normalizeTaskDatesForType({\n ...task,\n startDate: clampedRange.start.toISOString().split(\"T\")[0],\n endDate: clampedRange.end.toISOString().split(\"T\")[0],\n });\n const startDate = parseUTCDate(normalized.startDate);\n const endDate = parseUTCDate(normalized.endDate);\n\n onTasksChange?.([\n {\n ...normalized,\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n }, [task, onTasksChange, allTasks, businessDays, weekendPredicate]);\n\n // Both date pickers shift the whole task (preserving duration), same as drag-move\n // Also normalizes dates to ensure startDate is always before or equal to endDate\n const handleStartDateChange = useCallback(\n (newDateISO: string) => {\n if (!newDateISO) return;\n if (isMilestone) {\n emitMilestoneDateChange(newDateISO);\n return;\n }\n let nextEndISO: string;\n const normalizedInputStart = businessDays\n ? alignToWorkingDay(new Date(`${newDateISO}T00:00:00.000Z`), 1, weekendPredicate)\n : new Date(`${newDateISO}T00:00:00.000Z`);\n\n if (businessDays) {\n const duration = getDuration(task.startDate, task.endDate);\n nextEndISO = buildTaskRangeFromStart(\n normalizedInputStart,\n duration,\n true,\n weekendPredicate,\n 1\n ).end.toISOString().split(\"T\")[0];\n } else {\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n nextEndISO = new Date(normalizedInputStart.getTime() + durationMs).toISOString().split(\"T\")[0];\n }\n\n const { startDate: normalizedStart, endDate: normalizedEnd } =\n normalizeTaskDates(normalizedInputStart, nextEndISO);\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n new Date(`${normalizedStart}T00:00:00.000Z`),\n new Date(`${normalizedEnd}T00:00:00.000Z`),\n allTasks,\n businessDays,\n weekendPredicate\n );\n const startDate = clampedRange.start;\n const endDate = clampedRange.end;\n onTasksChange?.([\n {\n ...task,\n startDate: startDate.toISOString().split(\"T\")[0],\n endDate: endDate.toISOString().split(\"T\")[0],\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n },\n [task, onTasksChange, businessDays, getDuration, getEndDate, allTasks, weekendPredicate, isMilestone, emitMilestoneDateChange],\n );\n\n const handleEndDateChange = useCallback(\n (newDateISO: string) => {\n if (!newDateISO) return;\n if (isMilestone) {\n emitMilestoneDateChange(newDateISO);\n return;\n }\n let nextStartISO: string;\n const normalizedInputEnd = businessDays\n ? alignToWorkingDay(new Date(`${newDateISO}T00:00:00.000Z`), -1, weekendPredicate)\n : new Date(`${newDateISO}T00:00:00.000Z`);\n\n if (businessDays) {\n const duration = getDuration(task.startDate, task.endDate);\n nextStartISO = buildTaskRangeFromEnd(\n normalizedInputEnd,\n duration,\n true,\n weekendPredicate,\n -1\n ).start.toISOString().split(\"T\")[0];\n } else {\n const origStart = parseUTCDate(task.startDate);\n const origEnd = parseUTCDate(task.endDate);\n const durationMs = origEnd.getTime() - origStart.getTime();\n nextStartISO = new Date(normalizedInputEnd.getTime() - durationMs).toISOString().split(\"T\")[0];\n }\n\n const { startDate: normalizedStart, endDate: normalizedEnd } =\n normalizeTaskDates(nextStartISO, normalizedInputEnd);\n const clampedRange = clampTaskRangeForIncomingFS(\n task,\n new Date(`${normalizedStart}T00:00:00.000Z`),\n new Date(`${normalizedEnd}T00:00:00.000Z`),\n allTasks,\n businessDays,\n weekendPredicate\n );\n const startDate = clampedRange.start;\n const endDate = clampedRange.end;\n onTasksChange?.([\n {\n ...task,\n startDate: startDate.toISOString().split(\"T\")[0],\n endDate: endDate.toISOString().split(\"T\")[0],\n ...(task.dependencies && {\n dependencies: recalculateIncomingLags(\n task,\n startDate,\n endDate,\n allTasks,\n businessDays,\n weekendPredicate\n ),\n }),\n },\n ]);\n },\n [task, onTasksChange, businessDays, getDuration, weekendPredicate, allTasks, isMilestone, emitMilestoneDateChange],\n );\n\n const handleRowClickInternal = useCallback(() => {\n onRowClick?.(task.id);\n }, [task.id, onRowClick]);\n\n const handleNumberClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRowClick?.(task.id);\n },\n [task.id, onRowClick],\n );\n\n const handleToggleCollapse = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleCollapse?.(task.id);\n },\n [task.id, onToggleCollapse],\n );\n\n // Hierarchy handlers - promote/demote\n const handlePromote = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onPromoteTask?.(task.id);\n },\n [task.id, onPromoteTask],\n );\n\n const handleDemote = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n // The parent calculation is done in TaskList.tsx's handleDemoteWrapper,\n // which has access to the ordered visible task list and implements the\n // \"previous visible task becomes parent\" principle.\n // Pass empty string as placeholder — the wrapper ignores this value.\n onDemoteTask?.(task.id, \"\");\n },\n [task.id, onDemoteTask],\n );\n\n const handleApplyColor = useCallback(\n (color?: string) => {\n if (!onTasksChange) return;\n\n const descendantIds = new Set<string>();\n if (isParent) {\n const stack = getChildren(task.id, allTasks);\n while (stack.length > 0) {\n const current = stack.shift();\n if (!current || descendantIds.has(current.id)) continue;\n descendantIds.add(current.id);\n stack.push(...getChildren(current.id, allTasks));\n }\n }\n\n const updatedTasks: Task[] = [\n { ...task, color },\n ...allTasks\n .filter(candidate => descendantIds.has(candidate.id))\n .map(candidate => ({ ...candidate, color })),\n ];\n\n onTasksChange(updatedTasks);\n setColorMenuOpen(false);\n setContextMenuOpen(false);\n },\n [allTasks, isParent, onTasksChange, task],\n );\n\n // Dependency handlers\n const handleAddClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(task.id);\n },\n [task.id, onSetSelectingPredecessorFor],\n );\n\n const handlePredecessorPick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!isPicking || isSourceRow) return;\n if (!selectingPredecessorFor || !activeLinkType) return;\n if (dependencyPickMode === \"predecessor\") {\n onAddDependency?.(selectingPredecessorFor, task.id, activeLinkType);\n } else {\n onAddDependency?.(task.id, selectingPredecessorFor, activeLinkType);\n }\n },\n [\n isPicking,\n isSourceRow,\n selectingPredecessorFor,\n task.id,\n activeLinkType,\n dependencyPickMode,\n onAddDependency,\n ],\n );\n\n const handleCancelPicking = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onSetSelectingPredecessorFor?.(null);\n },\n [onSetSelectingPredecessorFor],\n );\n\n const handleSourceCellClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n handleCancelPicking(e);\n }\n },\n [handleCancelPicking],\n );\n\n const handleSearchPick = useCallback(\n (pickedTaskId: string) => {\n if (!activeLinkType) return;\n if (dependencyPickMode === \"predecessor\") {\n onAddDependency?.(task.id, pickedTaskId, activeLinkType);\n } else {\n onAddDependency?.(pickedTaskId, task.id, activeLinkType);\n }\n },\n [activeLinkType, dependencyPickMode, onAddDependency, task.id],\n );\n\n const handleSearchRemove = useCallback(\n (pickedTaskId: string) => {\n const matchingTypes = dependencyPickMode === \"predecessor\"\n ? (task.dependencies ?? [])\n .filter((dep) => dep.taskId === pickedTaskId)\n .map((dep) => dep.type)\n : ((allTasks.find((candidate) => candidate.id === pickedTaskId)?.dependencies ?? []))\n .filter((dep) => dep.taskId === task.id)\n .map((dep) => dep.type);\n\n for (const linkType of matchingTypes) {\n if (dependencyPickMode === \"predecessor\") {\n onRemoveDependency?.(task.id, pickedTaskId, linkType);\n } else {\n onRemoveDependency?.(pickedTaskId, task.id, linkType);\n }\n }\n },\n [allTasks, dependencyPickMode, onRemoveDependency, task.dependencies, task.id],\n );\n\n const sourcePickerContent = (\n <div\n className=\"gantt-tl-dep-source-picker\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"gantt-tl-dep-source-direction\">\n <button\n type=\"button\"\n className={`gantt-tl-dep-source-direction-btn${dependencyPickMode === \"successor\" ? \" gantt-tl-dep-source-direction-btn-active\" : \"\"}`}\n onClick={() => onSetDependencyPickMode?.(\"successor\")}\n >\n Последователь\n </button>\n <button\n type=\"button\"\n className={`gantt-tl-dep-source-direction-btn${dependencyPickMode === \"predecessor\" ? \" gantt-tl-dep-source-direction-btn-active\" : \"\"}`}\n onClick={() => onSetDependencyPickMode?.(\"predecessor\")}\n >\n Предшественник\n </button>\n </div>\n <div className=\"gantt-tl-dep-source-types\">\n {LINK_TYPE_ORDER.map((linkType) => {\n const Icon = LINK_TYPE_ICONS[linkType];\n return (\n <button\n key={linkType}\n type=\"button\"\n className={`gantt-tl-dep-source-type-btn${activeLinkType === linkType ? \" gantt-tl-dep-source-type-btn-active\" : \"\"}`}\n onClick={() => onSetActiveLinkType?.(linkType)}\n aria-label={`Выбрать тип связи ${linkType}`}\n title={linkType}\n >\n <Icon />\n <span>{LINK_TYPE_LABELS_RU[linkType]}</span>\n </button>\n );\n })}\n </div>\n <div className=\"gantt-tl-dep-source-picker-head\">\n <input\n ref={dependencySearchInputRef}\n type=\"text\"\n className=\"gantt-tl-dep-source-input\"\n placeholder={dependencyPickMode === \"predecessor\" ? \"Укажите предшественника\" : \"Укажите последователя\"}\n value={dependencySearchQuery}\n onChange={(e) => setDependencySearchQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n onSetSelectingPredecessorFor?.(null);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (dependencySearchCandidates.length > 0) {\n setHighlightedDependencyIndex((current) =>\n Math.min(current + 1, dependencySearchCandidates.length - 1)\n );\n }\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n if (dependencySearchCandidates.length > 0) {\n setHighlightedDependencyIndex((current) => Math.max(current - 1, 0));\n }\n return;\n }\n if (e.key === \"Enter\" && dependencySearchCandidates[highlightedDependencyIndex]) {\n e.preventDefault();\n const activeCandidate = dependencySearchCandidates[highlightedDependencyIndex];\n if (activeCandidate.isAlreadyLinked) {\n handleSearchRemove(activeCandidate.task.id);\n } else {\n handleSearchPick(activeCandidate.task.id);\n }\n }\n }}\n />\n </div>\n <div\n ref={dependencySearchListRef}\n className=\"gantt-tl-dep-source-list\"\n >\n {dependencySearchCandidates.length > 0 ? (\n dependencySearchCandidates.map(({ task: candidate, label, isAlreadyLinked }, index) => (\n <button\n key={candidate.id}\n type=\"button\"\n data-index={index}\n className={`gantt-tl-dep-source-option${index === highlightedDependencyIndex ? \" gantt-tl-dep-source-option-active\" : \"\"}${isAlreadyLinked ? \" gantt-tl-dep-source-option-linked\" : \"\"}`}\n onClick={() => {\n if (!isAlreadyLinked) {\n handleSearchPick(candidate.id);\n }\n }}\n onMouseEnter={() => setHighlightedDependencyIndex(index)}\n onKeyDown={(e) => {\n // Allow Delete/Backspace to remove linked items via keyboard\n if (isAlreadyLinked && (e.key === \"Delete\" || e.key === \"Backspace\")) {\n e.preventDefault();\n handleSearchRemove(candidate.id);\n }\n }}\n title={label}\n >\n <span className=\"gantt-tl-dep-source-option-label\">{label}</span>\n {isAlreadyLinked && (\n <span\n className=\"gantt-tl-dep-source-option-remove\"\n onClick={(e) => {\n e.stopPropagation();\n handleSearchRemove(candidate.id);\n }}\n aria-label={`Удалить связь с ${label}`}\n >\n ×\n </span>\n )}\n </button>\n ))\n ) : (\n <span className=\"gantt-tl-dep-source-hint\">Ничего не найдено</span>\n )}\n </div>\n </div>\n );\n\n // True when this row is the predecessor for the currently selected chip\n const isSelectedPredecessor =\n selectedChip != null && selectedChip.predecessorId === task.id;\n const isSelectedDependencyOwner =\n selectedChip != null && selectedChip.successorId === task.id;\n\n // Delete the selected dependency from the predecessor row's \"Удалить\" button\n const handleDeleteSelected = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!selectedChip) return;\n onRemoveDependency?.(\n selectedChip.successorId,\n selectedChip.predecessorId,\n selectedChip.linkType as LinkType,\n );\n onChipSelect?.(null);\n },\n [selectedChip?.successorId, selectedChip?.predecessorId, selectedChip?.linkType, onRemoveDependency, onChipSelect],\n );\n\n const startDateISO = toISODate(normalizedTask.startDate);\n const endDateISO = editingDuration\n ? getEndDate(normalizedTask.startDate, durationValue)\n : toISODate(normalizedTask.endDate);\n\n // --- Built-in cell JSX (referenced from resolvedColumns.map) ---\n const numberCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-number\"\n onClick={handleNumberClick}\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\">\n {taskNumber || rowIndex + 1}\n </span>\n </div>\n );\n\n const nameTriggerPaddingLeft =\n isParent\n ? `${nestingDepth * 20 + 28}px`\n : nestingDepth > 0\n ? `${nestingDepth * 20 + 8}px`\n : undefined;\n\n const nameInputPaddingLeft =\n nestingDepth > 0 ? `${nestingDepth * 20 + 8}px` : undefined;\n\n const nameCell = (\n <div className=\"gantt-tl-cell gantt-tl-cell-name\">\n {isChild && !editingName && (\n <>\n {!isFilterHideMode && (\n <>\n {/* Ancestor continuation lines — full-height vertical bars for each ongoing ancestor level */}\n {ancestorLineModes.map((mode, idx) =>\n mode ? (\n <React.Fragment key={idx}>\n <span\n data-testid={`gantt-tl-ancestor-connector-${idx}`}\n style={{\n position: \"absolute\",\n left: `${idx * 20 + 9}px`,\n top: 0,\n height: mode === \"half\" ? `${rowHeight / 2}px` : `${rowHeight}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(idx),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n {mode === \"half\" && (\n <span\n data-testid={`gantt-tl-ancestor-connector-cap-${idx}`}\n style={{\n position: \"absolute\",\n left: `${idx * 20 + 9}px`,\n top: `${rowHeight / 2 - 0.75}px`,\n width: \"5px\",\n height: \"1.5px\",\n background: getHierarchyLineColor(idx),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n </React.Fragment>\n ) : null\n )}\n {/* Vertical line from parent to last child position */}\n {nestingDepth > 0 && (\n <span\n data-testid=\"gantt-tl-child-connector-vertical\"\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 9}px`,\n top: 0,\n height:\n isLastChild && !hasVisibleChildren\n ? `${rowHeight / 2}px`\n : `${rowHeight}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth - 1),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n {/* Horizontal branch */}\n <span\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 9}px`,\n top: `${rowHeight / 2 - 0.75}px`,\n width: \"8px\",\n height: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth - 1),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n {/* End dot */}\n <span\n style={{\n position: \"absolute\",\n left: `${(nestingDepth - 1) * 20 + 15}px`,\n top: `${rowHeight / 2 - 2}px`,\n width: \"4px\",\n height: \"4px\",\n borderRadius: \"50%\",\n background: getHierarchyLineColor(nestingDepth - 1),\n pointerEvents: \"none\",\n }}\n />\n </>\n )}\n {isParent && !editingName && (\n <>\n {!isFilterHideMode && !isCollapsed && (\n <span\n style={{\n position: \"absolute\",\n left: `${nestingDepth * 20 + 9}px`,\n top: `${rowHeight / 2 + 7}px`,\n height: `${rowHeight / 2 - 7}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-collapse-btn ${isCollapsed ? \"gantt-tl-collapse-btn-collapsed\" : \"\"}`}\n onClick={handleToggleCollapse}\n style={{ left: `${nestingDepth * 20 + 1}px` }}\n aria-label={isCollapsed ? \"Expand children\" : \"Collapse children\"}\n >\n <ChevronRightIcon />\n </button>\n </>\n )}\n </>\n )}\n {!isChild && isParent && !editingName && (\n <>\n {!isFilterHideMode && !isCollapsed && (\n <span\n data-testid=\"gantt-tl-parent-connector-tail\"\n style={{\n position: \"absolute\",\n left: `${nestingDepth * 20 + 9}px`,\n top: `${rowHeight / 2 + 7}px`,\n height: `${rowHeight / 2 - 7}px`,\n width: \"1.5px\",\n background: getHierarchyLineColor(nestingDepth),\n borderRadius: \"1px\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <button\n type=\"button\"\n className={`gantt-tl-collapse-btn ${isCollapsed ? \"gantt-tl-collapse-btn-collapsed\" : \"\"}`}\n onClick={handleToggleCollapse}\n style={{ left: `${nestingDepth * 20 + 1}px` }}\n aria-label={isCollapsed ? \"Expand children\" : \"Collapse children\"}\n >\n <ChevronRightIcon />\n </button>\n </>\n )}\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 style={{ paddingLeft: nameInputPaddingLeft }}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <button\n type=\"button\"\n className={[\n \"gantt-tl-name-trigger\",\n disableTaskNameEditing ? \"gantt-tl-name-locked\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n title={task.name}\n onClick={handleNameClick}\n onDoubleClick={handleNameDoubleClick}\n style={{\n paddingLeft: nameTriggerPaddingLeft,\n paddingRight: task.color ? \"20px\" : undefined,\n }}\n >\n <span className=\"gantt-tl-name-trigger-text\">{task.name}</span>\n </button>\n )}\n {!editingName && task.color && (\n <span\n className=\"gantt-tl-name-color-stripe\"\n style={{ backgroundColor: task.color }}\n aria-hidden=\"true\"\n />\n )}\n {!editingName && (onInsertAfter || onDelete || onPromoteTask || onDemoteTask || onDuplicateTask || onTasksChange) && (\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(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate(),\n ),\n )\n .toISOString()\n .split(\"T\")[0];\n const endISO = new Date(\n Date.UTC(\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate() + 7,\n ),\n )\n .toISOString()\n .split(\"T\")[0];\n const newTask: Task = {\n id: crypto.randomUUID(),\n name: \"Новая задача\",\n startDate: todayISO,\n endDate: endISO,\n parentId: task.parentId,\n };\n onInsertAfter(task.id, newTask);\n }}\n aria-label=\"Вставить задачу после этой\"\n >\n <PlusIcon />\n </button>\n )}\n <HierarchyButton\n isChild={isChild}\n rowIndex={rowIndex}\n canDemote={canDemoteTask}\n onPromote={onPromoteTask ? handlePromote : undefined}\n onDemote={onDemoteTask ? handleDemote : undefined}\n />\n {(onDuplicateTask || onDelete || onTasksChange) && (\n <Popover open={contextMenuOpen} onOpenChange={(open) => {\n setContextMenuOpen(open);\n if (!open) setColorMenuOpen(false);\n }}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"gantt-tl-name-action-btn gantt-tl-action-context\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen((v) => !v);\n }}\n aria-label=\"Дополнительно\"\n >\n <VerticalDotsIcon />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"gantt-tl-context-menu\" portal={true} align=\"end\">\n {onTasksChange && (\n <div className=\"gantt-tl-context-menu-section\">\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item gantt-tl-context-menu-item-toggle\"\n onClick={(e) => {\n e.stopPropagation();\n setColorMenuOpen((value) => !value);\n }}\n aria-expanded={colorMenuOpen}\n >\n <span className=\"gantt-tl-context-menu-item-main\">\n {task.color && (\n <span\n className=\"gantt-tl-color-swatch gantt-tl-color-swatch-inline\"\n style={{ backgroundColor: task.color }}\n aria-hidden=\"true\"\n />\n )}\n Цвет\n </span>\n <ChevronRightIcon />\n </button>\n {colorMenuOpen && (\n <div className=\"gantt-tl-color-grid\">\n <button\n type=\"button\"\n className={`gantt-tl-color-swatch gantt-tl-color-swatch-clear${!task.color ? \" is-selected\" : \"\"}`}\n onClick={(e) => {\n e.stopPropagation();\n handleApplyColor(undefined);\n }}\n aria-label=\"Сбросить цвет\"\n title=\"Сбросить цвет\"\n >\n <span className=\"gantt-tl-color-swatch-clear-line\" />\n </button>\n {TASK_COLOR_PALETTE.map((paletteColor) => (\n <button\n key={paletteColor.value}\n type=\"button\"\n className={`gantt-tl-color-swatch${task.color === paletteColor.value ? \" is-selected\" : \"\"}`}\n style={{ backgroundColor: paletteColor.value }}\n onClick={(e) => {\n e.stopPropagation();\n handleApplyColor(paletteColor.value);\n }}\n aria-label={`Выбрать цвет ${paletteColor.label}`}\n title={paletteColor.label}\n />\n ))}\n </div>\n )}\n </div>\n )}\n {onDuplicateTask && (\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen(false);\n onDuplicateTask(task.id);\n }}\n >\n <CopyIcon />\n Дублировать\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n className=\"gantt-tl-context-menu-item gantt-tl-context-menu-item-danger\"\n onClick={(e) => {\n e.stopPropagation();\n setContextMenuOpen(false);\n onDelete(task.id);\n }}\n >\n <TrashIcon />\n Удалить задачу\n </button>\n )}\n </PopoverContent>\n </Popover>\n )}\n </div>\n )}\n </div>\n );\n\n const startDateCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-date\"\n onClick={(e) => e.stopPropagation()}\n >\n <DatePicker\n value={startDateISO}\n onChange={handleStartDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n isWeekend={weekendPredicate}\n businessDays={businessDays}\n />\n </div>\n );\n\n const endDateCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-date\"\n onClick={(e) => e.stopPropagation()}\n >\n <DatePicker\n value={endDateISO}\n onChange={handleEndDateChange}\n format=\"dd.MM.yy\"\n portal={true}\n disabled={task.locked}\n isWeekend={weekendPredicate}\n businessDays={businessDays}\n />\n </div>\n );\n\n const durationCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-duration\"\n onClick={handleDurationClick}\n >\n {editingDuration && (\n <div\n className=\"gantt-tl-number-editor\"\n onClick={(e) => e.stopPropagation()}\n >\n <Input\n ref={durationInputRef}\n type=\"number\"\n min={0}\n step={1}\n value={durationValue}\n onChange={(e) =>\n applyDurationChange(parseInt(e.target.value, 10) || 0)\n }\n onBlur={handleDurationSave}\n onKeyDown={handleDurationKeyDown}\n className=\"gantt-tl-number-input\"\n />\n <div className=\"gantt-tl-number-steppers\" aria-hidden=\"true\">\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleDurationAdjust(1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleDurationAdjust(-1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n </div>\n </div>\n )}\n <span\n style={\n editingDuration\n ? { visibility: \"hidden\", pointerEvents: \"none\" }\n : undefined\n }\n >\n {isMilestone ? '◆' : `${getDuration(normalizedTask.startDate, normalizedTask.endDate)}д`}\n </span>\n </div>\n );\n\n const progressCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-progress\"\n onClick={handleProgressClick}\n >\n {editingProgress && (\n <div\n className=\"gantt-tl-number-editor\"\n onClick={(e) => e.stopPropagation()}\n >\n <Input\n ref={progressInputRef}\n type=\"number\"\n min={0}\n max={100}\n step={1}\n value={progressValue}\n onChange={(e) =>\n setProgressValue(parseInt(e.target.value, 10) || 0)\n }\n onBlur={handleProgressSave}\n onKeyDown={handleProgressKeyDown}\n className=\"gantt-tl-number-input\"\n />\n <div className=\"gantt-tl-number-steppers\" aria-hidden=\"true\">\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleProgressAdjust(1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"gantt-tl-number-stepper\"\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleProgressAdjust(-1)}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n </div>\n </div>\n )}\n <span\n style={\n editingProgress\n ? { visibility: \"hidden\", pointerEvents: \"none\" }\n : task.progress === 100\n ? {\n backgroundColor: \"#17c864\",\n borderRadius: \"4px\",\n padding: \"2px 4px\",\n color: \"#ffffff\",\n }\n : undefined\n }\n >\n {task.progress\n ? Math.round(task.progress) === 100\n ? \"100\"\n : `${Math.round(task.progress)}%`\n : \"-\"}\n </span>\n </div>\n );\n\n const dependenciesCell = (\n <div\n className=\"gantt-tl-cell gantt-tl-cell-deps\"\n onClick={\n isSourceRow\n ? handleSourceCellClick\n : isPicking\n ? handlePredecessorPick\n : undefined\n }\n >\n {isSourceRow ? (\n <>\n <span\n className=\"gantt-tl-dep-source-hint\"\n onClick={handleCancelPicking}\n >\n Отменить\n </span>\n {sourcePickerContent}\n </>\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\">\n Связано с\n </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) => {\n e.stopPropagation();\n setOverflowOpen((v) => !v);\n }}\n >\n {chips.length} {linkWord}\n </button>\n </PopoverTrigger>\n <PopoverContent portal={true} align=\"start\">\n <div\n className=\"gantt-tl-dep-overflow-list\"\n onClick={(e) => e.stopPropagation()}\n >\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 taskNumber={taskNumber}\n predecessorName={predecessorName}\n predecessorTaskNumber={taskNumberMap[dep.taskId]}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n task={task}\n allTasks={allTasks}\n onTasksChange={onTasksChange}\n businessDays={businessDays}\n weekendPredicate={weekendPredicate}\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 taskNumber={taskNumber}\n predecessorName={chips[0].predecessorName}\n predecessorTaskNumber={taskNumberMap[chips[0].dep.taskId]}\n selectedChip={selectedChip}\n disableDependencyEditing={disableDependencyEditing}\n onChipSelect={onChipSelect}\n onRowClick={onRowClick}\n onScrollToTask={onScrollToTask}\n onRemoveDependency={onRemoveDependency}\n onChipSelectClear={() => onChipSelect?.(null)}\n task={task}\n allTasks={allTasks}\n onTasksChange={onTasksChange}\n businessDays={businessDays}\n weekendPredicate={weekendPredicate}\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 );\n\n const builtInCells: Record<string, React.ReactNode> = {\n number: numberCell,\n name: nameCell,\n startDate: startDateCell,\n endDate: endDateCell,\n duration: durationCell,\n progress: progressCell,\n dependencies: dependenciesCell,\n };\n\n return (\n <div\n data-filter-match={isFilterMatch ? 'true' : 'false'}\n className={[\n \"gantt-tl-row\",\n isFilterMatch ? \"gantt-tl-row-filter-match\" : \"\",\n isSelected ? \"gantt-tl-row-selected\" : \"\",\n isSelectedDependencyOwner ? \"gantt-tl-row-dependency-owner\" : \"\",\n isSelectedPredecessor ? \"gantt-tl-row-dependency-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 ]\n .filter(Boolean)\n .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 tabIndex={isSelected ? 0 : -1}\n >\n {resolvedColumns?.map(col => {\n const builtIn = builtInCells[col.id];\n if (builtIn) return <React.Fragment key={col.id}>{builtIn}</React.Fragment>;\n\n // Custom column\n const isEditing = editingColumnId === col.id;\n const editorFn = col.renderEditor;\n const columnContext = {\n task,\n rowIndex,\n isEditing,\n openEditor: () => {\n if (editorFn) setEditingColumnId(col.id);\n },\n closeEditor: () => {\n if (editingColumnId === col.id) setEditingColumnId(null);\n },\n updateTask: (patch: Partial<Task>) => {\n onTasksChange?.([{ ...task, ...patch } as Task]);\n setEditingColumnId(null);\n },\n };\n\n return (\n <div\n key={col.id}\n className=\"gantt-tl-cell gantt-tl-cell-custom\"\n data-column-id={`custom:${col.id}`}\n data-custom-column-id={col.id}\n data-custom-column-editing={isEditing ? \"true\" : \"false\"}\n data-testid={`custom-cell-${col.id}`}\n onClick={editorFn && !isEditing ? (e) => { e.stopPropagation(); setEditingColumnId(col.id); } : undefined}\n style={{ width: col.width ?? 120, minWidth: col.width ?? 120, flexShrink: 0 }}\n >\n {isEditing && editorFn ? (\n <div\n data-custom-column-editor={col.id}\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => e.stopPropagation()}\n >\n {editorFn(columnContext)}\n </div>\n ) : (\n col.renderCell(columnContext)\n )}\n </div>\n );\n })}\n </div>\n );\n },\n);\n\nTaskListRow.displayName = \"TaskListRow\";\nexport default TaskListRow;\n\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, useEffect, useRef } from 'react';\nimport { format, isValid, parse, addDays, addMonths, addYears, subMonths, subYears, subDays } 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 /** Optional predicate for custom weekend logic */\n isWeekend?: (date: Date) => boolean;\n /** Whether to use business days for +1/+7 buttons (default: true) */\n businessDays?: boolean;\n}\n\nconst segments = [\n { start: 0, end: 2, label: 'day', max: 31 },\n { start: 3, end: 5, label: 'month', max: 12 },\n { start: 6, end: 8, label: 'year', max: 99 },\n];\n\nconst shiftByBusinessDays = (\n startDate: Date,\n delta: number,\n weekendPredicate: (date: Date) => boolean\n): Date => {\n if (delta === 0) return startDate;\n\n const shifted = new Date(startDate);\n const step = delta > 0 ? 1 : -1;\n let remaining = Math.abs(delta);\n\n while (remaining > 0) {\n shifted.setUTCDate(shifted.getUTCDate() + step);\n if (!weekendPredicate(shifted)) {\n remaining--;\n }\n }\n\n return shifted;\n};\n\nconst snapToBusinessDay = (\n date: Date,\n direction: 1 | -1,\n weekendPredicate: (date: Date) => boolean\n): Date => {\n const snapped = new Date(date);\n while (weekendPredicate(snapped)) {\n snapped.setUTCDate(snapped.getUTCDate() + direction);\n }\n return snapped;\n};\n\nconst formatUTCDate = (date: Date, pattern: string): string => {\n const localDisplayDate = new Date(\n date.getUTCFullYear(),\n date.getUTCMonth(),\n date.getUTCDate()\n );\n return format(localDisplayDate, pattern);\n};\n\n/**\n * DatePicker component — shows formatted date as a button, opens calendar popup on click.\n * The popup includes a keyboard-navigable date input field above the calendar.\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 isWeekend,\n businessDays = true,\n}) => {\n const [open, setOpen] = useState(false);\n const [inputValue, setInputValue] = useState('');\n const [draftDate, setDraftDate] = useState<Date | undefined>(undefined);\n const dateInputRef = useRef<HTMLInputElement>(null);\n // Refs для синхронного отслеживания позиции — не зависят от DOM/rAF\n const segIdxRef = useRef(0); // текущий сегмент (0=day, 1=month, 2=year)\n const charPosRef = useRef(0); // позиция внутри сегмента (0 или 1)\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 const activeDate = draftDate ?? selectedDate;\n\n // Format Date for display on trigger button\n const displayValue = selectedDate\n ? formatUTCDate(selectedDate, displayFormat)\n : placeholder;\n\n // Sync inputValue with prop value\n useEffect(() => {\n if (value) {\n const d = new Date(value + 'T00:00:00Z');\n if (isValid(d)) {\n setInputValue(formatUTCDate(d, 'dd.MM.yy'));\n setDraftDate(undefined);\n }\n } else {\n setInputValue('');\n setDraftDate(undefined);\n }\n }, [value]);\n\n // Выделить сегмент по индексу (визуально)\n const selectSegByIdx = useCallback((idx: number) => {\n if (!dateInputRef.current) return;\n const seg = segments[idx] ?? segments[0];\n dateInputRef.current.setSelectionRange(seg.start, seg.end);\n }, []);\n\n // Auto-focus input when popup opens\n useEffect(() => {\n if (open) {\n setTimeout(() => {\n if (dateInputRef.current) {\n segIdxRef.current = 0;\n charPosRef.current = 0;\n dateInputRef.current.focus();\n selectSegByIdx(0);\n }\n }, 50);\n }\n }, [open, selectSegByIdx]);\n\n const handleFocus = () => {\n setTimeout(() => {\n segIdxRef.current = 0;\n charPosRef.current = 0;\n selectSegByIdx(0);\n }, 0);\n };\n\n const handleMouseDown = () => {\n setTimeout(() => {\n const pos = dateInputRef.current?.selectionStart ?? 0;\n const idx = segments.findIndex(s => pos >= s.start && pos <= s.end);\n segIdxRef.current = idx >= 0 ? idx : 0;\n charPosRef.current = 0;\n selectSegByIdx(segIdxRef.current);\n }, 0);\n };\n\n const handleShiftButtonMouseDown = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n },\n []\n );\n\n const updateFromDate = useCallback((newDate: Date) => {\n if (!isValid(newDate)) return;\n setInputValue(formatUTCDate(newDate, 'dd.MM.yy'));\n setDraftDate(newDate);\n }, []);\n\n const commitDate = useCallback((dateToCommit?: Date) => {\n const nextDate = dateToCommit ?? draftDate ?? selectedDate;\n if (!nextDate || !isValid(nextDate)) return;\n const iso = [\n nextDate.getUTCFullYear(),\n String(nextDate.getUTCMonth() + 1).padStart(2, '0'),\n String(nextDate.getUTCDate()).padStart(2, '0'),\n ].join('-');\n if (iso === value) return;\n onChange?.(iso);\n }, [draftDate, onChange, selectedDate, value]);\n\n const handleCalendarSelect = useCallback(\n (day: Date) => {\n const normalizedDay = businessDays && isWeekend && isWeekend(day)\n ? snapToBusinessDay(day, 1, isWeekend)\n : day;\n updateFromDate(normalizedDay);\n commitDate(normalizedDay);\n setOpen(false);\n },\n [businessDays, commitDate, isWeekend, updateFromDate]\n );\n\n const handleDayShift = useCallback(\n (delta: number) => {\n const base = activeDate ?? new Date();\n // Use business days if enabled and weekend predicate is available\n if (businessDays && isWeekend) {\n updateFromDate(shiftByBusinessDays(base, delta, isWeekend));\n } else {\n updateFromDate(addDays(base, delta));\n }\n },\n [activeDate, updateFromDate, businessDays, isWeekend]\n );\n\n const handleTriggerKeyDown = useCallback((e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n handleDayShift(1);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n handleDayShift(-1);\n }\n }, [disabled, handleDayShift]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!dateInputRef.current) return;\n const { value: inputVal } = dateInputRef.current;\n\n // Читаем сегмент из рефа — всегда актуально, даже при быстром вводе\n const segIdx = segIdxRef.current;\n const seg = segments[segIdx] ?? segments[0];\n\n if (e.key === 'Tab') return;\n\n if (e.key === 'Escape') {\n e.preventDefault(); e.stopPropagation();\n setOpen(false);\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault(); e.stopPropagation();\n commitDate();\n setOpen(false);\n return;\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault(); e.stopPropagation();\n const base = activeDate ?? new Date();\n let newDate = base;\n if (seg.label === 'day') newDate = e.key === 'ArrowUp' ? addDays(base, 1) : subDays(base, 1);\n if (seg.label === 'month') newDate = e.key === 'ArrowUp' ? addMonths(base, 1) : subMonths(base, 1);\n if (seg.label === 'year') newDate = e.key === 'ArrowUp' ? addYears(base, 1) : subYears(base, 1);\n if (businessDays && isWeekend && isWeekend(newDate)) {\n newDate = snapToBusinessDay(newDate, e.key === 'ArrowUp' ? 1 : -1, isWeekend);\n }\n charPosRef.current = 0;\n updateFromDate(newDate);\n requestAnimationFrame(() => selectSegByIdx(segIdx));\n return;\n }\n\n if (e.key === 'Backspace' || e.key === 'Delete') {\n e.preventDefault(); e.stopPropagation();\n const chars = inputVal.split('');\n for (let i = seg.start; i < seg.end; i++) chars[i] = '0';\n charPosRef.current = 0;\n setInputValue(chars.join(''));\n requestAnimationFrame(() => selectSegByIdx(segIdx));\n return;\n }\n\n if (e.key === 'ArrowRight') {\n e.preventDefault(); e.stopPropagation();\n const next = segIdx + 1 < segments.length ? segIdx + 1 : 0;\n segIdxRef.current = next;\n charPosRef.current = 0;\n selectSegByIdx(next);\n return;\n }\n\n if (e.key === 'ArrowLeft') {\n e.preventDefault(); e.stopPropagation();\n const prev = segIdx - 1 >= 0 ? segIdx - 1 : segments.length - 1;\n segIdxRef.current = prev;\n charPosRef.current = 0;\n selectSegByIdx(prev);\n return;\n }\n\n if (/^\\d$/.test(e.key)) {\n e.preventDefault(); e.stopPropagation();\n const charPos = charPosRef.current;\n const charIndex = seg.start + charPos;\n const chars = inputVal.split('');\n\n // На первой позиции сегмента — сбрасываем вторую цифру\n if (charPos === 0) {\n for (let i = seg.start + 1; i < seg.end; i++) chars[i] = '0';\n }\n chars[charIndex] = e.key;\n\n const segStr = chars.slice(seg.start, seg.end).join('');\n const segVal = parseInt(segStr, 10);\n\n if (seg.label === 'month' && charPos === 0 && parseInt(e.key) > 1) return;\n if (seg.label === 'day' && charPos === 0 && parseInt(e.key) > 3) return;\n if (segVal > seg.max) return;\n\n const updated = chars.join('');\n setInputValue(updated);\n\n const segLen = seg.end - seg.start;\n if (charPos + 1 < segLen) {\n // Ещё не заполнили сегмент — двигаемся внутри\n charPosRef.current = charPos + 1;\n requestAnimationFrame(() => {\n dateInputRef.current?.setSelectionRange(charIndex + 1, seg.end);\n });\n } else {\n // Сегмент заполнен — переходим к следующему\n const nextIdx = segIdx + 1 < segments.length ? segIdx + 1 : segIdx;\n segIdxRef.current = nextIdx;\n charPosRef.current = 0;\n requestAnimationFrame(() => selectSegByIdx(nextIdx));\n }\n\n const parsed = parse(updated, 'dd.MM.yy', new Date());\n if (isValid(parsed) && !updated.includes('00.00')) {\n const normalizedDate = new Date(Date.UTC(parsed.getFullYear(), parsed.getMonth(), parsed.getDate()));\n updateFromDate(\n businessDays && isWeekend && isWeekend(normalizedDate)\n ? snapToBusinessDay(normalizedDate, 1, isWeekend)\n : normalizedDate\n );\n }\n }\n }, [activeDate, businessDays, commitDate, isWeekend, selectSegByIdx, updateFromDate]);\n\n const handleOpenChange = useCallback((nextOpen: boolean) => {\n if (!nextOpen && open) {\n commitDate();\n }\n setOpen(nextOpen);\n }, [commitDate, open]);\n\n return (\n <Popover open={open} onOpenChange={disabled ? undefined : handleOpenChange}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className={`gantt-datepicker-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled}\n onKeyDown={handleTriggerKeyDown}\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 <div className=\"gantt-datepicker-input-row\">\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(-7)} tabIndex={-1}>-7</button>\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(-1)} tabIndex={-1}>-1</button>\n <input\n ref={dateInputRef}\n type=\"text\"\n className=\"gantt-datepicker-date-input\"\n value={inputValue}\n onChange={() => {}}\n onFocus={handleFocus}\n onMouseDown={handleMouseDown}\n onKeyDown={handleKeyDown}\n onBlur={() => {\n commitDate();\n }}\n spellCheck={false}\n autoComplete=\"off\"\n />\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(1)} tabIndex={-1}>+1</button>\n <button type=\"button\" className=\"gantt-datepicker-shift-btn\" onMouseDown={handleShiftButtonMouseDown} onClick={() => handleDayShift(7)} tabIndex={-1}>+7</button>\n </div>\n <Calendar\n mode=\"single\"\n selected={activeDate}\n onSelect={handleCalendarSelect}\n initialDate={activeDate}\n isWeekend={isWeekend}\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 isSameDay,\n getDay,\n isToday,\n isWeekend,\n isBefore,\n startOfDay,\n} from 'date-fns';\nimport { ru } from 'date-fns/locale';\nimport { createCustomDayPredicate } from '../../utils/dateUtils';\n\nexport interface CalendarProps {\n selected?: Date;\n onSelect?: (date: Date) => void;\n initialDate?: Date;\n mode?: 'single' | 'range';\n disabled?: boolean;\n /** Optional predicate for custom weekend logic (e.g., holidays, shift patterns) */\n isWeekend?: (date: Date) => boolean;\n}\n\n\nfunction getDayClassName(\n day: Date,\n selected: Date | undefined,\n isWeekendProp?: (date: Date) => boolean\n): 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 // Use custom predicate if provided, otherwise default\n if (isWeekendProp ? isWeekendProp(day) : 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 isWeekend: isWeekendProp,\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 // Day of week headers (Monday-first)\n const weekdayLabels = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];\n const weekdayHeaders = weekdayLabels.map((label, i) => (\n <div key={`wd-${i}`} className=\"gantt-cal-weekday\">\n {label}\n </div>\n ));\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(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));\n const className = getDayClassName(day, selected, isWeekendProp);\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(Date.UTC(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 {weekdayHeaders}\n {emptyCells}\n {dayCells}\n </div>\n </div>\n );\n },\n [selected, onSelect, disabled, isWeekendProp]\n );\n\n const renderedMonths = useMemo(\n () => months.map(renderMonth),\n [months, renderMonth]\n );\n\n return (\n <div ref={scrollRef} className=\"gantt-cal-container\">\n {renderedMonths}\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 nestingDepth?: number;\n}\n\nexport const NewTaskRow: React.FC<NewTaskRowProps> = ({\n rowHeight,\n onConfirm,\n onCancel,\n nestingDepth = 0,\n}) => {\n const [nameValue, setNameValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n const confirmedRef = useRef(false);\n const inputInnerPadding = 4;\n const levelOffset = nestingDepth > 0 ? nestingDepth * 20 + 8 : 0;\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 style={{\n left: `${Math.max(0, levelOffset - inputInnerPadding)}px`,\n width: levelOffset > 0 ? `calc(100% - ${Math.max(0, levelOffset - inputInnerPadding)}px)` : '100%',\n paddingLeft: `${inputInnerPadding}px`,\n }}\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","import type { Task } from '../../GanttChart';\nimport type { TaskListColumn } from './types';\n\nexport const BUILT_IN_COLUMN_WIDTHS: Record<string, number> = {\n number: 40,\n name: 200,\n startDate: 90,\n endDate: 90,\n duration: 60,\n progress: 50,\n dependencies: 120,\n actions: 80,\n};\n\nexport function createBuiltInColumns<TTask extends Task>(opts?: {\n businessDays?: boolean;\n}): TaskListColumn<TTask>[] {\n return [\n { id: 'number', header: '\\u2116', width: BUILT_IN_COLUMN_WIDTHS.number, renderCell: () => null },\n { id: 'name', header: '\\u0418\\u043C\\u044F', width: BUILT_IN_COLUMN_WIDTHS.name, renderCell: () => null },\n { id: 'startDate', header: '\\u041D\\u0430\\u0447\\u0430\\u043B\\u043E', width: BUILT_IN_COLUMN_WIDTHS.startDate, renderCell: () => null },\n { id: 'endDate', header: '\\u041E\\u043A\\u043E\\u043D\\u0447\\u0430\\u043D\\u0438\\u0435', width: BUILT_IN_COLUMN_WIDTHS.endDate, renderCell: () => null },\n { id: 'duration', header: opts?.businessDays ? '\\u0414\\u043D. (\\u0440)' : '\\u0414\\u043D.', width: BUILT_IN_COLUMN_WIDTHS.duration, renderCell: () => null },\n { id: 'progress', header: '%', width: BUILT_IN_COLUMN_WIDTHS.progress, renderCell: () => null },\n { id: 'dependencies', header: null, width: BUILT_IN_COLUMN_WIDTHS.dependencies, renderCell: () => null },\n ];\n}\n","import type { Task } from '../../GanttChart';\nimport type { TaskListColumn } from './types';\n\nexport function resolveTaskListColumns<TTask extends Task>(\n builtIn: TaskListColumn<TTask>[],\n custom: TaskListColumn<TTask>[],\n): TaskListColumn<TTask>[] {\n // Dev-mode duplicate check\n if (process.env.NODE_ENV !== 'production') {\n const ids = new Set<string>();\n for (const col of [...builtIn, ...custom]) {\n if (ids.has(col.id)) {\n console.error(`[TaskList] Duplicate column id: \"${col.id}\"`);\n }\n ids.add(col.id);\n }\n }\n\n if (custom.length === 0) {\n return [...builtIn];\n }\n\n const result = [...builtIn];\n // Track last insertion index per anchor to preserve order for same-anchor columns\n const lastInsertAfter: Map<string, number> = new Map();\n const lastInsertBefore: Map<string, number> = new Map();\n\n for (const col of custom) {\n let insertAt: number;\n\n if ('before' in col && (col as { before: string }).before) {\n const anchor = (col as { before: string }).before;\n // If we've already inserted before this anchor, insert at the same position\n // so the new column goes right before the same target\n if (lastInsertBefore.has(anchor)) {\n insertAt = lastInsertBefore.get(anchor)!;\n } else {\n const idx = result.findIndex(c => c.id === anchor);\n insertAt = idx !== -1 ? idx : result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertBefore.set(anchor, insertAt);\n } else if ('after' in col && (col as { after: string }).after) {\n const anchor = (col as { after: string }).after;\n // If we've already inserted after this anchor, insert after the last insertion\n if (lastInsertAfter.has(anchor)) {\n insertAt = lastInsertAfter.get(anchor)! + 1;\n } else {\n const idx = result.findIndex(c => c.id === anchor);\n insertAt = idx !== -1 ? idx + 1 : result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertAfter.set(anchor, insertAt);\n } else {\n // No anchor — insert after 'name', tracking for multiple no-anchor columns\n const anchor = '__no_anchor__';\n if (lastInsertAfter.has(anchor)) {\n insertAt = lastInsertAfter.get(anchor)! + 1;\n } else {\n insertAt = result.findIndex(c => c.id === 'name') + 1;\n }\n lastInsertAfter.set(anchor, insertAt);\n }\n\n result.splice(insertAt, 0, col);\n }\n\n return result;\n}\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","// Utility functions barrel export\nexport * from './dateUtils';\nexport * from './dependencyUtils';\nexport * from './expired';\nexport * from './geometry';\nexport * from './hierarchyOrder';\nexport * from './taskListReorder';\n","import { Task } from '../types';\nimport { parseUTCDate } from '../utils/dateUtils';\nimport { isTaskExpired } from '../utils/expired';\n\n/**\n * Predicate function for filtering tasks\n * @param task - Task to evaluate\n * @returns true to include task in filtered results, false to exclude\n */\nexport type TaskPredicate = (task: Task | undefined) => boolean;\n\n/**\n * Combine predicates with AND logic — all must be true\n * @param predicates - Array of predicate functions\n * @returns Composite predicate that returns true only if all predicates return true\n */\nexport const and = (...predicates: TaskPredicate[]): TaskPredicate =>\n (task) => predicates.every(p => p(task));\n\n/**\n * Combine predicates with OR logic — at least one must be true\n * @param predicates - Array of predicate functions\n * @returns Composite predicate that returns true if any predicate returns true\n */\nexport const or = (...predicates: TaskPredicate[]): TaskPredicate =>\n (task) => predicates.some(p => p(task));\n\n/**\n * Invert a predicate's logic\n * @param predicate - Predicate function to invert\n * @returns Composite predicate that returns the opposite of the input predicate\n */\nexport const not = (predicate: TaskPredicate): TaskPredicate =>\n (task) => !predicate(task);\n\n/**\n * Filter tasks that have no dependencies\n * @returns Predicate that returns true for tasks without dependencies array or with empty array\n */\nexport const withoutDeps = (): TaskPredicate =>\n (task) => !!task && (!task.dependencies || task.dependencies.length === 0);\n\n/**\n * Filter expired (overdue) tasks\n * @param referenceDate - Date to compare against (default: now)\n * @returns Predicate that returns true for tasks ending before reference date\n */\nexport const expired = (referenceDate: Date = new Date()): TaskPredicate =>\n (task) => isTaskExpired(task, referenceDate);\n\n/**\n * Filter tasks that intersect with a date range\n * Task intersects if: taskStart <= rangeEnd && taskEnd >= rangeStart\n * @param rangeStart - Start of the date range\n * @param rangeEnd - End of the date range\n * @returns Predicate that returns true for tasks intersecting the range\n */\nexport const inDateRange = (rangeStart: Date, rangeEnd: Date): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const taskStart = parseUTCDate(task.startDate);\n const taskEnd = parseUTCDate(task.endDate);\n return taskStart.getTime() <= rangeEnd.getTime() && taskEnd.getTime() >= rangeStart.getTime();\n };\n\n/**\n * Filter tasks by progress value range\n * @param min - Minimum progress value (0-100)\n * @param max - Maximum progress value (0-100)\n * @returns Predicate that returns true for tasks with progress in [min, max] range\n */\nexport const progressInRange = (min: number, max: number): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const progress = task.progress ?? 0;\n return progress >= min && progress <= max;\n };\n\n/**\n * Filter tasks by name substring search\n * @param substring - Text to search for in task name\n * @param caseSensitive - If false (default), search is case-insensitive\n * @returns Predicate that returns true for tasks with substring in name\n */\nexport const nameContains = (substring: string, caseSensitive = false): TaskPredicate =>\n (task) => {\n if (!task) return false;\n const name = task.name;\n const search = caseSensitive ? substring : substring.toLowerCase();\n const target = caseSensitive ? name : name.toLowerCase();\n return target.includes(search);\n };\n"],"mappings":"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","names":["addBusinessDays","getBusinessDaysCount","subtractBusinessDays","startOfMonth","addBusinessDays","getBusinessDaysCount","subtractBusinessDays","import_react","DAY_MS","DAY_MS","import_react","bounds","bar","isWeekend","getWeekBlocks","import_react","snapDirection","originalStart","duration","dayWidth","getUTCDayDifference","currentTask","import_jsx_runtime","React","isWeekend","import_react","import_jsx_runtime","import_react","import_jsx_runtime","arePropsEqual","React","import_jsx_runtime","import_react","import_jsx_runtime","React","lines","taskMap","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","isWeekend","import_jsx_runtime","import_jsx_runtime","DAY_MS","effectiveLag","React","isWeekend","import_react","import_jsx_runtime","import_jsx_runtime","LINK_TYPE_ORDER","getAllDescendants","isWeekend","tasks","React","import_jsx_runtime","isWeekend","tasks","import_react","import_jsx_runtime","React"]}