gantt-lib 0.77.0 → 0.78.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
@@ -1,28 +1,12 @@
1
1
  "use client";
2
2
 
3
3
  "use client";
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
- };
11
- var __export = (target, all) => {
12
- for (var name in all)
13
- __defProp(target, name, { get: all[name], enumerable: true });
14
- };
15
- var __copyProps = (to, from, except, desc) => {
16
- if (from && typeof from === "object" || typeof from === "function") {
17
- for (let key of __getOwnPropNames(from))
18
- if (!__hasOwnProp.call(to, key) && key !== except)
19
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
- }
21
- return to;
22
- };
23
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
4
+
5
+ // src/components/GanttChart/GanttChart.tsx
6
+ import { useMemo as useMemo10, useCallback as useCallback8, useRef as useRef9, useState as useState8, useEffect as useEffect9, useImperativeHandle, forwardRef } from "react";
24
7
 
25
8
  // src/core/scheduling/dateMath.ts
9
+ var DAY_MS = 24 * 60 * 60 * 1e3;
26
10
  function normalizeUTCDate(date) {
27
11
  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
28
12
  }
@@ -120,37 +104,328 @@ function getTaskDuration(startDate, endDate, businessDays = false, weekendPredic
120
104
  }
121
105
  return Math.max(1, Math.round((end.getTime() - start.getTime()) / DAY_MS) + 1);
122
106
  }
123
- var DAY_MS;
124
- var init_dateMath = __esm({
125
- "src/core/scheduling/dateMath.ts"() {
126
- "use strict";
127
- DAY_MS = 24 * 60 * 60 * 1e3;
128
- }
129
- });
130
107
 
131
108
  // src/utils/dateUtils.ts
132
- var dateUtils_exports = {};
133
- __export(dateUtils_exports, {
134
- addBusinessDays: () => addBusinessDays2,
135
- createCustomDayPredicate: () => createCustomDayPredicate,
136
- createDateKey: () => createDateKey,
137
- formatDateLabel: () => formatDateLabel,
138
- formatDateRangeLabel: () => formatDateRangeLabel,
139
- getBusinessDaysCount: () => getBusinessDaysCount2,
140
- getDayOffset: () => getDayOffset,
141
- getMonthBlocks: () => getMonthBlocks,
142
- getMonthDays: () => getMonthDays,
143
- getMonthSpans: () => getMonthSpans,
144
- getMultiMonthDays: () => getMultiMonthDays,
145
- getWeekBlocks: () => getWeekBlocks,
146
- getWeekSpans: () => getWeekSpans,
147
- getYearSpans: () => getYearSpans,
148
- isToday: () => isToday,
149
- isWeekend: () => isWeekend,
150
- normalizeTaskDates: () => normalizeTaskDates,
151
- parseUTCDate: () => parseUTCDate,
152
- subtractBusinessDays: () => subtractBusinessDays2
153
- });
109
+ var parseUTCDate = (date) => {
110
+ if (typeof date === "string") {
111
+ const dateStr = date.includes("T") ? date : `${date}T00:00:00Z`;
112
+ const parsed = new Date(dateStr);
113
+ if (isNaN(parsed.getTime())) {
114
+ throw new Error(`Invalid date string: ${date}`);
115
+ }
116
+ return parsed;
117
+ }
118
+ return date;
119
+ };
120
+ var getMonthDays = (date) => {
121
+ const utcDate = parseUTCDate(date);
122
+ const year = utcDate.getUTCFullYear();
123
+ const month = utcDate.getUTCMonth();
124
+ const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
125
+ const days = [];
126
+ for (let day = 1; day <= daysInMonth; day++) {
127
+ days.push(new Date(Date.UTC(year, month, day)));
128
+ }
129
+ return days;
130
+ };
131
+ var getDayOffset = (date, monthStart) => {
132
+ const dateMs = Date.UTC(
133
+ date.getUTCFullYear(),
134
+ date.getUTCMonth(),
135
+ date.getUTCDate()
136
+ );
137
+ const startMs = Date.UTC(
138
+ monthStart.getUTCFullYear(),
139
+ monthStart.getUTCMonth(),
140
+ monthStart.getUTCDate()
141
+ );
142
+ return Math.round((dateMs - startMs) / (1e3 * 60 * 60 * 24));
143
+ };
144
+ var isToday = (date) => {
145
+ const now = /* @__PURE__ */ new Date();
146
+ const today = new Date(Date.UTC(
147
+ now.getFullYear(),
148
+ now.getMonth(),
149
+ now.getDate()
150
+ ));
151
+ const compareDate = new Date(Date.UTC(
152
+ date.getUTCFullYear(),
153
+ date.getUTCMonth(),
154
+ date.getUTCDate()
155
+ ));
156
+ return today.getTime() === compareDate.getTime();
157
+ };
158
+ var isWeekend = (date) => {
159
+ const day = date.getUTCDay();
160
+ return day === 0 || day === 6;
161
+ };
162
+ var createDateKey = (date) => {
163
+ return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
164
+ };
165
+ var createCustomDayPredicate = (config) => {
166
+ const { customDays, isWeekend: basePredicate } = config;
167
+ const workdaySet = /* @__PURE__ */ new Set();
168
+ const weekendSet = /* @__PURE__ */ new Set();
169
+ if (customDays && customDays.length > 0) {
170
+ for (const item of customDays) {
171
+ const key = createDateKey(item.date);
172
+ if (item.type === "workday") {
173
+ workdaySet.add(key);
174
+ } else {
175
+ weekendSet.add(key);
176
+ }
177
+ }
178
+ }
179
+ return (date) => {
180
+ const key = createDateKey(date);
181
+ if (workdaySet.has(key)) {
182
+ return false;
183
+ }
184
+ if (weekendSet.has(key)) {
185
+ return true;
186
+ }
187
+ if (basePredicate) {
188
+ return basePredicate(date);
189
+ }
190
+ const dayOfWeek = date.getUTCDay();
191
+ return dayOfWeek === 0 || dayOfWeek === 6;
192
+ };
193
+ };
194
+ var getMultiMonthDays = (tasks) => {
195
+ if (!tasks || tasks.length === 0) {
196
+ return getMonthDays(/* @__PURE__ */ new Date());
197
+ }
198
+ let minDate = null;
199
+ let maxDate = null;
200
+ for (const task of tasks) {
201
+ const start = parseUTCDate(task.startDate);
202
+ const end = parseUTCDate(task.endDate);
203
+ if (!minDate || start.getTime() < minDate.getTime()) {
204
+ minDate = start;
205
+ }
206
+ if (!maxDate || end.getTime() > maxDate.getTime()) {
207
+ maxDate = end;
208
+ }
209
+ }
210
+ if (!minDate || !maxDate) {
211
+ return getMonthDays(/* @__PURE__ */ new Date());
212
+ }
213
+ const startOfMonth2 = new Date(Date.UTC(
214
+ minDate.getUTCFullYear(),
215
+ minDate.getUTCMonth(),
216
+ 1
217
+ ));
218
+ const endOfMonth = new Date(Date.UTC(
219
+ maxDate.getUTCFullYear(),
220
+ maxDate.getUTCMonth() + 1 + 2,
221
+ // Original + 2 months padding after
222
+ 0
223
+ ));
224
+ const days = [];
225
+ const current = new Date(startOfMonth2);
226
+ while (current.getTime() <= endOfMonth.getTime()) {
227
+ days.push(new Date(Date.UTC(
228
+ current.getUTCFullYear(),
229
+ current.getUTCMonth(),
230
+ current.getUTCDate()
231
+ )));
232
+ current.setUTCDate(current.getUTCDate() + 1);
233
+ }
234
+ return days;
235
+ };
236
+ var getMonthSpans = (dateRange) => {
237
+ if (dateRange.length === 0) {
238
+ return [];
239
+ }
240
+ const spans = [];
241
+ let currentMonthYear = `${dateRange[0].getUTCFullYear()}-${dateRange[0].getUTCMonth()}`;
242
+ let startOfMonthIndex = 0;
243
+ for (let i = 0; i < dateRange.length; i++) {
244
+ const date = dateRange[i];
245
+ const monthYear = `${date.getUTCFullYear()}-${date.getUTCMonth()}`;
246
+ if (monthYear !== currentMonthYear) {
247
+ spans.push({
248
+ month: new Date(Date.UTC(
249
+ dateRange[startOfMonthIndex].getUTCFullYear(),
250
+ dateRange[startOfMonthIndex].getUTCMonth(),
251
+ 1
252
+ )),
253
+ days: i - startOfMonthIndex,
254
+ startIndex: startOfMonthIndex
255
+ });
256
+ currentMonthYear = monthYear;
257
+ startOfMonthIndex = i;
258
+ }
259
+ if (i === dateRange.length - 1) {
260
+ spans.push({
261
+ month: new Date(Date.UTC(
262
+ date.getUTCFullYear(),
263
+ date.getUTCMonth(),
264
+ 1
265
+ )),
266
+ days: i - startOfMonthIndex + 1,
267
+ startIndex: startOfMonthIndex
268
+ });
269
+ }
270
+ }
271
+ return spans;
272
+ };
273
+ var formatDateLabel = (date) => {
274
+ const parsed = parseUTCDate(date);
275
+ const day = String(parsed.getUTCDate()).padStart(2, "0");
276
+ const month = String(parsed.getUTCMonth() + 1).padStart(2, "0");
277
+ return `${day}.${month}`;
278
+ };
279
+ var MONTH_ABBR = [
280
+ "\u044F\u043D\u0432",
281
+ "\u0444\u0435\u0432",
282
+ "\u043C\u0430\u0440",
283
+ "\u0430\u043F\u0440",
284
+ "\u043C\u0430\u044F",
285
+ "\u0438\u044E\u043D",
286
+ "\u0438\u044E\u043B",
287
+ "\u0430\u0432\u0433",
288
+ "\u0441\u0435\u043D",
289
+ "\u043E\u043A\u0442",
290
+ "\u043D\u043E\u044F",
291
+ "\u0434\u0435\u043A"
292
+ ];
293
+ var formatDateRangeLabel = (startDate, endDate) => {
294
+ const start = parseUTCDate(startDate);
295
+ const end = parseUTCDate(endDate);
296
+ const startDay = start.getUTCDate();
297
+ const endDay = end.getUTCDate();
298
+ const startMonth = start.getUTCMonth();
299
+ const endMonth = end.getUTCMonth();
300
+ const startYear = start.getUTCFullYear();
301
+ const endYear = end.getUTCFullYear();
302
+ if (startMonth === endMonth && startYear === endYear) {
303
+ if (startDay === endDay) {
304
+ return `${startDay} ${MONTH_ABBR[startMonth]}`;
305
+ }
306
+ return `${startDay}\u2013${endDay} ${MONTH_ABBR[startMonth]}`;
307
+ }
308
+ if (startYear === endYear) {
309
+ return `${startDay} ${MONTH_ABBR[startMonth]}\u2013${endDay} ${MONTH_ABBR[endMonth]}`;
310
+ }
311
+ return `${startDay} ${MONTH_ABBR[startMonth]} ${startYear}\u2013${endDay} ${MONTH_ABBR[endMonth]} ${endYear}`;
312
+ };
313
+ var getWeekBlocks = (days) => {
314
+ if (days.length === 0) return [];
315
+ const blocks = [];
316
+ let blockStart = 0;
317
+ while (blockStart < days.length) {
318
+ const maxBlockEnd = Math.min(blockStart + 7, days.length);
319
+ const startMonthYear = `${days[blockStart].getUTCFullYear()}-${days[blockStart].getUTCMonth()}`;
320
+ let actualBlockEnd = blockStart + 7;
321
+ if (actualBlockEnd > days.length) {
322
+ actualBlockEnd = days.length;
323
+ }
324
+ for (let i = blockStart + 1; i < maxBlockEnd; i++) {
325
+ const monthYear = `${days[i].getUTCFullYear()}-${days[i].getUTCMonth()}`;
326
+ if (monthYear !== startMonthYear) {
327
+ actualBlockEnd = i;
328
+ break;
329
+ }
330
+ }
331
+ blocks.push({
332
+ startDate: days[blockStart],
333
+ days: actualBlockEnd - blockStart
334
+ });
335
+ blockStart = actualBlockEnd;
336
+ }
337
+ return blocks;
338
+ };
339
+ var getWeekSpans = (days) => {
340
+ const blocks = getWeekBlocks(days);
341
+ if (blocks.length === 0) return [];
342
+ const spans = [];
343
+ let currentMonthYear = `${blocks[0].startDate.getUTCFullYear()}-${blocks[0].startDate.getUTCMonth()}`;
344
+ let startIndex = 0;
345
+ let totalDays = 0;
346
+ for (let i = 0; i < blocks.length; i++) {
347
+ const block = blocks[i];
348
+ const monthYear = `${block.startDate.getUTCFullYear()}-${block.startDate.getUTCMonth()}`;
349
+ if (monthYear !== currentMonthYear) {
350
+ spans.push({
351
+ month: new Date(Date.UTC(
352
+ blocks[startIndex].startDate.getUTCFullYear(),
353
+ blocks[startIndex].startDate.getUTCMonth(),
354
+ 1
355
+ )),
356
+ days: totalDays,
357
+ startIndex
358
+ });
359
+ currentMonthYear = monthYear;
360
+ startIndex = i;
361
+ totalDays = 0;
362
+ }
363
+ totalDays += block.days;
364
+ if (i === blocks.length - 1) {
365
+ spans.push({
366
+ month: new Date(Date.UTC(
367
+ block.startDate.getUTCFullYear(),
368
+ block.startDate.getUTCMonth(),
369
+ 1
370
+ )),
371
+ days: totalDays,
372
+ startIndex
373
+ });
374
+ }
375
+ }
376
+ return spans;
377
+ };
378
+ var getMonthBlocks = (days) => {
379
+ if (days.length === 0) return [];
380
+ return getMonthSpans(days).map((span) => ({
381
+ startDate: span.month,
382
+ days: span.days
383
+ }));
384
+ };
385
+ var getYearSpans = (days) => {
386
+ const blocks = getMonthBlocks(days);
387
+ if (blocks.length === 0) return [];
388
+ const spans = [];
389
+ let currentYear = blocks[0].startDate.getUTCFullYear();
390
+ let startIndex = 0;
391
+ let totalDays = 0;
392
+ for (let i = 0; i < blocks.length; i++) {
393
+ const blockYear = blocks[i].startDate.getUTCFullYear();
394
+ if (blockYear !== currentYear) {
395
+ spans.push({
396
+ year: new Date(Date.UTC(currentYear, 0, 1)),
397
+ days: totalDays,
398
+ startIndex
399
+ });
400
+ currentYear = blockYear;
401
+ startIndex = i;
402
+ totalDays = 0;
403
+ }
404
+ totalDays += blocks[i].days;
405
+ if (i === blocks.length - 1) {
406
+ spans.push({
407
+ year: new Date(Date.UTC(currentYear, 0, 1)),
408
+ days: totalDays,
409
+ startIndex
410
+ });
411
+ }
412
+ }
413
+ return spans;
414
+ };
415
+ var normalizeTaskDates = (startDate, endDate) => {
416
+ const start = parseUTCDate(startDate);
417
+ const end = parseUTCDate(endDate);
418
+ if (end.getTime() < start.getTime()) {
419
+ return {
420
+ startDate: end.toISOString().split("T")[0],
421
+ endDate: start.toISOString().split("T")[0]
422
+ };
423
+ }
424
+ return {
425
+ startDate: start.toISOString().split("T")[0],
426
+ endDate: end.toISOString().split("T")[0]
427
+ };
428
+ };
154
429
  function getBusinessDaysCount2(startDate, endDate, weekendPredicate) {
155
430
  return getBusinessDaysCount(startDate, endDate, weekendPredicate);
156
431
  }
@@ -162,343 +437,8 @@ function subtractBusinessDays2(endDate, businessDays, weekendPredicate) {
162
437
  const result = subtractBusinessDays(endDate, businessDays, weekendPredicate);
163
438
  return result.toISOString().split("T")[0];
164
439
  }
165
- var parseUTCDate, getMonthDays, getDayOffset, isToday, isWeekend, createDateKey, createCustomDayPredicate, getMultiMonthDays, getMonthSpans, formatDateLabel, MONTH_ABBR, formatDateRangeLabel, getWeekBlocks, getWeekSpans, getMonthBlocks, getYearSpans, normalizeTaskDates;
166
- var init_dateUtils = __esm({
167
- "src/utils/dateUtils.ts"() {
168
- "use strict";
169
- init_dateMath();
170
- parseUTCDate = (date) => {
171
- if (typeof date === "string") {
172
- const dateStr = date.includes("T") ? date : `${date}T00:00:00Z`;
173
- const parsed = new Date(dateStr);
174
- if (isNaN(parsed.getTime())) {
175
- throw new Error(`Invalid date string: ${date}`);
176
- }
177
- return parsed;
178
- }
179
- return date;
180
- };
181
- getMonthDays = (date) => {
182
- const utcDate = parseUTCDate(date);
183
- const year = utcDate.getUTCFullYear();
184
- const month = utcDate.getUTCMonth();
185
- const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
186
- const days = [];
187
- for (let day = 1; day <= daysInMonth; day++) {
188
- days.push(new Date(Date.UTC(year, month, day)));
189
- }
190
- return days;
191
- };
192
- getDayOffset = (date, monthStart) => {
193
- const dateMs = Date.UTC(
194
- date.getUTCFullYear(),
195
- date.getUTCMonth(),
196
- date.getUTCDate()
197
- );
198
- const startMs = Date.UTC(
199
- monthStart.getUTCFullYear(),
200
- monthStart.getUTCMonth(),
201
- monthStart.getUTCDate()
202
- );
203
- return Math.round((dateMs - startMs) / (1e3 * 60 * 60 * 24));
204
- };
205
- isToday = (date) => {
206
- const now = /* @__PURE__ */ new Date();
207
- const today = new Date(Date.UTC(
208
- now.getFullYear(),
209
- now.getMonth(),
210
- now.getDate()
211
- ));
212
- const compareDate = new Date(Date.UTC(
213
- date.getUTCFullYear(),
214
- date.getUTCMonth(),
215
- date.getUTCDate()
216
- ));
217
- return today.getTime() === compareDate.getTime();
218
- };
219
- isWeekend = (date) => {
220
- const day = date.getUTCDay();
221
- return day === 0 || day === 6;
222
- };
223
- createDateKey = (date) => {
224
- return `${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`;
225
- };
226
- createCustomDayPredicate = (config) => {
227
- const { customDays, isWeekend: basePredicate } = config;
228
- const workdaySet = /* @__PURE__ */ new Set();
229
- const weekendSet = /* @__PURE__ */ new Set();
230
- if (customDays && customDays.length > 0) {
231
- for (const item of customDays) {
232
- const key = createDateKey(item.date);
233
- if (item.type === "workday") {
234
- workdaySet.add(key);
235
- } else {
236
- weekendSet.add(key);
237
- }
238
- }
239
- }
240
- return (date) => {
241
- const key = createDateKey(date);
242
- if (workdaySet.has(key)) {
243
- return false;
244
- }
245
- if (weekendSet.has(key)) {
246
- return true;
247
- }
248
- if (basePredicate) {
249
- return basePredicate(date);
250
- }
251
- const dayOfWeek = date.getUTCDay();
252
- return dayOfWeek === 0 || dayOfWeek === 6;
253
- };
254
- };
255
- getMultiMonthDays = (tasks) => {
256
- if (!tasks || tasks.length === 0) {
257
- return getMonthDays(/* @__PURE__ */ new Date());
258
- }
259
- let minDate = null;
260
- let maxDate = null;
261
- for (const task of tasks) {
262
- const start = parseUTCDate(task.startDate);
263
- const end = parseUTCDate(task.endDate);
264
- if (!minDate || start.getTime() < minDate.getTime()) {
265
- minDate = start;
266
- }
267
- if (!maxDate || end.getTime() > maxDate.getTime()) {
268
- maxDate = end;
269
- }
270
- }
271
- if (!minDate || !maxDate) {
272
- return getMonthDays(/* @__PURE__ */ new Date());
273
- }
274
- const startOfMonth2 = new Date(Date.UTC(
275
- minDate.getUTCFullYear(),
276
- minDate.getUTCMonth(),
277
- 1
278
- ));
279
- const endOfMonth = new Date(Date.UTC(
280
- maxDate.getUTCFullYear(),
281
- maxDate.getUTCMonth() + 1 + 2,
282
- // Original + 2 months padding after
283
- 0
284
- ));
285
- const days = [];
286
- const current = new Date(startOfMonth2);
287
- while (current.getTime() <= endOfMonth.getTime()) {
288
- days.push(new Date(Date.UTC(
289
- current.getUTCFullYear(),
290
- current.getUTCMonth(),
291
- current.getUTCDate()
292
- )));
293
- current.setUTCDate(current.getUTCDate() + 1);
294
- }
295
- return days;
296
- };
297
- getMonthSpans = (dateRange) => {
298
- if (dateRange.length === 0) {
299
- return [];
300
- }
301
- const spans = [];
302
- let currentMonthYear = `${dateRange[0].getUTCFullYear()}-${dateRange[0].getUTCMonth()}`;
303
- let startOfMonthIndex = 0;
304
- for (let i = 0; i < dateRange.length; i++) {
305
- const date = dateRange[i];
306
- const monthYear = `${date.getUTCFullYear()}-${date.getUTCMonth()}`;
307
- if (monthYear !== currentMonthYear) {
308
- spans.push({
309
- month: new Date(Date.UTC(
310
- dateRange[startOfMonthIndex].getUTCFullYear(),
311
- dateRange[startOfMonthIndex].getUTCMonth(),
312
- 1
313
- )),
314
- days: i - startOfMonthIndex,
315
- startIndex: startOfMonthIndex
316
- });
317
- currentMonthYear = monthYear;
318
- startOfMonthIndex = i;
319
- }
320
- if (i === dateRange.length - 1) {
321
- spans.push({
322
- month: new Date(Date.UTC(
323
- date.getUTCFullYear(),
324
- date.getUTCMonth(),
325
- 1
326
- )),
327
- days: i - startOfMonthIndex + 1,
328
- startIndex: startOfMonthIndex
329
- });
330
- }
331
- }
332
- return spans;
333
- };
334
- formatDateLabel = (date) => {
335
- const parsed = parseUTCDate(date);
336
- const day = String(parsed.getUTCDate()).padStart(2, "0");
337
- const month = String(parsed.getUTCMonth() + 1).padStart(2, "0");
338
- return `${day}.${month}`;
339
- };
340
- MONTH_ABBR = [
341
- "\u044F\u043D\u0432",
342
- "\u0444\u0435\u0432",
343
- "\u043C\u0430\u0440",
344
- "\u0430\u043F\u0440",
345
- "\u043C\u0430\u044F",
346
- "\u0438\u044E\u043D",
347
- "\u0438\u044E\u043B",
348
- "\u0430\u0432\u0433",
349
- "\u0441\u0435\u043D",
350
- "\u043E\u043A\u0442",
351
- "\u043D\u043E\u044F",
352
- "\u0434\u0435\u043A"
353
- ];
354
- formatDateRangeLabel = (startDate, endDate) => {
355
- const start = parseUTCDate(startDate);
356
- const end = parseUTCDate(endDate);
357
- const startDay = start.getUTCDate();
358
- const endDay = end.getUTCDate();
359
- const startMonth = start.getUTCMonth();
360
- const endMonth = end.getUTCMonth();
361
- const startYear = start.getUTCFullYear();
362
- const endYear = end.getUTCFullYear();
363
- if (startMonth === endMonth && startYear === endYear) {
364
- if (startDay === endDay) {
365
- return `${startDay} ${MONTH_ABBR[startMonth]}`;
366
- }
367
- return `${startDay}\u2013${endDay} ${MONTH_ABBR[startMonth]}`;
368
- }
369
- if (startYear === endYear) {
370
- return `${startDay} ${MONTH_ABBR[startMonth]}\u2013${endDay} ${MONTH_ABBR[endMonth]}`;
371
- }
372
- return `${startDay} ${MONTH_ABBR[startMonth]} ${startYear}\u2013${endDay} ${MONTH_ABBR[endMonth]} ${endYear}`;
373
- };
374
- getWeekBlocks = (days) => {
375
- if (days.length === 0) return [];
376
- const blocks = [];
377
- let blockStart = 0;
378
- while (blockStart < days.length) {
379
- const maxBlockEnd = Math.min(blockStart + 7, days.length);
380
- const startMonthYear = `${days[blockStart].getUTCFullYear()}-${days[blockStart].getUTCMonth()}`;
381
- let actualBlockEnd = blockStart + 7;
382
- if (actualBlockEnd > days.length) {
383
- actualBlockEnd = days.length;
384
- }
385
- for (let i = blockStart + 1; i < maxBlockEnd; i++) {
386
- const monthYear = `${days[i].getUTCFullYear()}-${days[i].getUTCMonth()}`;
387
- if (monthYear !== startMonthYear) {
388
- actualBlockEnd = i;
389
- break;
390
- }
391
- }
392
- blocks.push({
393
- startDate: days[blockStart],
394
- days: actualBlockEnd - blockStart
395
- });
396
- blockStart = actualBlockEnd;
397
- }
398
- return blocks;
399
- };
400
- getWeekSpans = (days) => {
401
- const blocks = getWeekBlocks(days);
402
- if (blocks.length === 0) return [];
403
- const spans = [];
404
- let currentMonthYear = `${blocks[0].startDate.getUTCFullYear()}-${blocks[0].startDate.getUTCMonth()}`;
405
- let startIndex = 0;
406
- let totalDays = 0;
407
- for (let i = 0; i < blocks.length; i++) {
408
- const block = blocks[i];
409
- const monthYear = `${block.startDate.getUTCFullYear()}-${block.startDate.getUTCMonth()}`;
410
- if (monthYear !== currentMonthYear) {
411
- spans.push({
412
- month: new Date(Date.UTC(
413
- blocks[startIndex].startDate.getUTCFullYear(),
414
- blocks[startIndex].startDate.getUTCMonth(),
415
- 1
416
- )),
417
- days: totalDays,
418
- startIndex
419
- });
420
- currentMonthYear = monthYear;
421
- startIndex = i;
422
- totalDays = 0;
423
- }
424
- totalDays += block.days;
425
- if (i === blocks.length - 1) {
426
- spans.push({
427
- month: new Date(Date.UTC(
428
- block.startDate.getUTCFullYear(),
429
- block.startDate.getUTCMonth(),
430
- 1
431
- )),
432
- days: totalDays,
433
- startIndex
434
- });
435
- }
436
- }
437
- return spans;
438
- };
439
- getMonthBlocks = (days) => {
440
- if (days.length === 0) return [];
441
- return getMonthSpans(days).map((span) => ({
442
- startDate: span.month,
443
- days: span.days
444
- }));
445
- };
446
- getYearSpans = (days) => {
447
- const blocks = getMonthBlocks(days);
448
- if (blocks.length === 0) return [];
449
- const spans = [];
450
- let currentYear = blocks[0].startDate.getUTCFullYear();
451
- let startIndex = 0;
452
- let totalDays = 0;
453
- for (let i = 0; i < blocks.length; i++) {
454
- const blockYear = blocks[i].startDate.getUTCFullYear();
455
- if (blockYear !== currentYear) {
456
- spans.push({
457
- year: new Date(Date.UTC(currentYear, 0, 1)),
458
- days: totalDays,
459
- startIndex
460
- });
461
- currentYear = blockYear;
462
- startIndex = i;
463
- totalDays = 0;
464
- }
465
- totalDays += blocks[i].days;
466
- if (i === blocks.length - 1) {
467
- spans.push({
468
- year: new Date(Date.UTC(currentYear, 0, 1)),
469
- days: totalDays,
470
- startIndex
471
- });
472
- }
473
- }
474
- return spans;
475
- };
476
- normalizeTaskDates = (startDate, endDate) => {
477
- const start = parseUTCDate(startDate);
478
- const end = parseUTCDate(endDate);
479
- if (end.getTime() < start.getTime()) {
480
- return {
481
- startDate: end.toISOString().split("T")[0],
482
- endDate: start.toISOString().split("T")[0]
483
- };
484
- }
485
- return {
486
- startDate: start.toISOString().split("T")[0],
487
- endDate: end.toISOString().split("T")[0]
488
- };
489
- };
490
- }
491
- });
492
-
493
- // src/components/GanttChart/GanttChart.tsx
494
- init_dateUtils();
495
- import { useMemo as useMemo10, useCallback as useCallback8, useRef as useRef9, useState as useState8, useEffect as useEffect9, useImperativeHandle, forwardRef } from "react";
496
-
497
- // src/core/scheduling/index.ts
498
- init_dateMath();
499
440
 
500
441
  // src/core/scheduling/dependencies.ts
501
- init_dateMath();
502
442
  function normalizePredecessorDates(predecessor, parseDateFn) {
503
443
  const predStart = parseDateFn(predecessor.startDate);
504
444
  const isMilestone = predecessor.type === "milestone";
@@ -605,9 +545,6 @@ function calculateSuccessorDate(predecessorStart, predecessorEnd, linkType, lag
605
545
  return shiftBusinessDayOffset(anchorDate, offset, weekendPredicate);
606
546
  }
607
547
 
608
- // src/core/scheduling/cascade.ts
609
- init_dateMath();
610
-
611
548
  // src/core/scheduling/hierarchy.ts
612
549
  function getChildren(parentId, tasks) {
613
550
  return tasks.filter((t) => t.parentId === parentId);
@@ -729,7 +666,6 @@ function areTasksHierarchicallyRelated(taskId1, taskId2, tasks) {
729
666
  }
730
667
 
731
668
  // src/core/scheduling/commands.ts
732
- init_dateMath();
733
669
  function buildTaskRangeFromStart(startDate, duration, businessDays = false, weekendPredicate, snapDirection = 1) {
734
670
  const normalizedStart = businessDays && weekendPredicate ? alignToWorkingDay(startDate, snapDirection, weekendPredicate) : normalizeUTCDate(startDate);
735
671
  if (businessDays && weekendPredicate) {
@@ -1137,11 +1073,7 @@ function universalCascade(movedTask, newStart, newEnd, allTasks, businessDays =
1137
1073
  return Array.from(resultMap.values());
1138
1074
  }
1139
1075
 
1140
- // src/core/scheduling/modeSwitch.ts
1141
- init_dateMath();
1142
-
1143
1076
  // src/core/scheduling/execute.ts
1144
- init_dateMath();
1145
1077
  function toIsoDate(date) {
1146
1078
  return date.toISOString().split("T")[0];
1147
1079
  }
@@ -1583,7 +1515,6 @@ function validateDependencies(tasks) {
1583
1515
  }
1584
1516
 
1585
1517
  // src/utils/hierarchyOrder.ts
1586
- init_dateUtils();
1587
1518
  function flattenHierarchy(tasks) {
1588
1519
  const byId = new Map(tasks.map((task) => [task.id, task]));
1589
1520
  const byParent = /* @__PURE__ */ new Map();
@@ -1636,7 +1567,6 @@ function normalizeHierarchyTasks(tasks) {
1636
1567
  }
1637
1568
 
1638
1569
  // src/components/TimeScaleHeader/TimeScaleHeader.tsx
1639
- init_dateUtils();
1640
1570
  import { useMemo } from "react";
1641
1571
  import { format } from "date-fns";
1642
1572
  import { ru } from "date-fns/locale";
@@ -1827,7 +1757,6 @@ var TimeScaleHeader = ({
1827
1757
  var TimeScaleHeader_default = TimeScaleHeader;
1828
1758
 
1829
1759
  // src/components/TaskRow/TaskRow.tsx
1830
- init_dateUtils();
1831
1760
  import React2, { useMemo as useMemo2 } from "react";
1832
1761
 
1833
1762
  // src/utils/geometry.ts
@@ -2039,8 +1968,7 @@ var calculateDependencyPath = (from, to, arrivesFromRight) => {
2039
1968
  }
2040
1969
  };
2041
1970
  var calculateWeekGridLines = (dateRange, dayWidth) => {
2042
- const { getWeekBlocks: getWeekBlocks2 } = (init_dateUtils(), __toCommonJS(dateUtils_exports));
2043
- const blocks = getWeekBlocks2(dateRange);
1971
+ const blocks = getWeekBlocks(dateRange);
2044
1972
  const lines = [];
2045
1973
  let currentDayIndex = 0;
2046
1974
  for (let i = 0; i < blocks.length; i++) {
@@ -2096,7 +2024,6 @@ var calculateOrthogonalPath = (from, to) => {
2096
2024
  };
2097
2025
 
2098
2026
  // src/utils/expired.ts
2099
- init_dateUtils();
2100
2027
  var isTaskExpired = (task, referenceDate = /* @__PURE__ */ new Date()) => {
2101
2028
  if (!task) return false;
2102
2029
  const actualProgress = task.progress ?? 0;
@@ -2117,7 +2044,6 @@ var isTaskExpired = (task, referenceDate = /* @__PURE__ */ new Date()) => {
2117
2044
  };
2118
2045
 
2119
2046
  // src/utils/taskType.ts
2120
- init_dateUtils();
2121
2047
  var TASK_TYPE_DEFAULT = "task";
2122
2048
  function getTaskType(task) {
2123
2049
  return task.type ?? TASK_TYPE_DEFAULT;
@@ -2151,7 +2077,6 @@ function normalizeTaskDatesForType(task) {
2151
2077
  import { useEffect, useRef, useState, useCallback } from "react";
2152
2078
 
2153
2079
  // src/adapters/scheduling/drag.ts
2154
- init_dateMath();
2155
2080
  function resolveDateRangeFromPixels(mode, left, width, monthStart, dayWidth, task, businessDays, weekendPredicate) {
2156
2081
  const dayOffset = Math.round(left / dayWidth);
2157
2082
  const rawStartDate = new Date(Date.UTC(
@@ -3035,7 +2960,6 @@ TaskRow.displayName = "TaskRow";
3035
2960
  var TaskRow_default = TaskRow;
3036
2961
 
3037
2962
  // src/components/TodayIndicator/TodayIndicator.tsx
3038
- init_dateUtils();
3039
2963
  import { useMemo as useMemo3 } from "react";
3040
2964
  import { jsx as jsx3 } from "react/jsx-runtime";
3041
2965
  var TodayIndicator = ({ monthStart, dayWidth }) => {
@@ -3471,7 +3395,6 @@ DependencyLines.displayName = "DependencyLines";
3471
3395
  var DependencyLines_default = DependencyLines;
3472
3396
 
3473
3397
  // src/components/TaskList/TaskList.tsx
3474
- init_dateUtils();
3475
3398
  import React11, { useMemo as useMemo8, useCallback as useCallback5, useState as useState6, useEffect as useEffect6, useRef as useRef6 } from "react";
3476
3399
 
3477
3400
  // src/utils/taskListReorder.ts
@@ -3560,7 +3483,6 @@ var PopoverContent = ({
3560
3483
  };
3561
3484
 
3562
3485
  // src/components/TaskList/TaskListRow.tsx
3563
- init_dateUtils();
3564
3486
  import React9, {
3565
3487
  useState as useState4,
3566
3488
  useRef as useRef4,
@@ -4089,7 +4011,6 @@ var LINK_TYPE_LABELS = {
4089
4011
  };
4090
4012
 
4091
4013
  // src/components/TaskList/defaultTaskDates.ts
4092
- init_dateUtils();
4093
4014
  var DAY_MS2 = 24 * 60 * 60 * 1e3;
4094
4015
  var DEFAULT_TASK_DURATION_DAYS = 5;
4095
4016
  function toISODate(date) {
@@ -7285,11 +7206,9 @@ var TaskList = ({
7285
7206
  };
7286
7207
 
7287
7208
  // src/components/ResourceTimelineChart/ResourceTimelineChart.tsx
7288
- init_dateUtils();
7289
7209
  import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo9, useRef as useRef8 } from "react";
7290
7210
 
7291
7211
  // src/utils/resourceTimelineLayout.ts
7292
- init_dateUtils();
7293
7212
  var isInvalidDate = (date) => Number.isNaN(date.getTime());
7294
7213
  var getUTCDayNumber = (date) => {
7295
7214
  return Math.floor(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) / 864e5);
@@ -7684,35 +7603,6 @@ var ITEM_OUTER_VERTICAL_INSET = 2;
7684
7603
  var ITEM_INNER_VERTICAL_INSET = 1;
7685
7604
  var ITEM_HORIZONTAL_INSET = 1;
7686
7605
  var isValidDate = (date) => !Number.isNaN(date.getTime());
7687
- var getResourceTimelineDays = (items) => {
7688
- if (items.length === 0) {
7689
- return getMonthDays(/* @__PURE__ */ new Date());
7690
- }
7691
- let minDate = null;
7692
- let maxDate = null;
7693
- for (const item of items) {
7694
- const startDate = parseUTCDate(item.startDate);
7695
- const endDate = parseUTCDate(item.endDate);
7696
- if (!minDate || startDate.getTime() < minDate.getTime()) {
7697
- minDate = startDate;
7698
- }
7699
- if (!maxDate || endDate.getTime() > maxDate.getTime()) {
7700
- maxDate = endDate;
7701
- }
7702
- }
7703
- if (!minDate || !maxDate) {
7704
- return getMonthDays(/* @__PURE__ */ new Date());
7705
- }
7706
- const startOfMonth2 = new Date(Date.UTC(minDate.getUTCFullYear(), minDate.getUTCMonth(), 1));
7707
- const endOfMonth = new Date(Date.UTC(maxDate.getUTCFullYear(), maxDate.getUTCMonth() + 1, 0));
7708
- const days = [];
7709
- const current = new Date(startOfMonth2);
7710
- while (current.getTime() <= endOfMonth.getTime()) {
7711
- days.push(new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate())));
7712
- current.setUTCDate(current.getUTCDate() + 1);
7713
- }
7714
- return days;
7715
- };
7716
7606
  var collectValidItems = (resources) => {
7717
7607
  return resources.flatMap(
7718
7608
  (resource) => resource.items.flatMap((item) => {
@@ -7785,9 +7675,11 @@ var getDurationValue = (startDate, endDate, businessDays, weekendPredicate) => b
7785
7675
  function ResourceTimelineChart({
7786
7676
  resources,
7787
7677
  dayWidth = DEFAULT_DAY_WIDTH,
7678
+ viewMode = "day",
7788
7679
  rowHeaderWidth = DEFAULT_ROW_HEADER_WIDTH,
7789
7680
  laneHeight = DEFAULT_LANE_HEIGHT,
7790
7681
  headerHeight = DEFAULT_HEADER_HEIGHT,
7682
+ containerHeight,
7791
7683
  allowVerticalPan = false,
7792
7684
  customDays,
7793
7685
  isWeekend: isWeekend3,
@@ -7803,9 +7695,7 @@ function ResourceTimelineChart({
7803
7695
  const gridRef = useRef8(null);
7804
7696
  const panStateRef = useRef8(null);
7805
7697
  const validItems = useMemo9(() => collectValidItems(resources), [resources]);
7806
- const dateRange = useMemo9(() => {
7807
- return getResourceTimelineDays(validItems);
7808
- }, [validItems]);
7698
+ const dateRange = useMemo9(() => getMultiMonthDays(validItems), [validItems]);
7809
7699
  const monthStart = useMemo9(() => {
7810
7700
  const firstDay = dateRange[0] ?? /* @__PURE__ */ new Date();
7811
7701
  return new Date(Date.UTC(firstDay.getUTCFullYear(), firstDay.getUTCMonth(), 1));
@@ -7911,7 +7801,11 @@ function ResourceTimelineChart({
7911
7801
  {
7912
7802
  ref: scrollContainerRef,
7913
7803
  className: "gantt-resourceTimeline-scrollContainer",
7914
- style: { cursor: "grab" },
7804
+ style: {
7805
+ cursor: "grab",
7806
+ height: containerHeight ?? "auto",
7807
+ overflowY: containerHeight === void 0 ? void 0 : "auto"
7808
+ },
7915
7809
  "data-allow-vertical-pan": allowVerticalPan ? "true" : "false",
7916
7810
  onMouseDown: handlePanStart,
7917
7811
  children: /* @__PURE__ */ jsxs12("div", { className: "gantt-resourceTimeline-scrollContent", children: [
@@ -7966,6 +7860,7 @@ function ResourceTimelineChart({
7966
7860
  days: dateRange,
7967
7861
  dayWidth,
7968
7862
  headerHeight,
7863
+ viewMode,
7969
7864
  isCustomWeekend: weekendPredicate
7970
7865
  }
7971
7866
  ) }),
@@ -7982,6 +7877,7 @@ function ResourceTimelineChart({
7982
7877
  dateRange,
7983
7878
  dayWidth,
7984
7879
  totalHeight: layout.totalHeight,
7880
+ viewMode,
7985
7881
  isCustomWeekend: weekendPredicate
7986
7882
  }
7987
7883
  ),
@@ -9178,11 +9074,7 @@ var Button = React14.forwardRef(
9178
9074
  );
9179
9075
  Button.displayName = "Button";
9180
9076
 
9181
- // src/utils/index.ts
9182
- init_dateUtils();
9183
-
9184
9077
  // src/filters/index.ts
9185
- init_dateUtils();
9186
9078
  var and = (...predicates) => (task) => predicates.every((p) => p(task));
9187
9079
  var or = (...predicates) => (task) => predicates.some((p) => p(task));
9188
9080
  var not = (predicate) => (task) => !predicate(task);