gantt-lib 0.18.0 → 0.19.0

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.mjs CHANGED
@@ -25,6 +25,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
25
25
  // src/utils/dateUtils.ts
26
26
  var dateUtils_exports = {};
27
27
  __export(dateUtils_exports, {
28
+ createDateKey: () => createDateKey,
29
+ createIsWeekendPredicate: () => createIsWeekendPredicate,
28
30
  formatDateLabel: () => formatDateLabel,
29
31
  getDayOffset: () => getDayOffset,
30
32
  getMonthBlocks: () => getMonthBlocks,
@@ -39,7 +41,7 @@ __export(dateUtils_exports, {
39
41
  normalizeTaskDates: () => normalizeTaskDates,
40
42
  parseUTCDate: () => parseUTCDate
41
43
  });
42
- var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
44
+ var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, createDateKey, createIsWeekendPredicate, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
43
45
  var init_dateUtils = __esm({
44
46
  "src/utils/dateUtils.ts"() {
45
47
  "use strict";
@@ -96,6 +98,41 @@ var init_dateUtils = __esm({
96
98
  const day = date.getUTCDay();
97
99
  return day === 0 || day === 6;
98
100
  };
101
+ createDateKey = (date) => {
102
+ return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
103
+ };
104
+ createIsWeekendPredicate = (config) => {
105
+ const { weekends, workdays, isWeekend: customPredicate } = config;
106
+ if (customPredicate) {
107
+ return customPredicate;
108
+ }
109
+ if (workdays && workdays.length > 0) {
110
+ const workdaySet = new Set(workdays.map(createDateKey));
111
+ return (date) => {
112
+ const key = createDateKey(date);
113
+ if (workdaySet.has(key)) {
114
+ return false;
115
+ }
116
+ const dayOfWeek = date.getUTCDay();
117
+ return dayOfWeek === 0 || dayOfWeek === 6;
118
+ };
119
+ }
120
+ if (weekends && weekends.length > 0) {
121
+ const weekendSet = new Set(weekends.map(createDateKey));
122
+ return (date) => {
123
+ const key = createDateKey(date);
124
+ if (weekendSet.has(key)) {
125
+ return true;
126
+ }
127
+ const dayOfWeek = date.getUTCDay();
128
+ return dayOfWeek === 0 || dayOfWeek === 6;
129
+ };
130
+ }
131
+ return (date) => {
132
+ const dayOfWeek = date.getUTCDay();
133
+ return dayOfWeek === 0 || dayOfWeek === 6;
134
+ };
135
+ };
99
136
  getMultiMonthDays = (tasks) => {
100
137
  if (!tasks || tasks.length === 0) {
101
138
  return getMonthDays(/* @__PURE__ */ new Date());
@@ -819,7 +856,8 @@ var TimeScaleHeader = ({
819
856
  days,
820
857
  dayWidth,
821
858
  headerHeight,
822
- viewMode = "day"
859
+ viewMode = "day",
860
+ isCustomWeekend
823
861
  }) => {
824
862
  const monthSpans = useMemo(() => getMonthSpans(days), [days]);
825
863
  const rowHeight = headerHeight / 2;
@@ -983,12 +1021,12 @@ var TimeScaleHeader = ({
983
1021
  ) : (
984
1022
  // Day-view row 2: individual day numbers (existing code)
985
1023
  days.map((day, index) => {
986
- const isWeekend3 = day.getDay() === 0 || day.getDay() === 6;
1024
+ const isWeekendDay = isCustomWeekend ? isCustomWeekend(day) : day.getUTCDay() === 0 || day.getUTCDay() === 6;
987
1025
  const prevDay = days[index - 1];
988
- const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();
1026
+ const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();
989
1027
  const now = /* @__PURE__ */ new Date();
990
1028
  const isTodayDate = day.getUTCFullYear() === now.getFullYear() && day.getUTCMonth() === now.getMonth() && day.getUTCDate() === now.getDate();
991
- return /* @__PURE__ */ jsx("div", { className: `gantt-tsh-dayCell ${isWeekend3 ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ jsx("span", { className: "gantt-tsh-dayLabel", children: format(day, "d") }) }, `day-${index}`);
1029
+ return /* @__PURE__ */ jsx("div", { className: `gantt-tsh-dayCell ${isWeekendDay ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ jsx("span", { className: "gantt-tsh-dayLabel", children: format(day, "d") }) }, `day-${index}`);
992
1030
  })
993
1031
  )
994
1032
  }
@@ -1081,14 +1119,13 @@ var calculateGridLines = (dateRange, dayWidth) => {
1081
1119
  }
1082
1120
  return lines;
1083
1121
  };
1084
- var calculateWeekendBlocks = (dateRange, dayWidth) => {
1122
+ var calculateWeekendBlocks = (dateRange, dayWidth, isCustomWeekend) => {
1085
1123
  const blocks = [];
1086
1124
  let inWeekend = false;
1087
1125
  let weekendStartIndex = -1;
1088
1126
  for (let i = 0; i < dateRange.length; i++) {
1089
1127
  const date = dateRange[i];
1090
- const dayOfWeek = date.getUTCDay();
1091
- const isWeekend3 = dayOfWeek === 0 || dayOfWeek === 6;
1128
+ const isWeekend3 = isCustomWeekend ? isCustomWeekend(date) : date.getUTCDay() === 0 || date.getUTCDay() === 6;
1092
1129
  if (isWeekend3 && !inWeekend) {
1093
1130
  inWeekend = true;
1094
1131
  weekendStartIndex = i;
@@ -1904,10 +1941,10 @@ import React4, { useMemo as useMemo4 } from "react";
1904
1941
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1905
1942
  var arePropsEqual2 = (prevProps, nextProps) => {
1906
1943
  return prevProps.dayWidth === nextProps.dayWidth && prevProps.dateRange.length === nextProps.dateRange.length && prevProps.totalHeight === nextProps.totalHeight && // skip re-render only when totalHeight unchanged
1907
- prevProps.viewMode === nextProps.viewMode;
1944
+ prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
1908
1945
  };
1909
1946
  var GridBackground = React4.memo(
1910
- ({ dateRange, dayWidth, totalHeight, viewMode = "day" }) => {
1947
+ ({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
1911
1948
  const weekGridLines = useMemo4(() => {
1912
1949
  if (viewMode !== "week") return [];
1913
1950
  return calculateWeekGridLines(dateRange, dayWidth);
@@ -1922,8 +1959,8 @@ var GridBackground = React4.memo(
1922
1959
  }, [dateRange, dayWidth, viewMode]);
1923
1960
  const weekendBlocks = useMemo4(() => {
1924
1961
  if (viewMode === "week" || viewMode === "month") return [];
1925
- return calculateWeekendBlocks(dateRange, dayWidth);
1926
- }, [dateRange, dayWidth, viewMode]);
1962
+ return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);
1963
+ }, [dateRange, dayWidth, viewMode, isCustomWeekend]);
1927
1964
  const gridWidth = useMemo4(() => {
1928
1965
  return Math.round(dateRange.length * dayWidth);
1929
1966
  }, [dateRange.length, dayWidth]);
@@ -2423,6 +2460,7 @@ import { useState as useState3, useCallback as useCallback3, useEffect as useEff
2423
2460
  import { format as format3, isValid, parse, addDays, addMonths as addMonths2, addYears, subMonths as subMonths2, subYears, subDays } from "date-fns";
2424
2461
 
2425
2462
  // src/components/ui/Calendar.tsx
2463
+ init_dateUtils();
2426
2464
  import {
2427
2465
  useState as useState2,
2428
2466
  useRef as useRef2,
@@ -2445,11 +2483,11 @@ import {
2445
2483
  } from "date-fns";
2446
2484
  import { ru as ru2 } from "date-fns/locale";
2447
2485
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2448
- function getDayClassName(day, selected) {
2486
+ function getDayClassName(day, selected, isWeekendProp) {
2449
2487
  const classes = ["gantt-day-btn"];
2450
2488
  if (selected && isSameDay(day, selected)) classes.push("selected");
2451
2489
  if (isToday2(day)) classes.push("today");
2452
- if (isWeekend2(day)) classes.push("weekend");
2490
+ if (isWeekendProp ? isWeekendProp(day) : isWeekend2(day)) classes.push("weekend");
2453
2491
  if (isBefore(day, startOfDay(/* @__PURE__ */ new Date())) && !isToday2(day)) classes.push("past");
2454
2492
  return classes.join(" ");
2455
2493
  }
@@ -2458,9 +2496,22 @@ var Calendar = ({
2458
2496
  onSelect,
2459
2497
  initialDate,
2460
2498
  mode = "single",
2461
- disabled = false
2499
+ disabled = false,
2500
+ isWeekend: isWeekendProp,
2501
+ weekends,
2502
+ workdays
2462
2503
  }) => {
2463
2504
  const scrollRef = useRef2(null);
2505
+ const derivedWeekendPredicate = useMemo6(() => {
2506
+ if (isWeekendProp) return isWeekendProp;
2507
+ if (weekends || workdays) {
2508
+ return createIsWeekendPredicate({
2509
+ weekends: weekends ?? [],
2510
+ workdays: workdays ?? []
2511
+ });
2512
+ }
2513
+ return void 0;
2514
+ }, [isWeekendProp, weekends, workdays]);
2464
2515
  const initialMonth = useMemo6(
2465
2516
  () => startOfMonth(initialDate ?? selected ?? /* @__PURE__ */ new Date()),
2466
2517
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -2514,11 +2565,13 @@ var Calendar = ({
2514
2565
  const emptyDays = (getDay(firstDay) + 6) % 7;
2515
2566
  const monthKey = format2(month, "yyyy-MM");
2516
2567
  const monthLabel = format2(month, "LLLL yyyy", { locale: ru2 });
2568
+ const weekdayLabels = ["\u041F\u043D", "\u0412\u0442", "\u0421\u0440", "\u0427\u0442", "\u041F\u0442", "\u0421\u0431", "\u0412\u0441"];
2569
+ const weekdayHeaders = weekdayLabels.map((label, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-weekday", children: label }, `wd-${i}`));
2517
2570
  const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
2518
2571
  const dayCells = Array.from({ length: totalDays }, (_, i) => {
2519
2572
  const dayNum = i + 1;
2520
- const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
2521
- const className = getDayClassName(day, selected);
2573
+ const day = new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));
2574
+ const className = getDayClassName(day, selected, derivedWeekendPredicate);
2522
2575
  return /* @__PURE__ */ jsx9(
2523
2576
  "button",
2524
2577
  {
@@ -2527,7 +2580,7 @@ var Calendar = ({
2527
2580
  disabled,
2528
2581
  onClick: () => {
2529
2582
  if (!disabled && onSelect) {
2530
- onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));
2583
+ onSelect(new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum)));
2531
2584
  }
2532
2585
  },
2533
2586
  children: dayNum
@@ -2538,12 +2591,13 @@ var Calendar = ({
2538
2591
  return /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
2539
2592
  /* @__PURE__ */ jsx9("div", { className: "gantt-cal-month-header", children: monthLabel }),
2540
2593
  /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month-days", children: [
2594
+ weekdayHeaders,
2541
2595
  emptyCells,
2542
2596
  dayCells
2543
2597
  ] })
2544
2598
  ] }, monthKey);
2545
2599
  },
2546
- [selected, onSelect, disabled]
2600
+ [selected, onSelect, disabled, derivedWeekendPredicate]
2547
2601
  );
2548
2602
  const renderedMonths = useMemo6(
2549
2603
  () => months.map(renderMonth),
@@ -2567,7 +2621,10 @@ var DatePicker = ({
2567
2621
  placeholder = "Pick a date",
2568
2622
  portal = true,
2569
2623
  className,
2570
- disabled = false
2624
+ disabled = false,
2625
+ weekends,
2626
+ workdays,
2627
+ isWeekend: isWeekend3
2571
2628
  }) => {
2572
2629
  const [open, setOpen] = useState3(false);
2573
2630
  const [inputValue, setInputValue] = useState3("");
@@ -2787,7 +2844,10 @@ var DatePicker = ({
2787
2844
  mode: "single",
2788
2845
  selected: selectedDate,
2789
2846
  onSelect: handleCalendarSelect,
2790
- initialDate: selectedDate
2847
+ initialDate: selectedDate,
2848
+ weekends,
2849
+ workdays,
2850
+ isWeekend: isWeekend3
2791
2851
  }
2792
2852
  )
2793
2853
  ]
@@ -3253,7 +3313,10 @@ var TaskListRow = React9.memo(
3253
3313
  onDemoteTask,
3254
3314
  isLastChild = true,
3255
3315
  nestingDepth = 0,
3256
- ancestorContinues = []
3316
+ ancestorContinues = [],
3317
+ weekends,
3318
+ workdays,
3319
+ isWeekend: isWeekend3
3257
3320
  }) => {
3258
3321
  const [editingName, setEditingName] = useState4(false);
3259
3322
  const [nameValue, setNameValue] = useState4("");
@@ -3882,7 +3945,10 @@ var TaskListRow = React9.memo(
3882
3945
  onChange: handleStartDateChange,
3883
3946
  format: "dd.MM.yy",
3884
3947
  portal: true,
3885
- disabled: task.locked
3948
+ disabled: task.locked,
3949
+ weekends,
3950
+ workdays,
3951
+ isWeekend: isWeekend3
3886
3952
  }
3887
3953
  )
3888
3954
  }
@@ -3899,7 +3965,10 @@ var TaskListRow = React9.memo(
3899
3965
  onChange: handleEndDateChange,
3900
3966
  format: "dd.MM.yy",
3901
3967
  portal: true,
3902
- disabled: task.locked
3968
+ disabled: task.locked,
3969
+ weekends,
3970
+ workdays,
3971
+ isWeekend: isWeekend3
3903
3972
  }
3904
3973
  )
3905
3974
  }
@@ -4323,7 +4392,10 @@ var TaskList = ({
4323
4392
  collapsedParentIds: externalCollapsedParentIds,
4324
4393
  onToggleCollapse: externalOnToggleCollapse,
4325
4394
  onPromoteTask,
4326
- onDemoteTask
4395
+ onDemoteTask,
4396
+ weekends,
4397
+ workdays,
4398
+ isWeekend: isWeekend3
4327
4399
  }) => {
4328
4400
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState6(/* @__PURE__ */ new Set());
4329
4401
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -4789,7 +4861,10 @@ var TaskList = ({
4789
4861
  onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
4790
4862
  isLastChild: lastChildIds.has(task.id),
4791
4863
  nestingDepth: nestingDepthMap.get(task.id) ?? 0,
4792
- ancestorContinues: ancestorContinuesMap.get(task.id) ?? []
4864
+ ancestorContinues: ancestorContinuesMap.get(task.id) ?? [],
4865
+ weekends,
4866
+ workdays,
4867
+ isWeekend: isWeekend3
4793
4868
  },
4794
4869
  task.id
4795
4870
  )) }),
@@ -4857,7 +4932,10 @@ var GanttChart = forwardRef(({
4857
4932
  onPromoteTask,
4858
4933
  onDemoteTask,
4859
4934
  enableAddTask = true,
4860
- viewMode = "day"
4935
+ viewMode = "day",
4936
+ weekends,
4937
+ workdays,
4938
+ isWeekend: isWeekend3
4861
4939
  }, ref) => {
4862
4940
  const scrollContainerRef = useRef7(null);
4863
4941
  const [selectedTaskId, setSelectedTaskId] = useState7(null);
@@ -4866,6 +4944,10 @@ var GanttChart = forwardRef(({
4866
4944
  const [collapsedParentIds, setCollapsedParentIds] = useState7(/* @__PURE__ */ new Set());
4867
4945
  const [editingTaskId, setEditingTaskId] = useState7(null);
4868
4946
  const normalizedTasks = useMemo9(() => normalizeHierarchyTasks(tasks), [tasks]);
4947
+ const isCustomWeekend = useMemo9(
4948
+ () => createIsWeekendPredicate({ weekends, workdays, isWeekend: isWeekend3 }),
4949
+ [weekends, workdays, isWeekend3]
4950
+ );
4869
4951
  const dateRange = useMemo9(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
4870
4952
  const [validationResult, setValidationResult] = useState7(null);
4871
4953
  const [cascadeOverrides, setCascadeOverrides] = useState7(/* @__PURE__ */ new Map());
@@ -5257,7 +5339,10 @@ var GanttChart = forwardRef(({
5257
5339
  collapsedParentIds,
5258
5340
  onToggleCollapse: handleToggleCollapse,
5259
5341
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
5260
- onDemoteTask: onDemoteTask ?? handleDemoteTask
5342
+ onDemoteTask: onDemoteTask ?? handleDemoteTask,
5343
+ weekends,
5344
+ workdays,
5345
+ isWeekend: isWeekend3
5261
5346
  }
5262
5347
  ),
5263
5348
  /* @__PURE__ */ jsxs12("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
@@ -5267,7 +5352,8 @@ var GanttChart = forwardRef(({
5267
5352
  days: dateRange,
5268
5353
  dayWidth,
5269
5354
  headerHeight,
5270
- viewMode
5355
+ viewMode,
5356
+ isCustomWeekend
5271
5357
  }
5272
5358
  ) }),
5273
5359
  /* @__PURE__ */ jsxs12(
@@ -5285,7 +5371,8 @@ var GanttChart = forwardRef(({
5285
5371
  dateRange,
5286
5372
  dayWidth,
5287
5373
  totalHeight: totalGridHeight,
5288
- viewMode
5374
+ viewMode,
5375
+ isCustomWeekend
5289
5376
  }
5290
5377
  ),
5291
5378
  todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
@@ -5399,6 +5486,8 @@ export {
5399
5486
  computeLagFromDates,
5400
5487
  computeParentDates,
5401
5488
  computeParentProgress,
5489
+ createDateKey,
5490
+ createIsWeekendPredicate,
5402
5491
  detectCycles,
5403
5492
  detectEdgeZone,
5404
5493
  findParentId,