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.js CHANGED
@@ -36,6 +36,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
36
36
  // src/utils/dateUtils.ts
37
37
  var dateUtils_exports = {};
38
38
  __export(dateUtils_exports, {
39
+ createCustomDayPredicate: () => createCustomDayPredicate,
40
+ createDateKey: () => createDateKey,
39
41
  formatDateLabel: () => formatDateLabel,
40
42
  getDayOffset: () => getDayOffset,
41
43
  getMonthBlocks: () => getMonthBlocks,
@@ -50,7 +52,7 @@ __export(dateUtils_exports, {
50
52
  normalizeTaskDates: () => normalizeTaskDates,
51
53
  parseUTCDate: () => parseUTCDate
52
54
  });
53
- var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
55
+ var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, createDateKey, createCustomDayPredicate, getMultiMonthDays, getMonthSpans, formatDateLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
54
56
  var init_dateUtils = __esm({
55
57
  "src/utils/dateUtils.ts"() {
56
58
  "use strict";
@@ -107,6 +109,38 @@ var init_dateUtils = __esm({
107
109
  const day = date.getUTCDay();
108
110
  return day === 0 || day === 6;
109
111
  };
112
+ createDateKey = (date) => {
113
+ return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
114
+ };
115
+ createCustomDayPredicate = (config) => {
116
+ const { customDays, isWeekend: basePredicate } = config;
117
+ const workdaySet = /* @__PURE__ */ new Set();
118
+ const weekendSet = /* @__PURE__ */ new Set();
119
+ if (customDays && customDays.length > 0) {
120
+ for (const item of customDays) {
121
+ const key = createDateKey(item.date);
122
+ if (item.type === "workday") {
123
+ workdaySet.add(key);
124
+ } else {
125
+ weekendSet.add(key);
126
+ }
127
+ }
128
+ }
129
+ return (date) => {
130
+ const key = createDateKey(date);
131
+ if (workdaySet.has(key)) {
132
+ return false;
133
+ }
134
+ if (weekendSet.has(key)) {
135
+ return true;
136
+ }
137
+ if (basePredicate) {
138
+ return basePredicate(date);
139
+ }
140
+ const dayOfWeek = date.getUTCDay();
141
+ return dayOfWeek === 0 || dayOfWeek === 6;
142
+ };
143
+ };
110
144
  getMultiMonthDays = (tasks) => {
111
145
  if (!tasks || tasks.length === 0) {
112
146
  return getMonthDays(/* @__PURE__ */ new Date());
@@ -343,6 +377,8 @@ __export(index_exports, {
343
377
  computeLagFromDates: () => computeLagFromDates,
344
378
  computeParentDates: () => computeParentDates,
345
379
  computeParentProgress: () => computeParentProgress,
380
+ createCustomDayPredicate: () => createCustomDayPredicate,
381
+ createDateKey: () => createDateKey,
346
382
  detectCycles: () => detectCycles,
347
383
  detectEdgeZone: () => detectEdgeZone,
348
384
  findParentId: () => findParentId,
@@ -896,7 +932,8 @@ var TimeScaleHeader = ({
896
932
  days,
897
933
  dayWidth,
898
934
  headerHeight,
899
- viewMode = "day"
935
+ viewMode = "day",
936
+ isCustomWeekend
900
937
  }) => {
901
938
  const monthSpans = (0, import_react.useMemo)(() => getMonthSpans(days), [days]);
902
939
  const rowHeight = headerHeight / 2;
@@ -1060,12 +1097,12 @@ var TimeScaleHeader = ({
1060
1097
  ) : (
1061
1098
  // Day-view row 2: individual day numbers (existing code)
1062
1099
  days.map((day, index) => {
1063
- const isWeekend3 = day.getDay() === 0 || day.getDay() === 6;
1100
+ const isWeekendDay = isCustomWeekend ? isCustomWeekend(day) : day.getUTCDay() === 0 || day.getUTCDay() === 6;
1064
1101
  const prevDay = days[index - 1];
1065
- const isMonthBoundary = index > 0 && prevDay && prevDay.getMonth() !== day.getMonth();
1102
+ const isMonthBoundary = index > 0 && prevDay && prevDay.getUTCMonth() !== day.getUTCMonth();
1066
1103
  const now = /* @__PURE__ */ new Date();
1067
1104
  const isTodayDate = day.getUTCFullYear() === now.getFullYear() && day.getUTCMonth() === now.getMonth() && day.getUTCDate() === now.getDate();
1068
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `gantt-tsh-dayCell ${isWeekend3 ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gantt-tsh-dayLabel", children: (0, import_date_fns.format)(day, "d") }) }, `day-${index}`);
1105
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `gantt-tsh-dayCell ${isWeekendDay ? "gantt-tsh-weekendDay" : ""} ${isTodayDate ? "gantt-tsh-today" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gantt-tsh-dayLabel", children: (0, import_date_fns.format)(day, "d") }) }, `day-${index}`);
1069
1106
  })
1070
1107
  )
1071
1108
  }
@@ -1158,14 +1195,13 @@ var calculateGridLines = (dateRange, dayWidth) => {
1158
1195
  }
1159
1196
  return lines;
1160
1197
  };
1161
- var calculateWeekendBlocks = (dateRange, dayWidth) => {
1198
+ var calculateWeekendBlocks = (dateRange, dayWidth, isCustomWeekend) => {
1162
1199
  const blocks = [];
1163
1200
  let inWeekend = false;
1164
1201
  let weekendStartIndex = -1;
1165
1202
  for (let i = 0; i < dateRange.length; i++) {
1166
1203
  const date = dateRange[i];
1167
- const dayOfWeek = date.getUTCDay();
1168
- const isWeekend3 = dayOfWeek === 0 || dayOfWeek === 6;
1204
+ const isWeekend3 = isCustomWeekend ? isCustomWeekend(date) : date.getUTCDay() === 0 || date.getUTCDay() === 6;
1169
1205
  if (isWeekend3 && !inWeekend) {
1170
1206
  inWeekend = true;
1171
1207
  weekendStartIndex = i;
@@ -1981,10 +2017,10 @@ var import_react5 = __toESM(require("react"));
1981
2017
  var import_jsx_runtime4 = require("react/jsx-runtime");
1982
2018
  var arePropsEqual2 = (prevProps, nextProps) => {
1983
2019
  return prevProps.dayWidth === nextProps.dayWidth && prevProps.dateRange.length === nextProps.dateRange.length && prevProps.totalHeight === nextProps.totalHeight && // skip re-render only when totalHeight unchanged
1984
- prevProps.viewMode === nextProps.viewMode;
2020
+ prevProps.viewMode === nextProps.viewMode && prevProps.isCustomWeekend === nextProps.isCustomWeekend;
1985
2021
  };
1986
2022
  var GridBackground = import_react5.default.memo(
1987
- ({ dateRange, dayWidth, totalHeight, viewMode = "day" }) => {
2023
+ ({ dateRange, dayWidth, totalHeight, viewMode = "day", isCustomWeekend }) => {
1988
2024
  const weekGridLines = (0, import_react5.useMemo)(() => {
1989
2025
  if (viewMode !== "week") return [];
1990
2026
  return calculateWeekGridLines(dateRange, dayWidth);
@@ -1999,8 +2035,8 @@ var GridBackground = import_react5.default.memo(
1999
2035
  }, [dateRange, dayWidth, viewMode]);
2000
2036
  const weekendBlocks = (0, import_react5.useMemo)(() => {
2001
2037
  if (viewMode === "week" || viewMode === "month") return [];
2002
- return calculateWeekendBlocks(dateRange, dayWidth);
2003
- }, [dateRange, dayWidth, viewMode]);
2038
+ return calculateWeekendBlocks(dateRange, dayWidth, isCustomWeekend);
2039
+ }, [dateRange, dayWidth, viewMode, isCustomWeekend]);
2004
2040
  const gridWidth = (0, import_react5.useMemo)(() => {
2005
2041
  return Math.round(dateRange.length * dayWidth);
2006
2042
  }, [dateRange.length, dayWidth]);
@@ -2498,11 +2534,11 @@ var import_react8 = require("react");
2498
2534
  var import_date_fns2 = require("date-fns");
2499
2535
  var import_locale2 = require("date-fns/locale");
2500
2536
  var import_jsx_runtime9 = require("react/jsx-runtime");
2501
- function getDayClassName(day, selected) {
2537
+ function getDayClassName(day, selected, isWeekendProp) {
2502
2538
  const classes = ["gantt-day-btn"];
2503
2539
  if (selected && (0, import_date_fns2.isSameDay)(day, selected)) classes.push("selected");
2504
2540
  if ((0, import_date_fns2.isToday)(day)) classes.push("today");
2505
- if ((0, import_date_fns2.isWeekend)(day)) classes.push("weekend");
2541
+ if (isWeekendProp ? isWeekendProp(day) : (0, import_date_fns2.isWeekend)(day)) classes.push("weekend");
2506
2542
  if ((0, import_date_fns2.isBefore)(day, (0, import_date_fns2.startOfDay)(/* @__PURE__ */ new Date())) && !(0, import_date_fns2.isToday)(day)) classes.push("past");
2507
2543
  return classes.join(" ");
2508
2544
  }
@@ -2511,7 +2547,8 @@ var Calendar = ({
2511
2547
  onSelect,
2512
2548
  initialDate,
2513
2549
  mode = "single",
2514
- disabled = false
2550
+ disabled = false,
2551
+ isWeekend: isWeekendProp
2515
2552
  }) => {
2516
2553
  const scrollRef = (0, import_react8.useRef)(null);
2517
2554
  const initialMonth = (0, import_react8.useMemo)(
@@ -2567,11 +2604,13 @@ var Calendar = ({
2567
2604
  const emptyDays = ((0, import_date_fns2.getDay)(firstDay) + 6) % 7;
2568
2605
  const monthKey = (0, import_date_fns2.format)(month, "yyyy-MM");
2569
2606
  const monthLabel = (0, import_date_fns2.format)(month, "LLLL yyyy", { locale: import_locale2.ru });
2607
+ const weekdayLabels = ["\u041F\u043D", "\u0412\u0442", "\u0421\u0440", "\u0427\u0442", "\u041F\u0442", "\u0421\u0431", "\u0412\u0441"];
2608
+ const weekdayHeaders = weekdayLabels.map((label, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-weekday", children: label }, `wd-${i}`));
2570
2609
  const emptyCells = Array.from({ length: emptyDays }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-empty-day" }, `e-${i}`));
2571
2610
  const dayCells = Array.from({ length: totalDays }, (_, i) => {
2572
2611
  const dayNum = i + 1;
2573
- const day = new Date(month.getFullYear(), month.getMonth(), dayNum);
2574
- const className = getDayClassName(day, selected);
2612
+ const day = new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum));
2613
+ const className = getDayClassName(day, selected, isWeekendProp);
2575
2614
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2576
2615
  "button",
2577
2616
  {
@@ -2580,7 +2619,7 @@ var Calendar = ({
2580
2619
  disabled,
2581
2620
  onClick: () => {
2582
2621
  if (!disabled && onSelect) {
2583
- onSelect(new Date(month.getFullYear(), month.getMonth(), dayNum));
2622
+ onSelect(new Date(Date.UTC(month.getFullYear(), month.getMonth(), dayNum)));
2584
2623
  }
2585
2624
  },
2586
2625
  children: dayNum
@@ -2591,12 +2630,13 @@ var Calendar = ({
2591
2630
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gantt-cal-month", "data-month": monthKey, children: [
2592
2631
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gantt-cal-month-header", children: monthLabel }),
2593
2632
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gantt-cal-month-days", children: [
2633
+ weekdayHeaders,
2594
2634
  emptyCells,
2595
2635
  dayCells
2596
2636
  ] })
2597
2637
  ] }, monthKey);
2598
2638
  },
2599
- [selected, onSelect, disabled]
2639
+ [selected, onSelect, disabled, isWeekendProp]
2600
2640
  );
2601
2641
  const renderedMonths = (0, import_react8.useMemo)(
2602
2642
  () => months.map(renderMonth),
@@ -2620,7 +2660,8 @@ var DatePicker = ({
2620
2660
  placeholder = "Pick a date",
2621
2661
  portal = true,
2622
2662
  className,
2623
- disabled = false
2663
+ disabled = false,
2664
+ isWeekend: isWeekend3
2624
2665
  }) => {
2625
2666
  const [open, setOpen] = (0, import_react9.useState)(false);
2626
2667
  const [inputValue, setInputValue] = (0, import_react9.useState)("");
@@ -2840,7 +2881,8 @@ var DatePicker = ({
2840
2881
  mode: "single",
2841
2882
  selected: selectedDate,
2842
2883
  onSelect: handleCalendarSelect,
2843
- initialDate: selectedDate
2884
+ initialDate: selectedDate,
2885
+ isWeekend: isWeekend3
2844
2886
  }
2845
2887
  )
2846
2888
  ]
@@ -3306,7 +3348,9 @@ var TaskListRow = import_react10.default.memo(
3306
3348
  onDemoteTask,
3307
3349
  isLastChild = true,
3308
3350
  nestingDepth = 0,
3309
- ancestorContinues = []
3351
+ ancestorContinues = [],
3352
+ customDays,
3353
+ isWeekend: isWeekend3
3310
3354
  }) => {
3311
3355
  const [editingName, setEditingName] = (0, import_react10.useState)(false);
3312
3356
  const [nameValue, setNameValue] = (0, import_react10.useState)("");
@@ -3335,6 +3379,10 @@ var TaskListRow = import_react10.default.memo(
3335
3379
  [task.id, allTasks]
3336
3380
  );
3337
3381
  const isChild = task.parentId !== void 0;
3382
+ const weekendPredicate = (0, import_react10.useMemo)(
3383
+ () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
3384
+ [customDays, isWeekend3]
3385
+ );
3338
3386
  const isCollapsed = collapsedParentIds.has(task.id);
3339
3387
  const isPicking = selectingPredecessorFor != null;
3340
3388
  const isSourceRow = isPicking && selectingPredecessorFor === task.id;
@@ -3935,7 +3983,8 @@ var TaskListRow = import_react10.default.memo(
3935
3983
  onChange: handleStartDateChange,
3936
3984
  format: "dd.MM.yy",
3937
3985
  portal: true,
3938
- disabled: task.locked
3986
+ disabled: task.locked,
3987
+ isWeekend: weekendPredicate
3939
3988
  }
3940
3989
  )
3941
3990
  }
@@ -3952,7 +4001,8 @@ var TaskListRow = import_react10.default.memo(
3952
4001
  onChange: handleEndDateChange,
3953
4002
  format: "dd.MM.yy",
3954
4003
  portal: true,
3955
- disabled: task.locked
4004
+ disabled: task.locked,
4005
+ isWeekend: weekendPredicate
3956
4006
  }
3957
4007
  )
3958
4008
  }
@@ -4376,7 +4426,9 @@ var TaskList = ({
4376
4426
  collapsedParentIds: externalCollapsedParentIds,
4377
4427
  onToggleCollapse: externalOnToggleCollapse,
4378
4428
  onPromoteTask,
4379
- onDemoteTask
4429
+ onDemoteTask,
4430
+ customDays,
4431
+ isWeekend: isWeekend3
4380
4432
  }) => {
4381
4433
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
4382
4434
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
@@ -4842,7 +4894,9 @@ var TaskList = ({
4842
4894
  onDemoteTask: onDemoteTask ? handleDemoteWrapper : void 0,
4843
4895
  isLastChild: lastChildIds.has(task.id),
4844
4896
  nestingDepth: nestingDepthMap.get(task.id) ?? 0,
4845
- ancestorContinues: ancestorContinuesMap.get(task.id) ?? []
4897
+ ancestorContinues: ancestorContinuesMap.get(task.id) ?? [],
4898
+ customDays,
4899
+ isWeekend: isWeekend3
4846
4900
  },
4847
4901
  task.id
4848
4902
  )) }),
@@ -4910,7 +4964,9 @@ var GanttChart = (0, import_react13.forwardRef)(({
4910
4964
  onPromoteTask,
4911
4965
  onDemoteTask,
4912
4966
  enableAddTask = true,
4913
- viewMode = "day"
4967
+ viewMode = "day",
4968
+ customDays,
4969
+ isWeekend: isWeekend3
4914
4970
  }, ref) => {
4915
4971
  const scrollContainerRef = (0, import_react13.useRef)(null);
4916
4972
  const [selectedTaskId, setSelectedTaskId] = (0, import_react13.useState)(null);
@@ -4919,6 +4975,10 @@ var GanttChart = (0, import_react13.forwardRef)(({
4919
4975
  const [collapsedParentIds, setCollapsedParentIds] = (0, import_react13.useState)(/* @__PURE__ */ new Set());
4920
4976
  const [editingTaskId, setEditingTaskId] = (0, import_react13.useState)(null);
4921
4977
  const normalizedTasks = (0, import_react13.useMemo)(() => normalizeHierarchyTasks(tasks), [tasks]);
4978
+ const isCustomWeekend = (0, import_react13.useMemo)(
4979
+ () => createCustomDayPredicate({ customDays, isWeekend: isWeekend3 }),
4980
+ [customDays, isWeekend3]
4981
+ );
4922
4982
  const dateRange = (0, import_react13.useMemo)(() => getMultiMonthDays(normalizedTasks), [normalizedTasks]);
4923
4983
  const [validationResult, setValidationResult] = (0, import_react13.useState)(null);
4924
4984
  const [cascadeOverrides, setCascadeOverrides] = (0, import_react13.useState)(/* @__PURE__ */ new Map());
@@ -5310,7 +5370,9 @@ var GanttChart = (0, import_react13.forwardRef)(({
5310
5370
  collapsedParentIds,
5311
5371
  onToggleCollapse: handleToggleCollapse,
5312
5372
  onPromoteTask: onPromoteTask ?? handlePromoteTask,
5313
- onDemoteTask: onDemoteTask ?? handleDemoteTask
5373
+ onDemoteTask: onDemoteTask ?? handleDemoteTask,
5374
+ customDays,
5375
+ isWeekend: isWeekend3
5314
5376
  }
5315
5377
  ),
5316
5378
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { minWidth: `${gridWidth}px`, flex: 1 }, children: [
@@ -5320,7 +5382,8 @@ var GanttChart = (0, import_react13.forwardRef)(({
5320
5382
  days: dateRange,
5321
5383
  dayWidth,
5322
5384
  headerHeight,
5323
- viewMode
5385
+ viewMode,
5386
+ isCustomWeekend
5324
5387
  }
5325
5388
  ) }),
5326
5389
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
@@ -5338,7 +5401,8 @@ var GanttChart = (0, import_react13.forwardRef)(({
5338
5401
  dateRange,
5339
5402
  dayWidth,
5340
5403
  totalHeight: totalGridHeight,
5341
- viewMode
5404
+ viewMode,
5405
+ isCustomWeekend
5342
5406
  }
5343
5407
  ),
5344
5408
  todayInRange && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TodayIndicator_default, { monthStart, dayWidth }),
@@ -5453,6 +5517,8 @@ init_dateUtils();
5453
5517
  computeLagFromDates,
5454
5518
  computeParentDates,
5455
5519
  computeParentProgress,
5520
+ createCustomDayPredicate,
5521
+ createDateKey,
5456
5522
  detectCycles,
5457
5523
  detectEdgeZone,
5458
5524
  findParentId,