gantt-lib 0.18.0 → 0.20.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
+ createCustomDayPredicate: () => createCustomDayPredicate,
29
+ createDateKey: () => createDateKey,
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, createCustomDayPredicate, 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,38 @@ 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
+ createCustomDayPredicate = (config) => {
105
+ const { customDays, isWeekend: basePredicate } = config;
106
+ const workdaySet = /* @__PURE__ */ new Set();
107
+ const weekendSet = /* @__PURE__ */ new Set();
108
+ if (customDays && customDays.length > 0) {
109
+ for (const item of customDays) {
110
+ const key = createDateKey(item.date);
111
+ if (item.type === "workday") {
112
+ workdaySet.add(key);
113
+ } else {
114
+ weekendSet.add(key);
115
+ }
116
+ }
117
+ }
118
+ return (date) => {
119
+ const key = createDateKey(date);
120
+ if (workdaySet.has(key)) {
121
+ return false;
122
+ }
123
+ if (weekendSet.has(key)) {
124
+ return true;
125
+ }
126
+ if (basePredicate) {
127
+ return basePredicate(date);
128
+ }
129
+ const dayOfWeek = date.getUTCDay();
130
+ return dayOfWeek === 0 || dayOfWeek === 6;
131
+ };
132
+ };
99
133
  getMultiMonthDays = (tasks) => {
100
134
  if (!tasks || tasks.length === 0) {
101
135
  return getMonthDays(/* @__PURE__ */ new Date());
@@ -819,7 +853,8 @@ var TimeScaleHeader = ({
819
853
  days,
820
854
  dayWidth,
821
855
  headerHeight,
822
- viewMode = "day"
856
+ viewMode = "day",
857
+ isCustomWeekend
823
858
  }) => {
824
859
  const monthSpans = useMemo(() => getMonthSpans(days), [days]);
825
860
  const rowHeight = headerHeight / 2;
@@ -983,12 +1018,12 @@ var TimeScaleHeader = ({
983
1018
  ) : (
984
1019
  // Day-view row 2: individual day numbers (existing code)
985
1020
  days.map((day, index) => {
986
- const isWeekend3 = day.getDay() === 0 || day.getDay() === 6;
1021
+ const isWeekendDay = isCustomWeekend ? isCustomWeekend(day) : day.getUTCDay() === 0 || day.getUTCDay() === 6;
987
1022
  const prevDay = days[index - 1];
988
- const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();
1023
+ const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();
989
1024
  const now = /* @__PURE__ */ new Date();
990
1025
  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}`);
1026
+ 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
1027
  })
993
1028
  )
994
1029
  }
@@ -1081,14 +1116,13 @@ var calculateGridLines = (dateRange, dayWidth) => {
1081
1116
  }
1082
1117
  return lines;
1083
1118
  };
1084
- var calculateWeekendBlocks = (dateRange, dayWidth) => {
1119
+ var calculateWeekendBlocks = (dateRange, dayWidth, isCustomWeekend) => {
1085
1120
  const blocks = [];
1086
1121
  let inWeekend = false;
1087
1122
  let weekendStartIndex = -1;
1088
1123
  for (let i = 0; i < dateRange.length; i++) {
1089
1124
  const date = dateRange[i];
1090
- const dayOfWeek = date.getUTCDay();
1091
- const isWeekend3 = dayOfWeek === 0 || dayOfWeek === 6;
1125
+ const isWeekend3 = isCustomWeekend ? isCustomWeekend(date) : date.getUTCDay() === 0 || date.getUTCDay() === 6;
1092
1126
  if (isWeekend3 && !inWeekend) {
1093
1127
  inWeekend = true;
1094
1128
  weekendStartIndex = i;
@@ -1904,10 +1938,10 @@ import React4, { useMemo as useMemo4 } from "react";
1904
1938
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1905
1939
  var arePropsEqual2 = (prevProps, nextProps) => {
1906
1940
  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;
1941
+ prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
1908
1942
  };
1909
1943
  var GridBackground = React4.memo(
1910
- ({ dateRange, dayWidth, totalHeight, viewMode = "day" }) => {
1944
+ ({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
1911
1945
  const weekGridLines = useMemo4(() => {
1912
1946
  if (viewMode !== "week") return [];
1913
1947
  return calculateWeekGridLines(dateRange, dayWidth);
@@ -1922,8 +1956,8 @@ var GridBackground = React4.memo(
1922
1956
  }, [dateRange, dayWidth, viewMode]);
1923
1957
  const weekendBlocks = useMemo4(() => {
1924
1958
  if (viewMode === "week" || viewMode === "month") return [];
1925
- return calculateWeekendBlocks(dateRange, dayWidth);
1926
- }, [dateRange, dayWidth, viewMode]);
1959
+ return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);
1960
+ }, [dateRange, dayWidth, viewMode, isCustomWeekend]);
1927
1961
  const gridWidth = useMemo4(() => {
1928
1962
  return Math.round(dateRange.length * dayWidth);
1929
1963
  }, [dateRange.length, dayWidth]);
@@ -2445,11 +2479,11 @@ import {
2445
2479
  } from "date-fns";
2446
2480
  import { ru as ru2 } from "date-fns/locale";
2447
2481
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2448
- function getDayClassName(day, selected) {
2482
+ function getDayClassName(day, selected, isWeekendProp) {
2449
2483
  const classes = ["gantt-day-btn"];
2450
2484
  if (selected && isSameDay(day, selected)) classes.push("selected");
2451
2485
  if (isToday2(day)) classes.push("today");
2452
- if (isWeekend2(day)) classes.push("weekend");
2486
+ if (isWeekendProp ? isWeekendProp(day) : isWeekend2(day)) classes.push("weekend");
2453
2487
  if (isBefore(day, startOfDay(/* @__PURE__ */ new Date())) && !isToday2(day)) classes.push("past");
2454
2488
  return classes.join(" ");
2455
2489
  }
@@ -2458,7 +2492,8 @@ var Calendar = ({
2458
2492
  onSelect,
2459
2493
  initialDate,
2460
2494
  mode = "single",
2461
- disabled = false
2495
+ disabled = false,
2496
+ isWeekend: isWeekendProp
2462
2497
  }) => {
2463
2498
  const scrollRef = useRef2(null);
2464
2499
  const initialMonth = useMemo6(
@@ -2514,11 +2549,13 @@ var Calendar = ({
2514
2549
  const emptyDays = (getDay(firstDay) + 6) % 7;
2515
2550
  const monthKey = format2(month, "yyyy-MM");
2516
2551
  const monthLabel = format2(month, "LLLL yyyy", { locale: ru2 });
2552
+ const weekdayLabels = ["\u041F\u043D", "\u0412\u0442", "\u0421\u0440", "\u0427\u0442", "\u041F\u0442", "\u0421\u0431", "\u0412\u0441"];
2553
+ const weekdayHeaders = weekdayLabels.map((label, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-weekday", children: label }, `wd-${i}`));
2517
2554
  const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ jsx9("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
2518
2555
  const dayCells = Array.from({ length: totalDays }, (_, i) => {
2519
2556
  const dayNum = i + 1;
2520
- const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
2521
- const className = getDayClassName(day, selected);
2557
+ const day = new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));
2558
+ const className = getDayClassName(day, selected, isWeekendProp);
2522
2559
  return /* @__PURE__ */ jsx9(
2523
2560
  "button",
2524
2561
  {
@@ -2527,7 +2564,7 @@ var Calendar = ({
2527
2564
  disabled,
2528
2565
  onClick: () => {
2529
2566
  if (!disabled && onSelect) {
2530
- onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));
2567
+ onSelect(new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum)));
2531
2568
  }
2532
2569
  },
2533
2570
  children: dayNum
@@ -2538,12 +2575,13 @@ var Calendar = ({
2538
2575
  return /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
2539
2576
  /* @__PURE__ */ jsx9("div", { className: "gantt-cal-month-header", children: monthLabel }),
2540
2577
  /* @__PURE__ */ jsxs6("div", { className: "gantt-cal-month-days", children: [
2578
+ weekdayHeaders,
2541
2579
  emptyCells,
2542
2580
  dayCells
2543
2581
  ] })
2544
2582
  ] }, monthKey);
2545
2583
  },
2546
- [selected, onSelect, disabled]
2584
+ [selected, onSelect, disabled, isWeekendProp]
2547
2585
  );
2548
2586
  const renderedMonths = useMemo6(
2549
2587
  () => months.map(renderMonth),
@@ -2567,7 +2605,8 @@ var DatePicker = ({
2567
2605
  placeholder = "Pick a date",
2568
2606
  portal = true,
2569
2607
  className,
2570
- disabled = false
2608
+ disabled = false,
2609
+ isWeekend: isWeekend3
2571
2610
  }) => {
2572
2611
  const [open, setOpen] = useState3(false);
2573
2612
  const [inputValue, setInputValue] = useState3("");
@@ -2787,7 +2826,8 @@ var DatePicker = ({
2787
2826
  mode: "single",
2788
2827
  selected: selectedDate,
2789
2828
  onSelect: handleCalendarSelect,
2790
- initialDate: selectedDate
2829
+ initialDate: selectedDate,
2830
+ isWeekend: isWeekend3
2791
2831
  }
2792
2832
  )
2793
2833
  ]
@@ -3253,7 +3293,9 @@ var TaskListRow = React9.memo(
3253
3293
  onDemoteTask,
3254
3294
  isLastChild = true,
3255
3295
  nestingDepth = 0,
3256
- ancestorContinues = []
3296
+ ancestorContinues = [],
3297
+ customDays,
3298
+ isWeekend: isWeekend3
3257
3299
  }) => {
3258
3300
  const [editingName, setEditingName] = useState4(false);
3259
3301
  const [nameValue, setNameValue] = useState4("");
@@ -3282,6 +3324,10 @@ var TaskListRow = React9.memo(
3282
3324
  [task.id, allTasks]
3283
3325
  );
3284
3326
  const isChild = task.parentId !== void 0;
3327
+ const weekendPredicate = useMemo7(
3328
+ () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
3329
+ [customDays, isWeekend3]
3330
+ );
3285
3331
  const isCollapsed = collapsedParentIds.has(task.id);
3286
3332
  const isPicking = selectingPredecessorFor != null;
3287
3333
  const isSourceRow = isPicking && selectingPredecessorFor === task.id;
@@ -3882,7 +3928,8 @@ var TaskListRow = React9.memo(
3882
3928
  onChange: handleStartDateChange,
3883
3929
  format: "dd.MM.yy",
3884
3930
  portal: true,
3885
- disabled: task.locked
3931
+ disabled: task.locked,
3932
+ isWeekend: weekendPredicate
3886
3933
  }
3887
3934
  )
3888
3935
  }
@@ -3899,7 +3946,8 @@ var TaskListRow = React9.memo(
3899
3946
  onChange: handleEndDateChange,
3900
3947
  format: "dd.MM.yy",
3901
3948
  portal: true,
3902
- disabled: task.locked
3949
+ disabled: task.locked,
3950
+ isWeekend: weekendPredicate
3903
3951
  }
3904
3952
  )
3905
3953
  }
@@ -4323,7 +4371,9 @@ var TaskList = ({
4323
4371
  collapsedParentIds: externalCollapsedParentIds,
4324
4372
  onToggleCollapse: externalOnToggleCollapse,
4325
4373
  onPromoteTask,
4326
- onDemoteTask
4374
+ onDemoteTask,
4375
+ customDays,
4376
+ isWeekend: isWeekend3
4327
4377
  }) => {
4328
4378
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = useState6(/* @__PURE__ */ new Set());
4329
4379
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -4789,7 +4839,9 @@ var TaskList = ({
4789
4839
  onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
4790
4840
  isLastChild: lastChildIds.has(task.id),
4791
4841
  nestingDepth: nestingDepthMap.get(task.id) ?? 0,
4792
- ancestorContinues: ancestorContinuesMap.get(task.id) ?? []
4842
+ ancestorContinues: ancestorContinuesMap.get(task.id) ?? [],
4843
+ customDays,
4844
+ isWeekend: isWeekend3
4793
4845
  },
4794
4846
  task.id
4795
4847
  )) }),
@@ -4857,7 +4909,9 @@ var GanttChart = forwardRef(({
4857
4909
  onPromoteTask,
4858
4910
  onDemoteTask,
4859
4911
  enableAddTask = true,
4860
- viewMode = "day"
4912
+ viewMode = "day",
4913
+ customDays,
4914
+ isWeekend: isWeekend3
4861
4915
  }, ref) => {
4862
4916
  const scrollContainerRef = useRef7(null);
4863
4917
  const [selectedTaskId, setSelectedTaskId] = useState7(null);
@@ -4866,6 +4920,10 @@ var GanttChart = forwardRef(({
4866
4920
  const [collapsedParentIds, setCollapsedParentIds] = useState7(/* @__PURE__ */ new Set());
4867
4921
  const [editingTaskId, setEditingTaskId] = useState7(null);
4868
4922
  const normalizedTasks = useMemo9(() => normalizeHierarchyTasks(tasks), [tasks]);
4923
+ const isCustomWeekend = useMemo9(
4924
+ () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
4925
+ [customDays, isWeekend3]
4926
+ );
4869
4927
  const dateRange = useMemo9(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
4870
4928
  const [validationResult, setValidationResult] = useState7(null);
4871
4929
  const [cascadeOverrides, setCascadeOverrides] = useState7(/* @__PURE__ */ new Map());
@@ -5257,7 +5315,9 @@ var GanttChart = forwardRef(({
5257
5315
  collapsedParentIds,
5258
5316
  onToggleCollapse: handleToggleCollapse,
5259
5317
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
5260
- onDemoteTask: onDemoteTask ?? handleDemoteTask
5318
+ onDemoteTask: onDemoteTask ?? handleDemoteTask,
5319
+ customDays,
5320
+ isWeekend: isWeekend3
5261
5321
  }
5262
5322
  ),
5263
5323
  /* @__PURE__ */ jsxs12("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
@@ -5267,7 +5327,8 @@ var GanttChart = forwardRef(({
5267
5327
  days: dateRange,
5268
5328
  dayWidth,
5269
5329
  headerHeight,
5270
- viewMode
5330
+ viewMode,
5331
+ isCustomWeekend
5271
5332
  }
5272
5333
  ) }),
5273
5334
  /* @__PURE__ */ jsxs12(
@@ -5285,7 +5346,8 @@ var GanttChart = forwardRef(({
5285
5346
  dateRange,
5286
5347
  dayWidth,
5287
5348
  totalHeight: totalGridHeight,
5288
- viewMode
5349
+ viewMode,
5350
+ isCustomWeekend
5289
5351
  }
5290
5352
  ),
5291
5353
  todayInRange && /* @__PURE__ */ jsx15(TodayIndicator_default, { monthStart, dayWidth }),
@@ -5399,6 +5461,8 @@ export {
5399
5461
  computeLagFromDates,
5400
5462
  computeParentDates,
5401
5463
  computeParentProgress,
5464
+ createCustomDayPredicate,
5465
+ createDateKey,
5402
5466
  detectCycles,
5403
5467
  detectEdgeZone,
5404
5468
  findParentId,