gantt-lib 0.60.0 → 0.60.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.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
+ import { T as Task$1, V as ValidationResult } from './index-CliEEiHA.js';
3
+ export { D as DAY_MS, a as DependencyError, G as GanttDateRange, b as GridConfig, c as GridLine, L as LinkType, M as MonthSpan, d as TaskBarGeometry, W as WeekendBlock, e as alignToWorkingDay, f as areTasksHierarchicallyRelated, g as buildAdjacencyList, h as buildTaskRangeFromEnd, i as buildTaskRangeFromStart, j as calculateSuccessorDate, k as cascadeByLinks, l as clampTaskRangeForIncomingFS, m as computeLagFromDates, n as computeParentDates, o as computeParentProgress, p as detectCycles, q as findParentId, r as getAllDependencyEdges, s as getAllDescendants, t as getBusinessDayOffset, u as getChildren, v as getDependencyLag, w as getSuccessorChain, x as getTaskDuration, y as getTransitiveCascadeChain, z as isAncestorTask, A as isTaskParent, B as moveTaskRange, C as normalizeDependencyLag, E as normalizeUTCDate, F as parseDateOnly, H as recalculateIncomingLags, I as reflowTasksOnModeSwitch, J as removeDependenciesBetweenTasks, K as shiftBusinessDayOffset, N as universalCascade, O as validateDependencies } from './index-CliEEiHA.js';
2
4
  import * as RadixPopover from '@radix-ui/react-popover';
3
5
 
4
6
  /**
@@ -233,148 +235,6 @@ declare function addBusinessDays(startDate: string | Date, businessDays: number,
233
235
  */
234
236
  declare function subtractBusinessDays(endDate: string | Date, businessDays: number, weekendPredicate: (date: Date) => boolean): string;
235
237
 
236
- /**
237
- * Dependency link types following PM standard
238
- * - FS (Finish-to-Start): Predecessor must finish before successor starts
239
- * - SS (Start-to-Start): Predecessor must start before successor starts
240
- * - FF (Finish-to-Finish): Predecessor must finish before successor finishes
241
- * - SF (Start-to-Finish): Predecessor must start before successor finishes
242
- */
243
- type LinkType = 'FS' | 'SS' | 'FF' | 'SF';
244
- /**
245
- * Single dependency relationship (predecessor link)
246
- */
247
- interface TaskDependency$1 {
248
- /** ID of the predecessor task */
249
- taskId: string;
250
- /** Type of link: FS (finish-to-start), SS, FF, SF */
251
- type: LinkType;
252
- /** Lag in days (positive or negative integer) */
253
- lag: number;
254
- }
255
- /**
256
- * Error or warning from dependency validation
257
- */
258
- interface DependencyError {
259
- /** Type of error */
260
- type: 'cycle' | 'constraint' | 'missing-task';
261
- /** ID of the task with the error */
262
- taskId: string;
263
- /** Human-readable error message */
264
- message: string;
265
- /** Related task IDs (e.g., cycle path, referenced tasks) */
266
- relatedTaskIds?: string[];
267
- }
268
- /**
269
- * Result of dependency validation
270
- */
271
- interface ValidationResult {
272
- /** True if no errors found */
273
- isValid: boolean;
274
- /** Array of errors/warnings (empty if valid) */
275
- errors: DependencyError[];
276
- }
277
- /**
278
- * Task data structure for Gantt chart
279
- */
280
- interface Task$1 {
281
- /** Unique identifier for the task */
282
- id: string;
283
- /** Display name of the task */
284
- name: string;
285
- /** Task start date (ISO string or Date object) */
286
- startDate: string | Date;
287
- /** Task end date (ISO string or Date object) */
288
- endDate: string | Date;
289
- /** Optional color for task bar visualization */
290
- color?: string;
291
- /** Optional parent task ID for hierarchy relationship */
292
- parentId?: string;
293
- /**
294
- * Optional progress value from 0-100
295
- * - Decimal values are allowed and rounded to nearest integer for display
296
- * - Values are clamped to 0-100 range
297
- * - Undefined or 0 means no progress is displayed
298
- * - Progress is visual-only, no user interaction
299
- */
300
- progress?: number;
301
- /**
302
- * Optional flag indicating if task is accepted
303
- * - Only meaningful when progress is 100%
304
- * - Affects the color of the progress bar (green for accepted, yellow for completed)
305
- */
306
- accepted?: boolean;
307
- /**
308
- * Optional array of predecessor dependencies
309
- * Each dependency specifies a predecessor task, link type, and optional lag
310
- */
311
- dependencies?: TaskDependency$1[];
312
- /**
313
- * Optional flag to prevent drag and resize interactions.
314
- * When true, the task bar cannot be moved or resized.
315
- * Independent of accepted/progress — consumer controls both separately.
316
- */
317
- locked?: boolean;
318
- }
319
- /**
320
- * Date range for Gantt chart display
321
- */
322
- interface GanttDateRange {
323
- /** Start date of the visible range */
324
- start: Date;
325
- /** End date of the visible range */
326
- end: Date;
327
- }
328
- /**
329
- * Task bar positioning and dimensions
330
- */
331
- interface TaskBarGeometry {
332
- /** Left position in pixels */
333
- left: number;
334
- /** Width in pixels */
335
- width: number;
336
- }
337
- /**
338
- * Grid configuration for layout calculations
339
- */
340
- interface GridConfig {
341
- /** Width of each day column in pixels */
342
- dayWidth: number;
343
- /** Height of each task row in pixels */
344
- rowHeight: number;
345
- }
346
- /**
347
- * Represents a month span in the calendar header
348
- */
349
- interface MonthSpan {
350
- /** First day of the month (UTC) */
351
- month: Date;
352
- /** Number of days this month spans in the visible range */
353
- days: number;
354
- /** Start index in the date range array */
355
- startIndex: number;
356
- }
357
- /**
358
- * Represents a vertical grid line
359
- */
360
- interface GridLine {
361
- /** X position in pixels */
362
- x: number;
363
- /** True if this line is at the start of a month */
364
- isMonthStart: boolean;
365
- /** True if this line is at the start of a week (Monday) */
366
- isWeekStart: boolean;
367
- }
368
- /**
369
- * Represents a weekend background block
370
- */
371
- interface WeekendBlock {
372
- /** Left position in pixels */
373
- left: number;
374
- /** Width in pixels */
375
- width: number;
376
- }
377
-
378
238
  /**
379
239
  * Predicate function for filtering tasks
380
240
  * @param task - Task to evaluate
@@ -1003,234 +863,6 @@ interface UseTaskDragReturn {
1003
863
  */
1004
864
  declare const useTaskDrag: (options: UseTaskDragOptions) => UseTaskDragReturn;
1005
865
 
1006
- /**
1007
- * Pure date math utilities for the core scheduling module.
1008
- * Zero React/DOM/date-fns dependencies.
1009
- *
1010
- * Functions moved from:
1011
- * - dependencyUtils.ts: normalizeUTCDate, parseDateOnly, getBusinessDayOffset, shiftBusinessDayOffset, DAY_MS
1012
- * - dateUtils.ts: getBusinessDaysCount, addBusinessDays, subtractBusinessDays
1013
- */
1014
- declare const DAY_MS: number;
1015
- /**
1016
- * Normalize a Date to UTC midnight (hours/minutes/seconds zeroed).
1017
- */
1018
- declare function normalizeUTCDate(date: Date): Date;
1019
- /**
1020
- * Parse a date string or Date object to a UTC midnight Date.
1021
- * Handles ISO strings like "2025-01-15" by appending T00:00:00.000Z.
1022
- */
1023
- declare function parseDateOnly(date: string | Date): Date;
1024
- /**
1025
- * Compute the business-day offset between two dates.
1026
- * Steps through each calendar day, counting only non-weekend days.
1027
- * Returns a positive number if toDate > fromDate, negative if toDate < fromDate.
1028
- */
1029
- declare function getBusinessDayOffset(fromDate: Date, toDate: Date, weekendPredicate: (date: Date) => boolean): number;
1030
- /**
1031
- * Shift a date by a business-day offset, skipping weekends.
1032
- */
1033
- declare function shiftBusinessDayOffset(date: Date, offset: number, weekendPredicate: (date: Date) => boolean): Date;
1034
- /**
1035
- * Snap a date to the nearest working day in the given direction.
1036
- */
1037
- declare function alignToWorkingDay(date: Date, direction: 1 | -1, weekendPredicate: (date: Date) => boolean): Date;
1038
- /**
1039
- * Get task duration in days (inclusive).
1040
- * If businessDays mode, counts business days using weekendPredicate.
1041
- * Otherwise, counts calendar days.
1042
- */
1043
- declare function getTaskDuration(startDate: string | Date, endDate: string | Date, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): number;
1044
-
1045
- /**
1046
- * Dependency calculation functions.
1047
- * Moved from dependencyUtils.ts — verbatim implementations.
1048
- * Zero React/DOM/date-fns imports.
1049
- */
1050
-
1051
- /**
1052
- * Get lag value from dependency, defaulting to 0.
1053
- */
1054
- declare function getDependencyLag(dep: Pick<TaskDependency$1, 'lag'>): number;
1055
- /**
1056
- * Normalize lag for FS links — clamp to >= -predecessorDuration.
1057
- */
1058
- declare function normalizeDependencyLag(linkType: LinkType, lag: number, predecessorStart: Date, predecessorEnd: Date, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): number;
1059
- /**
1060
- * Compute lag (in days) from actual predecessor/successor dates.
1061
- * This is the single source of truth for lag semantics.
1062
- *
1063
- * Semantics (lag=0 = natural, gap-free connection):
1064
- * - FS: lag = succStart - predEnd - 1 (adjacent days = 0)
1065
- * - SS: lag = succStart - predStart
1066
- * - FF: lag = succEnd - predEnd
1067
- * - SF: lag = succEnd - predStart + 1 (symmetric to FS)
1068
- */
1069
- declare function computeLagFromDates(linkType: LinkType, predStart: Date, predEnd: Date, succStart: Date, succEnd: Date, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): number;
1070
- /**
1071
- * Calculate successor date based on predecessor dates, link type, and lag.
1072
- *
1073
- * Link type semantics:
1074
- * - FS: Successor start = Predecessor end + lag + 1 day (lag=0 -> next day)
1075
- * - SS: Successor start = Predecessor start + lag
1076
- * - FF: Successor end = Predecessor end + lag
1077
- * - SF: Successor end = Predecessor start + lag - 1 day (lag=0 -> day before)
1078
- */
1079
- declare function calculateSuccessorDate(predecessorStart: Date, predecessorEnd: Date, linkType: LinkType, lag?: number, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): Date;
1080
-
1081
- /**
1082
- * Cascade engine functions.
1083
- * Moved from dependencyUtils.ts — verbatim implementations.
1084
- * Zero React/DOM/date-fns imports.
1085
- */
1086
-
1087
- /**
1088
- * Get successor tasks of a dragged task using BFS, filtered by link type(s).
1089
- */
1090
- declare function getSuccessorChain(draggedTaskId: string, allTasks: Task$1[], linkTypes?: LinkType[]): Task$1[];
1091
- /**
1092
- * Cascade successors by actual link constraints (BFS, constraint-based).
1093
- */
1094
- declare function cascadeByLinks(movedTaskId: string, newStart: Date, newEnd: Date, allTasks: Task$1[], skipChildCascade?: boolean): Task$1[];
1095
- /**
1096
- * Get transitive closure of successors for cascading.
1097
- */
1098
- declare function getTransitiveCascadeChain(changedTaskId: string, allTasks: Task$1[], firstLevelLinkTypes: LinkType[]): Task$1[];
1099
- /**
1100
- * Universal cascade engine that propagates a moved task's new position through
1101
- * the entire dependency+hierarchy graph using BFS with change detection.
1102
- */
1103
- declare function universalCascade(movedTask: Task$1, newStart: Date, newEnd: Date, allTasks: Task$1[], businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): Task$1[];
1104
- /**
1105
- * Recalculate all task dates when switching between business/calendar day modes.
1106
- */
1107
- declare function reflowTasksOnModeSwitch(sourceTasks: Task$1[], toBusinessDays: boolean, weekendPredicate: (date: Date) => boolean): Task$1[];
1108
-
1109
- /**
1110
- * High-level schedule command functions.
1111
- * Moved from dependencyUtils.ts — verbatim implementations.
1112
- * Zero React/DOM/date-fns imports.
1113
- */
1114
-
1115
- /**
1116
- * Build a task range (start/end dates) from a start date and duration.
1117
- */
1118
- declare function buildTaskRangeFromStart(startDate: Date, duration: number, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean, snapDirection?: 1 | -1): {
1119
- start: Date;
1120
- end: Date;
1121
- };
1122
- /**
1123
- * Build a task range (start/end dates) from an end date and duration.
1124
- */
1125
- declare function buildTaskRangeFromEnd(endDate: Date, duration: number, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean, snapDirection?: 1 | -1): {
1126
- start: Date;
1127
- end: Date;
1128
- };
1129
- /**
1130
- * Move a task range to a new start date, preserving duration.
1131
- */
1132
- declare function moveTaskRange(originalStart: string | Date, originalEnd: string | Date, proposedStart: Date, businessDays?: boolean, weekendPredicate?: (date: Date) => boolean, snapDirection?: 1 | -1): {
1133
- start: Date;
1134
- end: Date;
1135
- };
1136
- /**
1137
- * Clamp task range start date based on incoming FS dependencies.
1138
- */
1139
- declare function clampTaskRangeForIncomingFS(task: Pick<Task$1, 'dependencies'>, proposedStart: Date, proposedEnd: Date, allTasks: Task$1[], businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): {
1140
- start: Date;
1141
- end: Date;
1142
- };
1143
- /**
1144
- * Recalculate incoming dependency lags after a task's dates change.
1145
- */
1146
- declare function recalculateIncomingLags(task: Task$1, newStartDate: Date, newEndDate: Date, allTasks: Task$1[], businessDays?: boolean, weekendPredicate?: (date: Date) => boolean): NonNullable<Task$1['dependencies']>;
1147
-
1148
- /**
1149
- * Dependency validation and cycle detection.
1150
- * Moved from dependencyUtils.ts — verbatim implementations.
1151
- * Zero React/DOM/date-fns imports.
1152
- */
1153
-
1154
- /**
1155
- * Build adjacency list for dependency graph (task -> successors)
1156
- */
1157
- declare function buildAdjacencyList(tasks: Task$1[]): Map<string, string[]>;
1158
- /**
1159
- * Detect circular dependencies using depth-first search
1160
- */
1161
- declare function detectCycles(tasks: Task$1[]): {
1162
- hasCycle: boolean;
1163
- cyclePath?: string[];
1164
- };
1165
- /**
1166
- * Validate all dependencies in the task list
1167
- */
1168
- declare function validateDependencies(tasks: Task$1[]): ValidationResult;
1169
-
1170
- /**
1171
- * Hierarchy scheduling functions.
1172
- * Moved from dependencyUtils.ts — verbatim implementations.
1173
- * Zero React/DOM/date-fns imports.
1174
- */
1175
-
1176
- /**
1177
- * Get all child tasks of a parent task.
1178
- * Returns tasks where task.parentId === parentId.
1179
- */
1180
- declare function getChildren(parentId: string, tasks: Task$1[]): Task$1[];
1181
- /**
1182
- * Check if a task is a parent (has children).
1183
- * Returns true if any task has this task as parentId.
1184
- */
1185
- declare function isTaskParent(taskId: string, tasks: Task$1[]): boolean;
1186
- /**
1187
- * Compute parent task dates from children.
1188
- * Returns { startDate, endDate } where:
1189
- * - startDate = min(children.startDate) or own startDate if no children
1190
- * - endDate = max(children.endDate) or own endDate if no children
1191
- */
1192
- declare function computeParentDates(parentId: string, tasks: Task$1[]): {
1193
- startDate: Date;
1194
- endDate: Date;
1195
- };
1196
- /**
1197
- * Compute parent task progress from children (weighted average by duration).
1198
- * Returns 0 if no children.
1199
- * Progress is rounded to 1 decimal place.
1200
- */
1201
- declare function computeParentProgress(parentId: string, tasks: Task$1[]): number;
1202
- /**
1203
- * Get all descendant tasks of a parent task (transitive closure of children).
1204
- * Returns all tasks where task.parentId is in the hierarchy of the parent.
1205
- */
1206
- declare function getAllDescendants(parentId: string, tasks: Task$1[]): Task$1[];
1207
- /**
1208
- * Get all dependency edges for rendering.
1209
- * Returns array of { predecessorId, successorId, type, lag }
1210
- */
1211
- declare function getAllDependencyEdges(tasks: Task$1[]): Array<{
1212
- predecessorId: string;
1213
- successorId: string;
1214
- type: 'FS' | 'SS' | 'FF' | 'SF';
1215
- lag: number;
1216
- }>;
1217
- /**
1218
- * Remove dependencies between two tasks in both directions.
1219
- */
1220
- declare function removeDependenciesBetweenTasks(taskId1: string, taskId2: string, tasks: Task$1[]): Task$1[];
1221
- /**
1222
- * Find the parent ID of a task.
1223
- */
1224
- declare function findParentId(taskId: string, tasks: Task$1[]): string | undefined;
1225
- /**
1226
- * Returns true when ancestorId is an ancestor of taskId in the current hierarchy.
1227
- */
1228
- declare function isAncestorTask(ancestorId: string, taskId: string, tasks: Task$1[]): boolean;
1229
- /**
1230
- * Returns true when tasks are in the same ancestry chain.
1231
- */
1232
- declare function areTasksHierarchicallyRelated(taskId1: string, taskId2: string, tasks: Task$1[]): boolean;
1233
-
1234
866
  /**
1235
867
  * Checks whether a task is behind the expected progress for the current date.
1236
868
  * Uses the same progress-based rule as expired task highlighting in TaskRow.
@@ -1419,4 +1051,4 @@ interface VisibleReorderPosition {
1419
1051
  */
1420
1052
  declare function getVisibleReorderPosition(orderedTasks: TaskLike[], visibleTasks: TaskLike[], movedTaskId: string, originVisibleIndex: number, dropVisibleIndex: number): VisibleReorderPosition | null;
1421
1053
 
1422
- export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DAY_MS, DatePicker, type DatePickerProps, type DependencyError, DragGuideLines, GanttChart, type GanttChartHandle, type GanttChartProps, type GanttDateRange, GridBackground, type GridConfig, type GridLine, Input, type InputProps, type LinkType, type MonthBlock, type MonthSpan, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskBarGeometry, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, type ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type WeekendBlock, type YearSpan, addBusinessDays, alignToWorkingDay, and, areTasksHierarchicallyRelated, buildAdjacencyList, buildTaskRangeFromEnd, buildTaskRangeFromStart, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMonthGridLines, calculateOrthogonalPath, calculateSuccessorDate, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, cascadeByLinks, clampTaskRangeForIncomingFS, computeLagFromDates, computeParentDates, computeParentProgress, createCustomDayPredicate, createDateKey, detectCycles, detectEdgeZone, expired, findParentId, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getAllDependencyEdges, getAllDescendants, getBusinessDayOffset, getBusinessDaysCount, getChildren, getCursorForPosition, getDayOffset, getDependencyLag, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getSuccessorChain, getTaskDuration, getTransitiveCascadeChain, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isAncestorTask, isTaskExpired, isTaskParent, isToday, isWeekend, moveTaskRange, nameContains, normalizeDependencyLag, normalizeHierarchyTasks, normalizeTaskDates, normalizeUTCDate, not, or, parseDateOnly, parseUTCDate, pixelsToDate, progressInRange, recalculateIncomingLags, reflowTasksOnModeSwitch, removeDependenciesBetweenTasks, shiftBusinessDayOffset, subtractBusinessDays, universalCascade, useTaskDrag, validateDependencies, withoutDeps };
1054
+ export { type BuiltInTaskListColumnId, Button, type ButtonProps, Calendar, type CalendarProps, type CustomDayConfig, type CustomDayPredicateConfig, DatePicker, type DatePickerProps, DragGuideLines, GanttChart, type GanttChartHandle, type GanttChartProps, GridBackground, Input, type InputProps, type MonthBlock, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type Task, type TaskDependency, TaskList, type TaskListColumn, type TaskListColumnContext, type TaskListProps, type TaskPredicate, TaskRow, TimeScaleHeader, TodayIndicator, ValidationResult, type VisibleReorderPosition, type WeekBlock, type WeekSpan, type YearSpan, addBusinessDays, and, calculateBezierPath, calculateDependencyPath, calculateGridLines, calculateGridWidth, calculateMonthGridLines, calculateOrthogonalPath, calculateTaskBar, calculateWeekGridLines, calculateWeekendBlocks, createCustomDayPredicate, createDateKey, detectEdgeZone, expired, flattenHierarchy, formatDateLabel, formatDateRangeLabel, getBusinessDaysCount, getCursorForPosition, getDayOffset, getMonthBlocks, getMonthDays, getMonthSpans, getMultiMonthDays, getVisibleReorderPosition, getWeekBlocks, getWeekSpans, getYearSpans, inDateRange, isTaskExpired, isToday, isWeekend, nameContains, normalizeHierarchyTasks, normalizeTaskDates, not, or, parseUTCDate, pixelsToDate, progressInRange, subtractBusinessDays, useTaskDrag, withoutDeps };
package/dist/index.js CHANGED
@@ -3329,6 +3329,7 @@ var DatePicker = ({
3329
3329
  }) => {
3330
3330
  const [open, setOpen] = (0, import_react9.useState)(false);
3331
3331
  const [inputValue, setInputValue] = (0, import_react9.useState)("");
3332
+ const [draftDate, setDraftDate] = (0, import_react9.useState)(void 0);
3332
3333
  const dateInputRef = (0, import_react9.useRef)(null);
3333
3334
  const segIdxRef = (0, import_react9.useRef)(0);
3334
3335
  const charPosRef = (0, import_react9.useRef)(0);
@@ -3337,13 +3338,18 @@ var DatePicker = ({
3337
3338
  const d = /* @__PURE__ */ new Date(value + "T00:00:00Z");
3338
3339
  return (0, import_date_fns3.isValid)(d) ? d : void 0;
3339
3340
  })();
3341
+ const activeDate = draftDate ?? selectedDate;
3340
3342
  const displayValue = selectedDate ? formatUTCDate(selectedDate, displayFormat) : placeholder;
3341
3343
  (0, import_react9.useEffect)(() => {
3342
3344
  if (value) {
3343
3345
  const d = /* @__PURE__ */ new Date(value + "T00:00:00Z");
3344
- if ((0, import_date_fns3.isValid)(d)) setInputValue(formatUTCDate(d, "dd.MM.yy"));
3346
+ if ((0, import_date_fns3.isValid)(d)) {
3347
+ setInputValue(formatUTCDate(d, "dd.MM.yy"));
3348
+ setDraftDate(void 0);
3349
+ }
3345
3350
  } else {
3346
3351
  setInputValue("");
3352
+ setDraftDate(void 0);
3347
3353
  }
3348
3354
  }, [value]);
3349
3355
  const selectSegByIdx = (0, import_react9.useCallback)((idx) => {
@@ -3388,31 +3394,38 @@ var DatePicker = ({
3388
3394
  const updateFromDate = (0, import_react9.useCallback)((newDate) => {
3389
3395
  if (!(0, import_date_fns3.isValid)(newDate)) return;
3390
3396
  setInputValue(formatUTCDate(newDate, "dd.MM.yy"));
3397
+ setDraftDate(newDate);
3398
+ }, []);
3399
+ const commitDate = (0, import_react9.useCallback)((dateToCommit) => {
3400
+ const nextDate = dateToCommit ?? draftDate ?? selectedDate;
3401
+ if (!nextDate || !(0, import_date_fns3.isValid)(nextDate)) return;
3391
3402
  const iso = [
3392
- newDate.getUTCFullYear(),
3393
- String(newDate.getUTCMonth() + 1).padStart(2, "0"),
3394
- String(newDate.getUTCDate()).padStart(2, "0")
3403
+ nextDate.getUTCFullYear(),
3404
+ String(nextDate.getUTCMonth() + 1).padStart(2, "0"),
3405
+ String(nextDate.getUTCDate()).padStart(2, "0")
3395
3406
  ].join("-");
3407
+ if (iso === value) return;
3396
3408
  onChange?.(iso);
3397
- }, [onChange]);
3409
+ }, [draftDate, onChange, selectedDate, value]);
3398
3410
  const handleCalendarSelect = (0, import_react9.useCallback)(
3399
3411
  (day) => {
3400
3412
  const normalizedDay = businessDays && isWeekend3 && isWeekend3(day) ? snapToBusinessDay(day, 1, isWeekend3) : day;
3401
3413
  updateFromDate(normalizedDay);
3414
+ commitDate(normalizedDay);
3402
3415
  setOpen(false);
3403
3416
  },
3404
- [updateFromDate, businessDays, isWeekend3]
3417
+ [businessDays, commitDate, isWeekend3, updateFromDate]
3405
3418
  );
3406
3419
  const handleDayShift = (0, import_react9.useCallback)(
3407
3420
  (delta) => {
3408
- const base = selectedDate ?? /* @__PURE__ */ new Date();
3421
+ const base = activeDate ?? /* @__PURE__ */ new Date();
3409
3422
  if (businessDays && isWeekend3) {
3410
3423
  updateFromDate(shiftByBusinessDays(base, delta, isWeekend3));
3411
3424
  } else {
3412
3425
  updateFromDate((0, import_date_fns3.addDays)(base, delta));
3413
3426
  }
3414
3427
  },
3415
- [selectedDate, updateFromDate, businessDays, isWeekend3]
3428
+ [activeDate, updateFromDate, businessDays, isWeekend3]
3416
3429
  );
3417
3430
  const handleTriggerKeyDown = (0, import_react9.useCallback)((e) => {
3418
3431
  if (disabled) return;
@@ -3443,13 +3456,14 @@ var DatePicker = ({
3443
3456
  if (e.key === "Enter") {
3444
3457
  e.preventDefault();
3445
3458
  e.stopPropagation();
3459
+ commitDate();
3446
3460
  setOpen(false);
3447
3461
  return;
3448
3462
  }
3449
3463
  if (e.key === "ArrowUp" || e.key === "ArrowDown") {
3450
3464
  e.preventDefault();
3451
3465
  e.stopPropagation();
3452
- const base = selectedDate ?? /* @__PURE__ */ new Date();
3466
+ const base = activeDate ?? /* @__PURE__ */ new Date();
3453
3467
  let newDate = base;
3454
3468
  if (seg.label === "day") newDate = e.key === "ArrowUp" ? (0, import_date_fns3.addDays)(base, 1) : (0, import_date_fns3.subDays)(base, 1);
3455
3469
  if (seg.label === "month") newDate = e.key === "ArrowUp" ? (0, import_date_fns3.addMonths)(base, 1) : (0, import_date_fns3.subMonths)(base, 1);
@@ -3527,8 +3541,14 @@ var DatePicker = ({
3527
3541
  );
3528
3542
  }
3529
3543
  }
3530
- }, [selectedDate, updateFromDate, selectSegByIdx, businessDays, isWeekend3]);
3531
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
3544
+ }, [activeDate, businessDays, commitDate, isWeekend3, selectSegByIdx, updateFromDate]);
3545
+ const handleOpenChange = (0, import_react9.useCallback)((nextOpen) => {
3546
+ if (!nextOpen && open) {
3547
+ commitDate();
3548
+ }
3549
+ setOpen(nextOpen);
3550
+ }, [commitDate, open]);
3551
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Popover, { open, onOpenChange: disabled ? void 0 : handleOpenChange, children: [
3532
3552
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3533
3553
  "button",
3534
3554
  {
@@ -3564,6 +3584,9 @@ var DatePicker = ({
3564
3584
  onFocus: handleFocus,
3565
3585
  onMouseDown: handleMouseDown,
3566
3586
  onKeyDown: handleKeyDown,
3587
+ onBlur: () => {
3588
+ commitDate();
3589
+ },
3567
3590
  spellCheck: false,
3568
3591
  autoComplete: "off"
3569
3592
  }
@@ -3575,9 +3598,9 @@ var DatePicker = ({
3575
3598
  Calendar,
3576
3599
  {
3577
3600
  mode: "single",
3578
- selected: selectedDate,
3601
+ selected: activeDate,
3579
3602
  onSelect: handleCalendarSelect,
3580
- initialDate: selectedDate,
3603
+ initialDate: activeDate,
3581
3604
  isWeekend: isWeekend3
3582
3605
  }
3583
3606
  )