@mogura/moguchart-core 0.5.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.
@@ -0,0 +1,3163 @@
1
+ import { LitElement as e, css as t, html as n, render as r, svg as i, unsafeCSS as a } from "lit";
2
+ import { customElement as o, property as s, state as c } from "lit/decorators.js";
3
+ import l from "dayjs";
4
+ import { repeat as u } from "lit/directives/repeat.js";
5
+ import { unsafeHTML as d } from "lit/directives/unsafe-html.js";
6
+ import { throttle as f } from "lodash-es";
7
+ import p from "html2canvas-pro";
8
+ import { jsPDF as m } from "jspdf";
9
+ //#region src/core/patterns.ts
10
+ var h = [
11
+ "diagonal-stripe",
12
+ "diagonal-stripe-thin",
13
+ "diagonal-stripe-thick",
14
+ "diagonal-stripe-reverse",
15
+ "vertical-stripe",
16
+ "horizontal-stripe",
17
+ "checkerboard",
18
+ "dots",
19
+ "triangle",
20
+ "circle",
21
+ "grid",
22
+ "diagonal-grid"
23
+ ], g = { type: "diagonal-stripe" }, _ = { type: "diagonal-stripe-reverse" }, v = { type: "vertical-stripe" }, y = { type: "horizontal-stripe" }, b = { type: "checkerboard" }, x = { type: "dots" }, S = { type: "triangle" }, C = { type: "circle" }, w = { type: "grid" }, T = { type: "diagonal-grid" }, E = { type: "diagonal-stripe-thin" }, D = { type: "diagonal-stripe-thick" }, O = { type: "dots-dense" };
24
+ function k(e) {
25
+ if (!e?.type) return "";
26
+ let t = e.color || "rgba(255, 255, 255, 0.3)", n = e.type === "dots" ? "6px" : "8px";
27
+ switch (e.type) {
28
+ case "diagonal-stripe": return `
29
+ background-image: linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent);
30
+ background-size: ${n} ${n};
31
+ background-repeat: repeat;
32
+ `;
33
+ case "diagonal-stripe-thin": return n = "4px", `
34
+ background-image: linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent);
35
+ background-size: ${n} ${n};
36
+ background-repeat: repeat;
37
+ `;
38
+ case "diagonal-stripe-thick": return n = "16px", `
39
+ background-image: linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent);
40
+ background-size: ${n} ${n};
41
+ background-repeat: repeat;
42
+ `;
43
+ case "diagonal-stripe-reverse": return `
44
+ background-image: linear-gradient(135deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent);
45
+ background-size: ${n} ${n};
46
+ background-repeat: repeat;
47
+ `;
48
+ case "diagonal-grid": return `
49
+ background-image: linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent), linear-gradient(135deg, ${t} 25%, transparent 25%, transparent 50%, ${t} 50%, ${t} 75%, transparent 75%, transparent);
50
+ background-size: ${n} ${n};
51
+ background-repeat: repeat;
52
+ `;
53
+ case "vertical-stripe": return `
54
+ background-image: linear-gradient(90deg, ${t} 50%, transparent 50%);
55
+ background-size: ${n} ${n};
56
+ background-repeat: repeat;
57
+ `;
58
+ case "horizontal-stripe": return `
59
+ background-image: linear-gradient(0deg, ${t} 50%, transparent 50%);
60
+ background-size: ${n} ${n};
61
+ background-repeat: repeat;
62
+ `;
63
+ case "checkerboard": return `
64
+ background-image: linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 75%, ${t} 75%, ${t}), linear-gradient(45deg, ${t} 25%, transparent 25%, transparent 75%, ${t} 75%, ${t});
65
+ background-position: 0 0, calc(${n} / 2) calc(${n} / 2);
66
+ background-size: ${n} ${n};
67
+ background-repeat: repeat;
68
+ `;
69
+ case "dots": return `
70
+ background-image: radial-gradient(${t} 20%, transparent 20%);
71
+ background-size: ${n} ${n};
72
+ background-repeat: repeat;
73
+ `;
74
+ case "dots-dense": return n = "4px", `
75
+ background-image: radial-gradient(${t} 20%, transparent 20%);
76
+ background-size: ${n} ${n};
77
+ background-repeat: repeat;
78
+ `;
79
+ case "triangle": return `
80
+ background-image: conic-gradient(from 150deg at 50% 35%, ${t} 60deg, transparent 60deg);
81
+ background-size: ${n} ${n};
82
+ background-repeat: repeat;
83
+ `;
84
+ case "circle": return `
85
+ background-image: radial-gradient(circle, transparent 50%, ${t} 50%, ${t} 70%, transparent 70%);
86
+ background-size: ${n} ${n};
87
+ background-repeat: repeat;
88
+ `;
89
+ case "grid": return `
90
+ background-image: linear-gradient(${t} 1px, transparent 1px), linear-gradient(90deg, ${t} 1px, transparent 1px);
91
+ background-size: ${n} ${n};
92
+ background-repeat: repeat;
93
+ `;
94
+ default: return "";
95
+ }
96
+ }
97
+ //#endregion
98
+ //#region src/core/i18n.ts
99
+ var A = {
100
+ monthFormat: "YYYY年M月",
101
+ monthRowFormat: "M月",
102
+ dateFormat: (e) => `${e.getFullYear()}/${e.getMonth() + 1}/${e.getDate()}`,
103
+ timeUnitDateFormat: (e) => `${e.getFullYear()}年${e.getMonth() + 1}月${e.getDate()}日`,
104
+ dateTimeFormat: (e) => {
105
+ let t = `${e.getFullYear()}/${e.getMonth() + 1}/${e.getDate()}`, n = e.getHours(), r = e.getMinutes();
106
+ return n === 0 && r === 0 ? t : `${t} ${n.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}`;
107
+ },
108
+ yearMonthFormat: (e) => `${e.getFullYear()}/${e.getMonth() + 1}`,
109
+ duration: {
110
+ days: (e) => `${e}日`,
111
+ hours: (e) => `${e}時間`,
112
+ minutes: (e) => `${e}分`,
113
+ zero: "0分"
114
+ },
115
+ tooltip: { duration: (e) => `所要日数: ${e}日` },
116
+ dragOverlay: {
117
+ noTitle: "タイトルなし",
118
+ moveTo: (e) => `移動先: ${e}`,
119
+ movingTasks: (e) => `${e}件のタスクを移動中`
120
+ }
121
+ }, j = {
122
+ monthFormat: "MMM YYYY",
123
+ monthRowFormat: "MMM",
124
+ dateFormat: (e) => `${e.getMonth() + 1}/${e.getDate()}/${e.getFullYear()}`,
125
+ timeUnitDateFormat: (e) => `${[
126
+ "Jan",
127
+ "Feb",
128
+ "Mar",
129
+ "Apr",
130
+ "May",
131
+ "Jun",
132
+ "Jul",
133
+ "Aug",
134
+ "Sep",
135
+ "Oct",
136
+ "Nov",
137
+ "Dec"
138
+ ][e.getMonth()]} ${e.getDate()}, ${e.getFullYear()}`,
139
+ dateTimeFormat: (e) => {
140
+ let t = `${e.getMonth() + 1}/${e.getDate()}/${e.getFullYear()}`, n = e.getHours(), r = e.getMinutes();
141
+ return n === 0 && r === 0 ? t : `${t} ${n.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}`;
142
+ },
143
+ yearMonthFormat: (e) => `${e.getFullYear()}/${e.getMonth() + 1}`,
144
+ duration: {
145
+ days: (e) => `${e} day${e === 1 ? "" : "s"}`,
146
+ hours: (e) => `${e} hour${e === 1 ? "" : "s"}`,
147
+ minutes: (e) => `${e} minute${e === 1 ? "" : "s"}`,
148
+ zero: "0 minutes"
149
+ },
150
+ tooltip: { duration: (e) => `Duration: ${e} day${e === 1 ? "" : "s"}` },
151
+ dragOverlay: {
152
+ noTitle: "No Title",
153
+ moveTo: (e) => `Move to: ${e}`,
154
+ movingTasks: (e) => `Moving ${e} task${e === 1 ? "" : "s"}`
155
+ }
156
+ }, M = {
157
+ light: {
158
+ bg: "#f1f5f9",
159
+ text: "#0f172a",
160
+ border: "#cbd5e1",
161
+ gridLine: "#cbd5e1",
162
+ subGridLine: "#e2e8f0",
163
+ monthGridLine: "#94a3b8",
164
+ yearGridLine: "#64748b",
165
+ dragTarget: "#e0f2fe",
166
+ tooltipBg: "rgba(0, 0, 0, 0.8)",
167
+ tooltipText: "white",
168
+ dragOverlayBg: "rgba(0, 0, 0, 0.85)",
169
+ dragOverlayText: "white",
170
+ dragOverlaySubText: "#cbd5e1",
171
+ dragOverlayDivider: "#666",
172
+ dependencyLine: "#94a3b8",
173
+ calendarBg: "#e2e8f0",
174
+ saturday: "#dbeafe",
175
+ sunday: "#fee2e2",
176
+ holiday: "#fee2e2",
177
+ rowHeaderBg: "#e2e8f0",
178
+ rowSelected: "#bfdbfe",
179
+ rowSelectedHeader: "#dbeafe",
180
+ rowHiddenBg: "repeating-linear-gradient(45deg, #f3f4f6, #f3f4f6 10px, #e5e7eb 10px, #e5e7eb 20px)",
181
+ currentTimeLine: "rgba(239, 68, 68, 0.5)",
182
+ currentTimeLineText: "#ffffff"
183
+ },
184
+ dark: {
185
+ bg: "#1e293b",
186
+ text: "#f8fafc",
187
+ border: "#263040",
188
+ gridLine: "#334155",
189
+ subGridLine: "#263040",
190
+ monthGridLine: "#475569",
191
+ yearGridLine: "#64748b",
192
+ dragTarget: "rgba(51, 65, 85, 0.5)",
193
+ tooltipBg: "rgba(255, 255, 255, 0.9)",
194
+ tooltipText: "#0f172a",
195
+ dragOverlayBg: "rgba(255, 255, 255, 0.9)",
196
+ dragOverlayText: "#0f172a",
197
+ dragOverlaySubText: "#64748b",
198
+ dragOverlayDivider: "#cbd5e1",
199
+ dependencyLine: "#475569",
200
+ calendarBg: "#0f172a",
201
+ saturday: "rgba(59, 130, 246, 0.15)",
202
+ sunday: "rgba(239, 68, 68, 0.15)",
203
+ holiday: "rgba(239, 68, 68, 0.15)",
204
+ rowHeaderBg: "#0f172a",
205
+ rowSelected: "#283548",
206
+ rowSelectedHeader: "#1c2738",
207
+ rowHiddenBg: "repeating-linear-gradient(45deg, #0f172a, #0f172a 10px, #1e293b 10px, #1e293b 20px)",
208
+ currentTimeLine: "rgba(239, 68, 68, 0.5)",
209
+ currentTimeLineText: "#ffffff"
210
+ }
211
+ }, N = (e, t, n, r) => {
212
+ if (r !== void 0) {
213
+ let n = t.getFullYear(), i = t.getMonth(), a = e.getFullYear(), o = e.getMonth(), s = (a - n) * 12 + (o - i), c = new Date(n, i + 1, 0).getDate(), l = (t.getDate() - 1 + t.getHours() / 24 + t.getMinutes() / 1440) / c, u = new Date(a, o + 1, 0).getDate();
214
+ return (s + (e.getDate() - 1 + e.getHours() / 24 + e.getMinutes() / 1440) / u - l) * r;
215
+ }
216
+ return (e.getTime() - t.getTime()) / (1e3 * 60 * 60 * 24) * n;
217
+ }, P = (e, t, n, r) => {
218
+ if (r !== void 0) {
219
+ let n = t.getFullYear(), i = t.getMonth(), a = new Date(n, i + 1, 0).getDate(), o = (t.getDate() - 1 + t.getHours() / 24 + t.getMinutes() / 1440) / a, s = e / r + o, c = i + Math.floor(s), l = n + Math.floor(c / 12);
220
+ c %= 12, c < 0 && (c += 12, --l);
221
+ let u = (s - Math.floor(s)) * new Date(l, c + 1, 0).getDate(), d = 1 + Math.floor(u), f = (u - Math.floor(u)) * 24, p = Math.floor(f), m = Math.round((f - p) * 60);
222
+ return new Date(l, c, d, p, m);
223
+ }
224
+ let i = e / n;
225
+ return new Date(t.getTime() + i * 24 * 60 * 60 * 1e3);
226
+ };
227
+ function F(e) {
228
+ if (!e.length) return {
229
+ tasksWithLanes: [],
230
+ laneCount: 1
231
+ };
232
+ let t = [...e].sort((e, t) => e.start.getTime() - t.start.getTime()), n = [], r = /* @__PURE__ */ new Map();
233
+ for (let e of t) {
234
+ let t = -1;
235
+ for (let r = 0; r < n.length; r++) if (e.start >= n[r]) {
236
+ n[r] = e.end, t = r;
237
+ break;
238
+ }
239
+ t === -1 && (n.push(e.end), t = n.length - 1), r.set(e.id, t);
240
+ }
241
+ return {
242
+ tasksWithLanes: e.map((e) => ({
243
+ ...e,
244
+ lane: r.get(e.id) ?? 0
245
+ })),
246
+ laneCount: n.length || 1
247
+ };
248
+ }
249
+ var I = (e, t) => ({
250
+ ...M[e] || M.light,
251
+ ...t
252
+ }), L = (e, t, n) => {
253
+ let r = e.getDay();
254
+ return n && n(e) ? t.holiday : [
255
+ t.sunday,
256
+ t.monday ?? "",
257
+ t.tuesday ?? "",
258
+ t.wednesday ?? "",
259
+ t.thursday ?? "",
260
+ t.friday ?? "",
261
+ t.saturday
262
+ ][r];
263
+ };
264
+ function R(e, t) {
265
+ return (t.getTime() - e.getTime()) / (1e3 * 60 * 60 * 24);
266
+ }
267
+ var z = (e, t, n) => {
268
+ let r = n ?? A, i = t.getTime() - e.getTime(), a = Math.floor(i / (1e3 * 60 * 60 * 24)), o = i % (1e3 * 60 * 60 * 24), s = Math.floor(o / (1e3 * 60 * 60)), c = o % (1e3 * 60 * 60), l = Math.floor(c / (1e3 * 60)), u = "";
269
+ return a > 0 && (u += r.duration.days(a)), s > 0 && (u += r.duration.hours(s)), l > 0 && (u += r.duration.minutes(l)), u || r.duration.zero;
270
+ }, B = {
271
+ BAR: "#3b82f6",
272
+ LABEL_BACKGROUND: "#fafafa",
273
+ SATURDAY: "#dbeafe",
274
+ SUNDAY: "#fee2e2",
275
+ HOLIDAY: "#fee2e2",
276
+ BORDER: "#e2e8f0"
277
+ }.BAR;
278
+ //#endregion
279
+ //#region \0@oxc-project+runtime@0.120.0/helpers/decorate.js
280
+ function V(e, t, n, r) {
281
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
282
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
283
+ else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
284
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
285
+ }
286
+ //#endregion
287
+ //#region src/components/gantt-bar.ts
288
+ var H = class extends e {
289
+ constructor(...e) {
290
+ super(...e), this.lane = 0, this.selected = !1, this.focused = !1, this.multiDragDx = 0, this.multiDragActive = !1, this.connectorDropTarget = !1, this.isExporting = !1, this._currentDragCursor = null, this._dragAnimationFrame = null, this._wasDragging = !1, this.handleKeyDown = (e) => {
291
+ (e.key === "Control" || e.key === "Alt") && this.updateCursor(!0);
292
+ }, this.handleKeyUp = (e) => {
293
+ (e.key === "Control" || e.key === "Alt") && this.updateCursor(!1);
294
+ };
295
+ }
296
+ static {
297
+ this.styles = t`
298
+ :host {
299
+ display: block;
300
+ position: absolute;
301
+ top: 0;
302
+ left: 0;
303
+ width: 100%;
304
+ height: 100%;
305
+ pointer-events: none;
306
+ }
307
+ .task-group {
308
+ position: absolute;
309
+ box-sizing: border-box;
310
+ pointer-events: auto;
311
+ z-index: 3;
312
+ }
313
+ .task-group:hover {
314
+ z-index: 50;
315
+ }
316
+ .task-group.dragging {
317
+ opacity: 0.5;
318
+ z-index: 15;
319
+ }
320
+ .bar {
321
+ cursor: grab;
322
+ width: 100%;
323
+ height: 100%;
324
+ position: absolute;
325
+ top: 0;
326
+ left: 0;
327
+ background-color: ${a(B)};
328
+ }
329
+ :host([selected]) .bar {
330
+ outline: 2px solid #3b82f6;
331
+ outline-offset: 1px;
332
+ box-shadow: 0 0 8px rgba(59, 130, 246, 0.5);
333
+ }
334
+ :host([focused]) .bar {
335
+ outline: 2px dashed #3b82f6;
336
+ outline-offset: 2px;
337
+ }
338
+ :host([selected][focused]) .bar {
339
+ outline: 2px solid #3b82f6;
340
+ outline-offset: 1px;
341
+ box-shadow: 0 0 8px rgba(59, 130, 246, 0.5);
342
+ }
343
+ .handle-left,
344
+ .handle-right {
345
+ background: transparent;
346
+ cursor: col-resize;
347
+ position: absolute;
348
+ top: 0;
349
+ bottom: 0;
350
+ width: 10px;
351
+ z-index: 10;
352
+ }
353
+ .handle-left {
354
+ left: 0px;
355
+ }
356
+ .handle-right {
357
+ right: 0px;
358
+ }
359
+ .handle-left:hover,
360
+ .handle-right:hover {
361
+ background: rgba(255, 255, 255, 0.3);
362
+ }
363
+ .connector-left,
364
+ .connector-right {
365
+ position: absolute;
366
+ top: 50%;
367
+ width: 10px;
368
+ height: 10px;
369
+ border-radius: 50%;
370
+ background: #3b82f6;
371
+ border: 2px solid #fff;
372
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
373
+ transform: translateY(-50%);
374
+ cursor: crosshair;
375
+ z-index: 20;
376
+ opacity: 0;
377
+ transition: opacity 0.15s ease;
378
+ pointer-events: auto;
379
+ }
380
+ .task-group:hover .connector-left,
381
+ .task-group:hover .connector-right {
382
+ opacity: 1;
383
+ }
384
+ .connector-left {
385
+ left: -10px;
386
+ }
387
+ .connector-right {
388
+ right: -10px;
389
+ }
390
+ .connector-left:hover,
391
+ .connector-right:hover {
392
+ background: #2563eb;
393
+ transform: translateY(-50%) scale(1.2);
394
+ }
395
+ :host([connector-drop-target]) .bar {
396
+ outline: 2px solid #3b82f6;
397
+ outline-offset: 2px;
398
+ box-shadow: 0 0 12px rgba(59, 130, 246, 0.6);
399
+ }
400
+ .bar-label {
401
+ color: white;
402
+ font-size: 12px;
403
+ pointer-events: none;
404
+ user-select: none;
405
+ position: absolute;
406
+ top: 2px;
407
+ left: 6px;
408
+ white-space: nowrap;
409
+ z-index: 5;
410
+ overflow: hidden;
411
+ text-overflow: ellipsis;
412
+ max-width: calc(100% - 12px);
413
+ }
414
+ :host([isexporting]) .bar,
415
+ :host([isexporting]) .bar * {
416
+ text-overflow: clip !important;
417
+ }
418
+ @keyframes pop-in {
419
+ 0% {
420
+ transform: scale(0.5);
421
+ opacity: 0;
422
+ }
423
+ 60% {
424
+ transform: scale(1.1);
425
+ }
426
+ 100% {
427
+ transform: scale(1);
428
+ opacity: 1;
429
+ }
430
+ }
431
+ @keyframes fade-out {
432
+ 0% {
433
+ transform: scale(1);
434
+ opacity: 1;
435
+ }
436
+ 100% {
437
+ transform: scale(0.5);
438
+ opacity: 0;
439
+ }
440
+ }
441
+ @keyframes collab-pulse {
442
+ 0%,
443
+ 100% {
444
+ outline-offset: 2px;
445
+ filter: brightness(1);
446
+ }
447
+ 50% {
448
+ outline-offset: 3px;
449
+ filter: brightness(1.08);
450
+ }
451
+ }
452
+ `;
453
+ }
454
+ getX(e) {
455
+ return N(e, this.option.calendar.start, this.option.calendar.pxPerDay ?? 50, this.option.calendar.pxPerMonth);
456
+ }
457
+ setupDragEvents(e, t, n, r) {
458
+ let i = () => {
459
+ e.releasePointerCapture(t), window.removeEventListener("pointermove", a), window.removeEventListener("pointerup", o), window.removeEventListener("keydown", s);
460
+ }, a = (e) => {
461
+ n(e);
462
+ }, o = (e) => {
463
+ i(), r(!1, e);
464
+ }, s = (e) => {
465
+ e.key === "Escape" && (i(), r(!0));
466
+ };
467
+ window.addEventListener("pointermove", a), window.addEventListener("pointerup", o), window.addEventListener("keydown", s);
468
+ }
469
+ onResizeStart(e, t) {
470
+ e.stopPropagation();
471
+ let n = e.target, r = this.task.movable ?? "both", i = this.task.resizable, a = !this.option.readOnly;
472
+ if (a &&= i === void 0 ? !(r === "y" || r === "none") : i, !a) return;
473
+ let o = this.shadowRoot?.querySelector(".bar");
474
+ if (!o) return;
475
+ o.style.pointerEvents = "none";
476
+ let s = this.shadowRoot?.querySelector(".task-group");
477
+ s?.classList.add("dragging"), n.setPointerCapture(e.pointerId);
478
+ let c = e.clientX, l = new Date(this.task.start), u = new Date(this.task.end), d = new Date(l), f = new Date(u);
479
+ this.setupDragEvents(n, e.pointerId, (e) => {
480
+ let n = e.clientX - c, r = new Date(l), i = new Date(u), a = this.option.calendar.pxPerDay ?? 50, o = this.option.calendar.pxPerMonth, p = Math.max(this.option.snapDuration ?? 1440, 1);
481
+ if (o) {
482
+ let e = this.getX(l), s = this.getX(u);
483
+ if (t === "left") {
484
+ let t = P(e + n, this.option.calendar.start, a, o);
485
+ t.getDate() > 15 && t.setMonth(t.getMonth() + 1), t.setDate(1), t.setHours(0, 0, 0, 0), r = t, r >= i && (r = new Date(i), r.setMonth(r.getMonth() - 1));
486
+ } else {
487
+ let e = P(s + n, this.option.calendar.start, a, o);
488
+ e.getDate() > 15 && e.setMonth(e.getMonth() + 1), e.setDate(1), e.setHours(0, 0, 0, 0), i = e, i <= r && (i = new Date(r), i.setMonth(i.getMonth() + 1));
489
+ }
490
+ } else {
491
+ let e = a / 1440, o = e * p, s = Math.round(n / o) * o, c = Math.round(s / e);
492
+ t === "left" ? (r = new Date(l.getTime() + c * 60 * 1e3), r >= i && (r = /* @__PURE__ */ new Date(i.getTime() - p * 60 * 1e3))) : (i = new Date(u.getTime() + c * 60 * 1e3), i <= r && (i = new Date(r.getTime() + p * 60 * 1e3)));
493
+ }
494
+ if (d = r, f = i, s) {
495
+ let e = this.getX(r), t = this.getX(i) - e;
496
+ s.style.left = `${e}px`, s.style.width = `${t}px`;
497
+ }
498
+ this._dragAnimationFrame && cancelAnimationFrame(this._dragAnimationFrame), this._dragAnimationFrame = requestAnimationFrame(() => {
499
+ this.dispatchEvent(new CustomEvent("task-update", {
500
+ detail: {
501
+ ...this.task,
502
+ start: r,
503
+ end: i,
504
+ dy: 0,
505
+ isDragging: !0,
506
+ x: e.clientX,
507
+ y: e.clientY
508
+ },
509
+ bubbles: !0,
510
+ composed: !0
511
+ }));
512
+ });
513
+ }, (e) => {
514
+ if (s?.classList.remove("dragging"), o.style.pointerEvents = "", this._dragAnimationFrame &&= (cancelAnimationFrame(this._dragAnimationFrame), null), e) {
515
+ if (s) {
516
+ let e = this.getX(l), t = this.getX(u) - e;
517
+ s.style.left = `${e}px`, s.style.width = `${t}px`;
518
+ }
519
+ this.requestUpdate(), this.dispatchEvent(new CustomEvent("task-update", {
520
+ detail: {
521
+ ...this.task,
522
+ start: l,
523
+ end: u,
524
+ dy: 0,
525
+ isDragging: !1
526
+ },
527
+ bubbles: !0,
528
+ composed: !0
529
+ }));
530
+ } else requestAnimationFrame(() => {
531
+ this.dispatchEvent(new CustomEvent("task-update", {
532
+ detail: {
533
+ ...this.task,
534
+ start: d,
535
+ end: f,
536
+ dy: 0,
537
+ isDragging: !1
538
+ },
539
+ bubbles: !0,
540
+ composed: !0
541
+ }));
542
+ });
543
+ });
544
+ }
545
+ onMoveStart(e) {
546
+ if (e.button === 2) return;
547
+ e.stopPropagation();
548
+ let t = e.target, n = this.shadowRoot?.querySelector(".task-group");
549
+ if (!t || !n) return;
550
+ let r = this.task.movable ?? "both";
551
+ if (r === "none") return;
552
+ let i = e.ctrlKey || e.altKey ? "copy" : "grabbing";
553
+ this._currentDragCursor = i, t.style.cursor = i, t.setPointerCapture(e.pointerId), n.classList.add("dragging");
554
+ let a = e.clientX, o = e.clientY, s = new Date(this.task.start), c = new Date(this.task.end), l = this.option.snapDuration ?? 1440;
555
+ this.setupDragEvents(t, e.pointerId, (e) => {
556
+ let i = e.ctrlKey || e.altKey ? "copy" : "grabbing";
557
+ this._currentDragCursor = i, t.style.cursor = i;
558
+ let u = e.clientX - a, d = e.clientY - o;
559
+ r === "y" && (u = 0), (r === "x" || this.multiDragActive) && (d = 0);
560
+ let f = u;
561
+ if (this.option.calendar.pxPerMonth) {
562
+ let e = P(this.getX(s) + u, this.option.calendar.start, 50, this.option.calendar.pxPerMonth), t = (e.getFullYear() - s.getFullYear()) * 12 + (e.getMonth() - s.getMonth()) + (e.getDate() > 15 ? 1 : 0), n = new Date(s);
563
+ n.setMonth(n.getMonth() + t), f = this.getX(n) - this.getX(s);
564
+ } else {
565
+ let e = this.option.calendar.pxPerDay / 1440 * l;
566
+ f = Math.round(u / e) * e;
567
+ }
568
+ n.style.transform = `translate(${f}px, ${d}px)`, this._dragAnimationFrame && cancelAnimationFrame(this._dragAnimationFrame), this._dragAnimationFrame = requestAnimationFrame(() => {
569
+ let t = e.ctrlKey || e.altKey;
570
+ this.dispatchEvent(new CustomEvent("task-update", {
571
+ detail: {
572
+ ...this.task,
573
+ start: s,
574
+ end: c,
575
+ dx: f,
576
+ dy: d,
577
+ isDragging: !0,
578
+ x: e.clientX,
579
+ y: e.clientY,
580
+ mode: t ? "copy" : "move"
581
+ },
582
+ bubbles: !0,
583
+ composed: !0
584
+ }));
585
+ });
586
+ }, (e, i) => {
587
+ if (this._currentDragCursor = null, n.classList.remove("dragging"), n.style.transform = "", t.style.cursor = "", this._dragAnimationFrame &&= (cancelAnimationFrame(this._dragAnimationFrame), null), e) this.requestUpdate(), this.dispatchEvent(new CustomEvent("task-update", {
588
+ detail: {
589
+ ...this.task,
590
+ start: s,
591
+ end: c,
592
+ dx: 0,
593
+ dy: 0,
594
+ isDragging: !1
595
+ },
596
+ bubbles: !0,
597
+ composed: !0
598
+ }));
599
+ else if (i) {
600
+ let e = i.clientX - a, t = e;
601
+ if (this.option.calendar.pxPerMonth) {
602
+ let n = P(this.getX(s) + e, this.option.calendar.start, 50, this.option.calendar.pxPerMonth), r = (n.getFullYear() - s.getFullYear()) * 12 + (n.getMonth() - s.getMonth()) + (n.getDate() > 15 ? 1 : 0), i = new Date(s);
603
+ i.setMonth(i.getMonth() + r), t = this.getX(i) - this.getX(s);
604
+ } else {
605
+ let n = this.option.calendar.pxPerDay / 1440 * l;
606
+ t = Math.round(e / n) * n;
607
+ }
608
+ let n = i.clientY - o;
609
+ if (r === "y" && (t = 0), (r === "x" || this.multiDragActive) && (n = 0), t === 0 && Math.abs(n) < 5) {
610
+ this.dispatchEvent(new CustomEvent("bar-click", {
611
+ detail: {
612
+ task: this.task,
613
+ event: i,
614
+ isMultiSelect: i.metaKey || i.ctrlKey
615
+ },
616
+ bubbles: !0,
617
+ composed: !0
618
+ })), this._wasDragging = !0;
619
+ return;
620
+ }
621
+ let u = i.ctrlKey || i.altKey;
622
+ this._wasDragging = !0, this.multiDragActive || this.dispatchEvent(new CustomEvent("bar-click", {
623
+ detail: {
624
+ task: this.task,
625
+ event: i,
626
+ isMultiSelect: !1
627
+ },
628
+ bubbles: !0,
629
+ composed: !0
630
+ })), this.dispatchEvent(new CustomEvent("task-update", {
631
+ detail: {
632
+ ...this.task,
633
+ start: s,
634
+ end: c,
635
+ dx: t,
636
+ dy: n,
637
+ isDragging: !1,
638
+ mode: u ? "copy" : "move"
639
+ },
640
+ bubbles: !0,
641
+ composed: !0
642
+ }));
643
+ }
644
+ });
645
+ }
646
+ updated(e) {
647
+ super.updated(e);
648
+ let t = this.shadowRoot?.querySelector(".bar");
649
+ if (t && (this.option.customRendering?.barContent, this.dispatchEvent(new CustomEvent("render-bar-content", {
650
+ detail: {
651
+ container: t,
652
+ task: this.task
653
+ },
654
+ bubbles: !0,
655
+ composed: !0
656
+ })), this._currentDragCursor ? t.style.cursor = this._currentDragCursor : this.option.readOnly || (t.style.cursor = "")), e.has("multiDragDx")) {
657
+ let e = this.shadowRoot?.querySelector(".task-group");
658
+ e && (this.multiDragDx === 0 ? (e.style.transform = "", e.style.opacity = "", e.style.pointerEvents = "") : (e.style.transform = `translateX(${this.multiDragDx}px)`, e.style.opacity = "0.6", e.style.pointerEvents = "none"));
659
+ }
660
+ }
661
+ disconnectedCallback() {
662
+ super.disconnectedCallback(), window.removeEventListener("keydown", this.handleKeyDown), window.removeEventListener("keyup", this.handleKeyUp);
663
+ }
664
+ updateCursor(e) {
665
+ let t = this.shadowRoot?.querySelector(".bar");
666
+ t && !this._currentDragCursor && (t.style.cursor = e ? "copy" : "");
667
+ }
668
+ onMouseEnter(e) {
669
+ let t = e.currentTarget;
670
+ if (t.classList.contains("dragging")) return;
671
+ this.option.readOnly || (window.addEventListener("keydown", this.handleKeyDown), window.addEventListener("keyup", this.handleKeyUp), (e.ctrlKey || e.altKey) && this.updateCursor(!0));
672
+ let n = t.getBoundingClientRect();
673
+ this.dispatchEvent(new CustomEvent("bar-mouseenter", {
674
+ detail: {
675
+ task: this.task,
676
+ x: n.left + n.width / 2,
677
+ y: n.top
678
+ },
679
+ bubbles: !0,
680
+ composed: !0
681
+ }));
682
+ }
683
+ onMouseLeave() {
684
+ this.option.readOnly || (window.removeEventListener("keydown", this.handleKeyDown), window.removeEventListener("keyup", this.handleKeyUp), this.updateCursor(!1)), this.dispatchEvent(new CustomEvent("bar-mouseleave", {
685
+ bubbles: !0,
686
+ composed: !0
687
+ }));
688
+ }
689
+ onDblClick(e) {
690
+ this.dispatchEvent(new CustomEvent("task-dblclick", {
691
+ detail: {
692
+ task: this.task,
693
+ event: e
694
+ },
695
+ bubbles: !0,
696
+ composed: !0
697
+ }));
698
+ }
699
+ onClick(e) {
700
+ if (e.stopPropagation(), this._wasDragging) {
701
+ this._wasDragging = !1;
702
+ return;
703
+ }
704
+ this.dispatchEvent(new CustomEvent("bar-click", {
705
+ detail: {
706
+ task: this.task,
707
+ event: e,
708
+ isMultiSelect: e.metaKey || e.ctrlKey
709
+ },
710
+ bubbles: !0,
711
+ composed: !0
712
+ }));
713
+ }
714
+ onConnectorDragStart(e, t) {
715
+ e.stopPropagation(), e.preventDefault();
716
+ let n = e.target;
717
+ if (n.setPointerCapture(e.pointerId), !this.shadowRoot?.querySelector(".task-group")) return;
718
+ let r = this.option.bar?.height ?? 28, i = this.option.bar?.margin ?? 4, a = this.getX(this.task.start), o = this.getX(this.task.end) - a, s = this.lane * (r + i) + i, c = t === "start" ? a : a + o, l = s + r / 2;
719
+ this.dispatchEvent(new CustomEvent("connector-drag-start", {
720
+ detail: {
721
+ taskId: this.task.id,
722
+ endpoint: t,
723
+ startX: c,
724
+ startY: l,
725
+ clientX: e.clientX,
726
+ clientY: e.clientY
727
+ },
728
+ bubbles: !0,
729
+ composed: !0
730
+ })), this.setupDragEvents(n, e.pointerId, (e) => {
731
+ this.dispatchEvent(new CustomEvent("connector-drag-move", {
732
+ detail: {
733
+ taskId: this.task.id,
734
+ endpoint: t,
735
+ startX: c,
736
+ startY: l,
737
+ clientX: e.clientX,
738
+ clientY: e.clientY
739
+ },
740
+ bubbles: !0,
741
+ composed: !0
742
+ }));
743
+ }, (e) => {
744
+ this.dispatchEvent(new CustomEvent("connector-drag-end", {
745
+ detail: {
746
+ taskId: this.task.id,
747
+ endpoint: t,
748
+ cancelled: e
749
+ },
750
+ bubbles: !0,
751
+ composed: !0
752
+ }));
753
+ });
754
+ }
755
+ onContextMenu(e) {
756
+ if (e.ctrlKey) {
757
+ e.preventDefault(), e.stopPropagation();
758
+ return;
759
+ }
760
+ e.preventDefault(), e.stopPropagation(), this.dispatchEvent(new CustomEvent("task-contextmenu", {
761
+ detail: {
762
+ task: this.task,
763
+ event: e
764
+ },
765
+ bubbles: !0,
766
+ composed: !0
767
+ }));
768
+ }
769
+ render() {
770
+ if (!this.task || !this.option) return n``;
771
+ let e = this.getX(this.task.start), t = this.getX(this.task.end) - e, r = this.option.bar?.height ?? 28, i = this.option.bar?.margin ?? 4, a = this.option.bar?.cornerRadius ?? 4, o = this.lane * (r + i) + i, s = this.option.readOnly, c = this.task.movable ?? "both", l = this.task.resizable, u = !s && c !== "none", d = !s;
772
+ return d &&= l === void 0 ? !(c === "y" || c === "none") : l, n`
773
+ <div
774
+ class="task-group"
775
+ style="
776
+ left: ${e}px;
777
+ top: ${o}px;
778
+ width: ${t}px;
779
+ height: ${r}px;
780
+ "
781
+ @mouseenter="${this.onMouseEnter}"
782
+ @mouseleave="${this.onMouseLeave}"
783
+ @click="${this.onClick}"
784
+ @dblclick="${this.onDblClick}"
785
+ @contextmenu="${this.onContextMenu}"
786
+ >
787
+ <div
788
+ class="bar"
789
+ style="border-radius: ${a}px; ${this.task.style || ""}; ${k(this.task.pattern)}; ${u ? "" : "cursor: pointer;"}"
790
+ @pointerdown="${u ? this.onMoveStart : void 0}"
791
+ >
792
+ ${this.option.customRendering?.barContent ? this.option.customRendering.barContent(this.task) : ""}
793
+ </div>
794
+ ${!this.option.customRendering?.barContent && this.task.name ? n`<div class="bar-label" style="${this.task.labelStyle || ""}">${this.task.name}</div>` : ""}
795
+ ${d ? n`
796
+ <div class="handle-left" @pointerdown="${(e) => this.onResizeStart(e, "left")}"></div>
797
+ <div class="handle-right" @pointerdown="${(e) => this.onResizeStart(e, "right")}"></div>
798
+ ` : ""}
799
+ ${s ? "" : n`
800
+ <div
801
+ class="connector-left"
802
+ @pointerdown="${(e) => this.onConnectorDragStart(e, "start")}"
803
+ ></div>
804
+ <div
805
+ class="connector-right"
806
+ @pointerdown="${(e) => this.onConnectorDragStart(e, "end")}"
807
+ ></div>
808
+ `}
809
+ </div>
810
+ `;
811
+ }
812
+ };
813
+ V([s({ type: Object })], H.prototype, "task", void 0), V([s({ type: Object })], H.prototype, "option", void 0), V([s({ type: Number })], H.prototype, "lane", void 0), V([s({
814
+ type: Boolean,
815
+ reflect: !0
816
+ })], H.prototype, "selected", void 0), V([s({
817
+ type: Boolean,
818
+ reflect: !0
819
+ })], H.prototype, "focused", void 0), V([s({ type: Number })], H.prototype, "multiDragDx", void 0), V([s({ type: Boolean })], H.prototype, "multiDragActive", void 0), V([s({
820
+ type: Boolean,
821
+ reflect: !0,
822
+ attribute: "connector-drop-target"
823
+ })], H.prototype, "connectorDropTarget", void 0), V([s({
824
+ type: Boolean,
825
+ reflect: !0
826
+ })], H.prototype, "isExporting", void 0), H = V([o("gantt-bar")], H);
827
+ //#endregion
828
+ //#region src/components/gantt-calendar.ts
829
+ var U = class extends e {
830
+ constructor(...e) {
831
+ super(...e), this.theme = "light", this.currentTime = /* @__PURE__ */ new Date(), this.hoveredMilestoneId = null, this._cachedDays = null, this._cachedMonths = null, this._cachedYears = null, this._cachedWeeks = null, this._cachedStartTime = 0, this._cachedEndTime = 0, this._cachedPxPerDay = 0, this._cachedPxPerMonth = void 0, this._cachedWeekStartDay = -1;
832
+ }
833
+ injectCustomContent(e, t, n) {
834
+ let r = e.querySelector(`.${n}`);
835
+ if (r && r.remove(), t instanceof HTMLElement) t.classList.add(n), e.appendChild(t);
836
+ else if (typeof t == "string") {
837
+ let r = document.createElement("span");
838
+ r.classList.add(n), r.innerHTML = t, e.appendChild(r);
839
+ }
840
+ }
841
+ updated() {
842
+ let e = this.shadowRoot?.querySelector(".label-placeholder");
843
+ if (!e) return;
844
+ let t = e.querySelector(".corner-content-root");
845
+ if (t && t.remove(), this.cornerContent) {
846
+ let t = this.cornerContent();
847
+ t instanceof HTMLElement && (t.classList.add("corner-content-root"), e.appendChild(t));
848
+ }
849
+ this.injectCalendarCustomContent();
850
+ }
851
+ injectCalendarCustomContent() {
852
+ this.calendarMonthContent && (this.shadowRoot?.querySelectorAll("[data-calendar-month]"))?.forEach((e) => {
853
+ let t = e, n = {
854
+ year: parseInt(t.dataset.calendarMonthYear ?? "0", 10),
855
+ month: parseInt(t.dataset.calendarMonth ?? "0", 10),
856
+ width: parseFloat(t.dataset.calendarMonthWidth ?? "0"),
857
+ defaultLabel: t.dataset.calendarMonthLabel ?? ""
858
+ }, r = this.calendarMonthContent(n);
859
+ this.injectCustomContent(t, r, "custom-month-content");
860
+ }), this.calendarDayContent && (this.shadowRoot?.querySelectorAll("[data-calendar-day]"))?.forEach((e) => {
861
+ let t = e, n = t.dataset.calendarDay ?? "", r = {
862
+ date: new Date(n),
863
+ width: parseFloat(t.dataset.calendarDayWidth ?? "0"),
864
+ isSaturday: t.dataset.calendarDaySaturday === "true",
865
+ isSunday: t.dataset.calendarDaySunday === "true",
866
+ isHoliday: t.dataset.calendarDayHoliday === "true",
867
+ defaultLabel: t.dataset.calendarDayLabel ?? ""
868
+ }, i = this.calendarDayContent(r);
869
+ this.injectCustomContent(t, i, "custom-day-content");
870
+ }), this.calendarWeekContent && (this.shadowRoot?.querySelectorAll("[data-calendar-week]"))?.forEach((e) => {
871
+ let t = e, n = parseInt(t.dataset.calendarWeek ?? "0", 10), r = t.dataset.calendarWeekStart ?? "", i = {
872
+ weekNumber: n,
873
+ startDate: new Date(r),
874
+ width: parseFloat(t.dataset.calendarWeekWidth ?? "0"),
875
+ defaultLabel: t.dataset.calendarWeekLabel ?? ""
876
+ }, a = this.calendarWeekContent(i);
877
+ this.injectCustomContent(t, a, "custom-week-content");
878
+ }), this.calendarHourContent && (this.shadowRoot?.querySelectorAll("[data-calendar-hour]"))?.forEach((e) => {
879
+ let t = e, n = parseInt(t.dataset.calendarHour ?? "0", 10), r = parseFloat(t.dataset.calendarHourWidth ?? "0"), i = t.dataset.calendarHourDate ?? "", a = {
880
+ hour: n,
881
+ width: r,
882
+ date: new Date(i)
883
+ }, o = this.calendarHourContent(a);
884
+ this.injectCustomContent(t, o, "custom-hour-content");
885
+ });
886
+ }
887
+ get totalDays() {
888
+ return R(this.option.calendar.start, this.option.calendar.end);
889
+ }
890
+ static {
891
+ this.styles = t`
892
+ :host {
893
+ display: flex;
894
+ width: fit-content;
895
+ min-width: 100%;
896
+ box-sizing: border-box;
897
+ position: sticky;
898
+ top: 0;
899
+ z-index: 500;
900
+ }
901
+ .label-placeholder {
902
+ flex-shrink: 0;
903
+ box-sizing: border-box;
904
+ position: sticky;
905
+ left: 0;
906
+ z-index: 100;
907
+ background: inherit;
908
+ display: flex;
909
+ align-items: center;
910
+ justify-content: flex-end;
911
+ padding-right: 4px;
912
+ overflow: hidden;
913
+ }
914
+ .calendar-group {
915
+ display: flex;
916
+ flex-direction: column;
917
+ position: relative;
918
+ z-index: 70;
919
+ }
920
+ .months-container {
921
+ display: flex;
922
+ }
923
+ .month-cell {
924
+ box-sizing: border-box;
925
+ padding: 4px 8px;
926
+ font-size: 12px;
927
+ font-weight: bold;
928
+ white-space: nowrap;
929
+ overflow: hidden;
930
+ }
931
+ .weeks-container {
932
+ display: flex;
933
+ }
934
+ .week-cell {
935
+ box-sizing: border-box;
936
+ padding: 4px 0;
937
+ font-size: 10px;
938
+ font-weight: bold;
939
+ text-align: center;
940
+ flex-shrink: 0;
941
+ white-space: nowrap;
942
+ overflow: hidden;
943
+ }
944
+ .days-container {
945
+ display: flex;
946
+ }
947
+ .day-cell {
948
+ text-align: center;
949
+ font-size: 10px;
950
+ padding: 6px 0;
951
+ flex-shrink: 0;
952
+ box-sizing: border-box;
953
+ word-break: break-all;
954
+ line-height: 1.1;
955
+ display: flex;
956
+ align-items: center;
957
+ justify-content: center;
958
+ }
959
+ .hours-container {
960
+ display: flex;
961
+ }
962
+ .hour-cell {
963
+ text-align: center;
964
+ font-size: 10px;
965
+ padding: 2px 0;
966
+ flex-shrink: 0;
967
+ box-sizing: border-box;
968
+ overflow: hidden;
969
+ }
970
+ .current-time-badge {
971
+ position: absolute;
972
+ bottom: 0;
973
+ transform: translateX(-50%);
974
+ padding: 2px 4px;
975
+ border-radius: 4px;
976
+ font-size: 10px;
977
+ font-weight: bold;
978
+ white-space: nowrap;
979
+ z-index: 10;
980
+ pointer-events: none;
981
+ }
982
+ .milestone-badge {
983
+ position: absolute;
984
+ top: 0;
985
+ transform: translateX(-50%);
986
+ padding: 2px 4px;
987
+ border-radius: 4px;
988
+ font-size: 10px;
989
+ font-weight: bold;
990
+ white-space: nowrap;
991
+ z-index: 9;
992
+ pointer-events: auto;
993
+ color: #ffffff;
994
+ transition: opacity 0.2s ease;
995
+ cursor: default;
996
+ }
997
+ .milestone-connector {
998
+ position: absolute;
999
+ top: 19px;
1000
+ bottom: 0px;
1001
+ transform: translateX(-50%);
1002
+ z-index: 8;
1003
+ pointer-events: auto;
1004
+ transition: opacity 0.2s ease;
1005
+ cursor: default;
1006
+ }
1007
+ `;
1008
+ }
1009
+ getDateX(e) {
1010
+ return N(e, this.option.calendar.start, this.option.calendar.pxPerDay, this.option.calendar.pxPerMonth);
1011
+ }
1012
+ formatTime(e) {
1013
+ return `${e.getHours().toString().padStart(2, "0")}:${e.getMinutes().toString().padStart(2, "0")}`;
1014
+ }
1015
+ _buildWeeks(e, t) {
1016
+ let n = (e) => {
1017
+ let n = new Date(e.getTime());
1018
+ n.setHours(0, 0, 0, 0);
1019
+ let r = (n.getDay() - t + 7) % 7, i = new Date(n.getTime());
1020
+ i.setDate(i.getDate() - r);
1021
+ let a = new Date(i.getFullYear(), 0, 1), o = Math.floor((i.getTime() - a.getTime()) / 864e5);
1022
+ return Math.floor(o / 7) + 1;
1023
+ }, r = [];
1024
+ return e.forEach((e) => {
1025
+ let i = e.getDay() === t, a = r[r.length - 1];
1026
+ a && !i ? a.count++ : r.push({
1027
+ weekNumber: n(e),
1028
+ startDate: new Date(e),
1029
+ count: 1
1030
+ });
1031
+ }), r;
1032
+ }
1033
+ render() {
1034
+ let e = I(this.theme, this.option.customTheme), t = this.option.calendar.start.getTime(), r = this.option.calendar.end.getTime(), i = this.option.calendar.pxPerDay, a = this.option.calendar.pxPerMonth, o = this.option.calendar.weekStartDay ?? 1, s = !this._cachedDays || t !== this._cachedStartTime || r !== this._cachedEndTime, c = i !== this._cachedPxPerDay || a !== this._cachedPxPerMonth;
1035
+ if (s) {
1036
+ this._cachedStartTime = t, this._cachedEndTime = r, this._cachedPxPerDay = i, this._cachedPxPerMonth = a;
1037
+ let e = Array.from({ length: Math.ceil(this.totalDays) }, (e, t) => {
1038
+ let n = new Date(this.option.calendar.start);
1039
+ return n.setDate(n.getDate() + t), n;
1040
+ });
1041
+ this._cachedDays = e;
1042
+ let n = [];
1043
+ e.forEach((e) => {
1044
+ let t = e.getFullYear(), r = e.getMonth(), i = n[n.length - 1];
1045
+ if (i && i.year === t && i.month === r) i.count++, i.end = new Date(e), i.end.setDate(i.end.getDate() + 1);
1046
+ else {
1047
+ let i = new Date(e);
1048
+ i.setHours(0, 0, 0, 0);
1049
+ let a = new Date(e);
1050
+ a.setDate(a.getDate() + 1), n.push({
1051
+ year: t,
1052
+ month: r,
1053
+ count: 1,
1054
+ start: i,
1055
+ end: a
1056
+ });
1057
+ }
1058
+ }), n.forEach((e) => {
1059
+ e.start && e.end && (e.width = this.getDateX(e.end) - this.getDateX(e.start));
1060
+ }), this._cachedMonths = n;
1061
+ let s = [];
1062
+ e.forEach((e) => {
1063
+ let t = e.getFullYear(), n = s[s.length - 1];
1064
+ if (n && n.year === t) n.count++, n.end = new Date(e), n.end.setDate(n.end.getDate() + 1);
1065
+ else {
1066
+ let n = new Date(e);
1067
+ n.setHours(0, 0, 0, 0);
1068
+ let r = new Date(e);
1069
+ r.setDate(r.getDate() + 1), s.push({
1070
+ year: t,
1071
+ count: 1,
1072
+ start: n,
1073
+ end: r
1074
+ });
1075
+ }
1076
+ }), s.forEach((e) => {
1077
+ e.start && e.end && (e.width = this.getDateX(e.end) - this.getDateX(e.start));
1078
+ }), this._cachedYears = s, this._cachedWeekStartDay = o, this._cachedWeeks = this._buildWeeks(e, o);
1079
+ } else c ? (this._cachedPxPerDay = i, this._cachedPxPerMonth = a, this._cachedMonths.forEach((e) => {
1080
+ e.start && e.end && (e.width = this.getDateX(e.end) - this.getDateX(e.start));
1081
+ }), this._cachedYears.forEach((e) => {
1082
+ e.start && e.end && (e.width = this.getDateX(e.end) - this.getDateX(e.start));
1083
+ }), o !== this._cachedWeekStartDay && (this._cachedWeekStartDay = o, this._cachedWeeks = this._buildWeeks(this._cachedDays, o))) : o !== this._cachedWeekStartDay && (this._cachedWeekStartDay = o, this._cachedWeeks = this._buildWeeks(this._cachedDays, o));
1084
+ let u = this._cachedDays, d = this._cachedMonths, f = this._cachedYears, p = `
1085
+ background-image: linear-gradient(90deg, transparent ${this.option.calendar.pxPerDay - 1}px, ${e.border} ${this.option.calendar.pxPerDay - 1}px);
1086
+ background-size: ${this.option.calendar.pxPerDay}px 100%;
1087
+ `, m = this.option.calendar.pxPerDay / 24, h = this.option.calendar.pxPerDay, g = this.option.customTheme?.showTimeDateLine ?? e.monthGridLine ?? e.border, _ = this.option.calendar.start, v = (_.getHours() * 60 * 60 * 1e3 + _.getMinutes() * 60 * 1e3 + _.getSeconds() * 1e3) / (1440 * 60 * 1e3) * h, y = v % m, b = v === 0 ? "0px 0" : `${-v}px 0`, x = y === 0 ? "0px 0" : `${-y}px 0`, S = `
1088
+ background-image: linear-gradient(90deg, transparent ${h - 1}px, ${g} ${h - 1}px), linear-gradient(90deg, transparent ${m - 1}px, ${e.border} ${m - 1}px);
1089
+ background-size: ${h}px 100%, ${m}px 100%;
1090
+ background-position: ${b}, ${x};
1091
+ `, C = [];
1092
+ if (this.option.calendar.showTime) {
1093
+ let e = this.option.calendar.start, t = this.option.calendar.end, n = new Date(e);
1094
+ for (n.setHours(0, 0, 0, 0); n.getTime() < t.getTime();) {
1095
+ let r = n.getTime() < e.getTime() ? e : n, i = new Date(n);
1096
+ i.setDate(i.getDate() + 1);
1097
+ let a = i.getTime() > t.getTime() ? t : i, o = r.getHours(), s = a.getHours(), c = a.getMinutes() > 0 || a.getSeconds() > 0 || a.getMilliseconds() > 0, l = s === 0 && !c ? 24 : c ? s + 1 : s, u = (a.getTime() - r.getTime()) / (1e3 * 60 * 60);
1098
+ C.push({
1099
+ date: new Date(n),
1100
+ hStart: o,
1101
+ hEnd: l,
1102
+ widthPx: u * m
1103
+ }), n = new Date(i);
1104
+ }
1105
+ }
1106
+ let w = d[d.length - 1], T = this.option.calendar.pxPerMonth !== void 0 && w?.end ? this.getDateX(w.end) : this.getDateX(this.option.calendar.end);
1107
+ return n`
1108
+ <style>
1109
+ :host {
1110
+ background: ${e.calendarBg};
1111
+ border-bottom: 2px solid ${e.border};
1112
+ color: ${e.text};
1113
+ }
1114
+ .label-placeholder {
1115
+ border-right: 1px solid ${e.border};
1116
+ }
1117
+ .months-container {
1118
+ background: ${e.bg};
1119
+ border-bottom: 1px solid ${e.border};
1120
+ }
1121
+ .hours-container {
1122
+ border-top: 1px solid ${e.border};
1123
+ }
1124
+ </style>
1125
+ <div
1126
+ class="label-placeholder"
1127
+ style="width: ${this.option.rowHeader?.width ?? 150}px; background-color: ${this.option.rowHeader?.backgroundColor ?? e.rowHeaderBg};"
1128
+ ></div>
1129
+ <div class="calendar-group" style="width: ${T}px; overflow: hidden;">
1130
+ ${this.option.calendar.showMonthsRow ? (() => {
1131
+ let t = this.option.calendar.monthTextAlign ?? "center";
1132
+ return n`<div class="months-container" style="position: relative; z-index: 2;">
1133
+ ${f.map((e) => n`<div
1134
+ class="month-cell"
1135
+ style="width: ${e.width ?? e.count * this.option.calendar.pxPerDay}px;"
1136
+ >
1137
+ ${e.year}
1138
+ </div>`)}
1139
+ </div>
1140
+ <div
1141
+ class="weeks-container"
1142
+ style="background: ${e.bg}; border-bottom: 1px solid ${e.border}; position: relative;"
1143
+ >
1144
+ ${d.map((e) => {
1145
+ let r = (this.option.locale ?? A).monthRowFormat, i = l(new Date(e.year, e.month)).format(r), a = e.width ?? e.count * this.option.calendar.pxPerDay;
1146
+ return n`<div
1147
+ class="week-cell"
1148
+ style="width: ${a}px; text-align: ${t}; padding: 0 2px;"
1149
+ data-calendar-month="${e.month}"
1150
+ data-calendar-month-year="${e.year}"
1151
+ data-calendar-month-width="${a}"
1152
+ data-calendar-month-label="${i}"
1153
+ >
1154
+ ${this.calendarMonthContent ? "" : i}
1155
+ </div>`;
1156
+ })}
1157
+ </div>`;
1158
+ })() : ""}
1159
+ ${this.option.calendar.showMonths !== !1 && !this.option.calendar.showMonthsRow ? n`<div class="months-container" style="position: relative;">
1160
+ ${d.map((e) => {
1161
+ let t = this.option.calendar.monthFormat || (this.option.locale ?? A).monthFormat, r = l(new Date(e.year, e.month)).format(t), i = e.width ?? e.count * this.option.calendar.pxPerDay;
1162
+ return n`<div
1163
+ class="month-cell"
1164
+ style="width: ${i}px;"
1165
+ data-calendar-month="${e.month}"
1166
+ data-calendar-month-year="${e.year}"
1167
+ data-calendar-month-width="${i}"
1168
+ data-calendar-month-label="${r}"
1169
+ >
1170
+ ${this.calendarMonthContent ? "" : r}
1171
+ </div>`;
1172
+ })}
1173
+ </div>` : ""}
1174
+ ${this.option.calendar.showWeeks ? (() => {
1175
+ let t = this._cachedWeeks, r = `
1176
+ background: ${e.bg};
1177
+ border-bottom: 1px solid ${e.border};
1178
+ `, i = this.option.calendar.weekFormat, a = this.option.calendar.weekTextAlign ?? "center";
1179
+ return n`<div class="weeks-container" style="${r}">
1180
+ ${t.map((t) => {
1181
+ let r = i ? i(t.weekNumber, t.startDate) : `W${t.weekNumber}`, o = t.count * this.option.calendar.pxPerDay;
1182
+ return n`<div
1183
+ class="week-cell"
1184
+ style="width: ${o}px; border-right: 1px solid ${e.border}; text-align: ${a}; padding: 0 2px;"
1185
+ data-calendar-week="${t.weekNumber}"
1186
+ data-calendar-week-start="${t.startDate.toISOString()}"
1187
+ data-calendar-week-width="${o}"
1188
+ data-calendar-week-label="${r}"
1189
+ >
1190
+ ${this.calendarWeekContent ? "" : r}
1191
+ </div>`;
1192
+ })}
1193
+ </div>`;
1194
+ })() : ""}
1195
+ ${this.option.calendar.showDays === !1 ? "" : n`<div class="days-container" style="${this.option.calendar.showTime ? "" : p}">
1196
+ ${this.option.calendar.showTime ? C.map((t, r) => {
1197
+ let i = L(t.date, e, this.option.calendar.isHoliday), a = r === C.length - 1, o = e.showTimeDateLine ?? e.monthGridLine ?? e.border, s = (this.option.locale ?? A).timeUnitDateFormat(t.date), c = this.option.calendar.isHoliday ? this.option.calendar.isHoliday(t.date) : !1;
1198
+ return n`
1199
+ <div
1200
+ class="day-cell"
1201
+ style="width: ${t.widthPx}px; border-right: ${a ? "none" : `1px solid ${o}`}; ${i ? `background-color: ${i};` : ""} font-size: 12px; font-weight: 700; justify-content: flex-start; padding-left: 4px;"
1202
+ data-calendar-day="${t.date.toISOString()}"
1203
+ data-calendar-day-width="${t.widthPx}"
1204
+ data-calendar-day-saturday="${t.date.getDay() === 6}"
1205
+ data-calendar-day-sunday="${t.date.getDay() === 0}"
1206
+ data-calendar-day-holiday="${c}"
1207
+ data-calendar-day-label="${s}"
1208
+ >
1209
+ ${this.calendarDayContent ? "" : s}
1210
+ </div>
1211
+ `;
1212
+ }) : u.map((t, r) => {
1213
+ let i = this.option.calendar.pxPerDay;
1214
+ r + 1 > this.totalDays && (i = (this.totalDays - r) * this.option.calendar.pxPerDay);
1215
+ let a = L(t, e, this.option.calendar.isHoliday), o = String(t.getDate()), s = this.option.calendar.isHoliday ? this.option.calendar.isHoliday(t) : !1;
1216
+ return n`
1217
+ <div
1218
+ class="day-cell"
1219
+ style="width: ${i}px; ${a ? `background-color: ${a};` : ""}"
1220
+ data-calendar-day="${t.toISOString()}"
1221
+ data-calendar-day-width="${i}"
1222
+ data-calendar-day-saturday="${t.getDay() === 6}"
1223
+ data-calendar-day-sunday="${t.getDay() === 0}"
1224
+ data-calendar-day-holiday="${s}"
1225
+ data-calendar-day-label="${o}"
1226
+ >
1227
+ ${this.calendarDayContent ? "" : o}
1228
+ </div>
1229
+ `;
1230
+ })}
1231
+ </div>`}
1232
+ ${this.option.calendar.showTime ? n`
1233
+ <div class="hours-container" style="${S}">
1234
+ ${C.map((e) => Array.from({ length: e.hEnd - e.hStart }, (t, n) => e.hStart + n).map((t) => n` <div
1235
+ class="hour-cell"
1236
+ style="width: ${m}px;"
1237
+ data-calendar-hour="${t}"
1238
+ data-calendar-hour-width="${m}"
1239
+ data-calendar-hour-date="${e.date.toISOString()}"
1240
+ >${this.calendarHourContent ? "" : t}</div> `))}
1241
+ </div>
1242
+ ` : ""}
1243
+ ${(() => {
1244
+ let t = this.option.calendar.showMonthsRow || this.option.calendar.showDays === !1 && !this.option.calendar.showWeeks, r = this.getDateX(this.option.calendar.start), i = this.getDateX(this.option.calendar.end), a = d.map((i) => {
1245
+ if (!i.start) return "";
1246
+ let a = this.getDateX(i.start);
1247
+ if (a <= r) return "";
1248
+ let o = i.month === 0, s, c = 1;
1249
+ return o ? (s = e.yearGridLine || e.monthGridLine || e.border, c = 3) : (s = t ? e.border : e.monthGridLine || e.border, c = 1), n`<div
1250
+ style="position: absolute; top: 0; bottom: 0; left: ${a - 1}px; width: 1px; background-color: ${s}; pointer-events: none; z-index: ${c};"
1251
+ ></div>`;
1252
+ }), o = d[d.length - 1];
1253
+ if (o && i > r) {
1254
+ let r = o.month === 11, s = r ? e.yearGridLine || e.monthGridLine || e.border : t ? e.border : e.monthGridLine || e.border, c = r ? 3 : 1;
1255
+ a.push(n`<div
1256
+ style="position: absolute; top: 0; bottom: 0; left: ${i - 1}px; width: 1px; background-color: ${s}; pointer-events: none; z-index: ${c};"
1257
+ ></div>`);
1258
+ }
1259
+ return a;
1260
+ })()}
1261
+ ${this.option.calendar.showCurrentTime && this.option.calendar.showCurrentTimeBadge === !0 && this.currentTime >= this.option.calendar.start && this.currentTime <= this.option.calendar.end ? n`
1262
+ <div
1263
+ class="current-time-badge"
1264
+ style="
1265
+ left: ${this.getDateX(this.currentTime)}px;
1266
+ background-color: ${e.currentTimeLine};
1267
+ color: ${e.currentTimeLineText};
1268
+ "
1269
+ >
1270
+ ${this.formatTime(this.currentTime)}
1271
+ </div>
1272
+ ` : ""}
1273
+ ${(this.option.calendar.milestones ?? []).map((e) => n`
1274
+ <div
1275
+ class="milestone-connector"
1276
+ style="
1277
+ left: ${this.getDateX(e.start) + 1}px;
1278
+ width: ${e.width ?? 2}px;
1279
+ background-color: ${e.color};
1280
+ opacity: ${this.hoveredMilestoneId === e.id ? 1 : .5};
1281
+ "
1282
+ @mouseenter="${() => {
1283
+ this.dispatchEvent(new CustomEvent("milestone-hover-change", {
1284
+ detail: { milestoneId: e.id },
1285
+ bubbles: !0,
1286
+ composed: !0
1287
+ }));
1288
+ }}"
1289
+ @mouseleave="${() => {
1290
+ this.dispatchEvent(new CustomEvent("milestone-hover-change", {
1291
+ detail: { milestoneId: null },
1292
+ bubbles: !0,
1293
+ composed: !0
1294
+ }));
1295
+ }}"
1296
+ ></div>
1297
+ <div
1298
+ class="milestone-badge"
1299
+ style="
1300
+ left: ${this.getDateX(e.start)}px;
1301
+ background-color: ${e.color};
1302
+ opacity: ${this.hoveredMilestoneId === e.id ? 1 : .5};
1303
+ "
1304
+ @mouseenter="${() => {
1305
+ this.dispatchEvent(new CustomEvent("milestone-hover-change", {
1306
+ detail: { milestoneId: e.id },
1307
+ bubbles: !0,
1308
+ composed: !0
1309
+ }));
1310
+ }}"
1311
+ @mouseleave="${() => {
1312
+ this.dispatchEvent(new CustomEvent("milestone-hover-change", {
1313
+ detail: { milestoneId: null },
1314
+ bubbles: !0,
1315
+ composed: !0
1316
+ }));
1317
+ }}"
1318
+ >
1319
+ ${e.name}
1320
+ </div>
1321
+ `)}
1322
+ </div>
1323
+ `;
1324
+ }
1325
+ };
1326
+ V([s({ type: Object })], U.prototype, "option", void 0), V([s({ type: String })], U.prototype, "theme", void 0), V([s({ type: Object })], U.prototype, "currentTime", void 0), V([s({ type: String })], U.prototype, "hoveredMilestoneId", void 0), V([s({ attribute: !1 })], U.prototype, "cornerContent", void 0), V([s({ attribute: !1 })], U.prototype, "calendarMonthContent", void 0), V([s({ attribute: !1 })], U.prototype, "calendarDayContent", void 0), V([s({ attribute: !1 })], U.prototype, "calendarWeekContent", void 0), V([s({ attribute: !1 })], U.prototype, "calendarHourContent", void 0), U = V([o("gantt-calendar")], U);
1327
+ //#endregion
1328
+ //#region src/components/gantt-row-background.ts
1329
+ var W = class extends e {
1330
+ constructor(...e) {
1331
+ super(...e), this.theme = "light", this.rowId = "", this._cachedCells = null, this._cachedCellsStartTime = 0, this._cachedCellsEndTime = 0, this._cachedCellsPxPerDay = 0, this._cachedCellsPxPerMonth = void 0, this._cachedCellsTheme = "";
1332
+ }
1333
+ get totalDays() {
1334
+ return R(this.option.calendar.start, this.option.calendar.end);
1335
+ }
1336
+ static {
1337
+ this.styles = t`
1338
+ :host {
1339
+ position: absolute;
1340
+ top: 0;
1341
+ left: 0;
1342
+ width: 100%;
1343
+ height: 100%;
1344
+ display: flex;
1345
+ z-index: 0;
1346
+ pointer-events: none;
1347
+ overflow: hidden;
1348
+ }
1349
+ .bg-cell {
1350
+ flex-shrink: 0;
1351
+ position: relative;
1352
+ overflow: hidden;
1353
+ }
1354
+ `;
1355
+ }
1356
+ render() {
1357
+ let e = I(this.theme, this.option.customTheme), t = this.option.calendar.start.getTime(), r = this.option.calendar.end.getTime(), i = this.option.calendar.pxPerDay ?? 50, a = this.option.calendar.pxPerMonth;
1358
+ (!this._cachedCells || t !== this._cachedCellsStartTime || r !== this._cachedCellsEndTime || i !== this._cachedCellsPxPerDay || a !== this._cachedCellsPxPerMonth || this.theme !== this._cachedCellsTheme) && (this._cachedCellsStartTime = t, this._cachedCellsEndTime = r, this._cachedCellsPxPerDay = i, this._cachedCellsPxPerMonth = a, this._cachedCellsTheme = this.theme, this._cachedCells = Array.from({ length: Math.ceil(this.totalDays) }, (e, t) => {
1359
+ let n = new Date(this.option.calendar.start);
1360
+ return n.setDate(n.getDate() + t), n;
1361
+ }).map((t) => {
1362
+ let n = L(t, e, this.option.calendar.isHoliday), r = new Date(t);
1363
+ r.setDate(t.getDate() + 1);
1364
+ let o = N(t, this.option.calendar.start, i, a);
1365
+ return {
1366
+ width: N(r, this.option.calendar.start, i, a) - o,
1367
+ color: n,
1368
+ date: t
1369
+ };
1370
+ }));
1371
+ let o = this.option.customRendering?.chartBackground;
1372
+ return o ? n`
1373
+ ${this._cachedCells.map(({ width: e, color: t, date: r }, i) => {
1374
+ let a = r.getDay(), s = this.option.calendar.isHoliday ? this.option.calendar.isHoliday(r) : !1, c = o({
1375
+ date: r,
1376
+ width: e,
1377
+ height: this.clientHeight || 0,
1378
+ rowId: this.rowId,
1379
+ isSaturday: a === 6,
1380
+ isSunday: a === 0,
1381
+ isHoliday: s,
1382
+ defaultColor: t,
1383
+ index: i
1384
+ });
1385
+ return typeof c == "string" ? n`<div
1386
+ class="bg-cell"
1387
+ style="width: ${e}px; background-color: ${t};"
1388
+ ><div style="position: absolute; inset: 0;">${n`${c}`}</div></div>` : n`<div
1389
+ class="bg-cell"
1390
+ style="width: ${e}px; background-color: ${t};"
1391
+ ><div style="position: absolute; inset: 0;">${c}</div></div>`;
1392
+ })}
1393
+ ` : n`
1394
+ ${this._cachedCells.map(({ width: e, color: t }) => n`<div
1395
+ style="width: ${e}px; background-color: ${t}; flex-shrink: 0;"
1396
+ ></div>`)}
1397
+ `;
1398
+ }
1399
+ };
1400
+ V([s({ type: Object })], W.prototype, "option", void 0), V([s({ type: String })], W.prototype, "theme", void 0), V([s({ type: String })], W.prototype, "rowId", void 0), W = V([o("gantt-row-background")], W);
1401
+ //#endregion
1402
+ //#region src/components/gantt-row.ts
1403
+ var G = class extends e {
1404
+ constructor(...e) {
1405
+ super(...e), this.isDragTarget = !1, this.draggingTask = null, this.draggingTaskIds = [], this.multiDragDx = 0, this.externalDragTask = null, this.theme = "light", this.isSelected = !1, this.dropPosition = null, this.selectedTaskIds = [], this.focusedTaskId = null, this.isExporting = !1, this._cachedMonthGridLines = null, this._cachedMonthGridStartTime = 0, this._cachedMonthGridEndTime = 0, this._cachedMonthGridPxPerDay = 0, this._cachedMonthGridPxPerMonth = 0;
1406
+ }
1407
+ getDateX(e) {
1408
+ return N(e, this.option.calendar.start, this.option.calendar.pxPerDay, this.option.calendar.pxPerMonth);
1409
+ }
1410
+ getMarkerPath(e, t) {
1411
+ let n = t / 2;
1412
+ switch (e) {
1413
+ case "triangle-up": return `M 0 ${t} L ${n} 0 L ${t} ${t} Z`;
1414
+ case "triangle-down": return `M 0 0 L ${t} 0 L ${n} ${t} Z`;
1415
+ case "triangle-left": return `M ${t} 0 L 0 ${n} L ${t} ${t} Z`;
1416
+ case "triangle-right": return `M 0 0 L ${t} ${n} L 0 ${t} Z`;
1417
+ case "diamond": return `M ${n} 0 L ${t} ${n} L ${n} ${t} L 0 ${n} Z`;
1418
+ case "square": return `M 0 0 L ${t} 0 L ${t} ${t} L 0 ${t} Z`;
1419
+ default: return `M 0 ${t} L ${n} 0 L ${t} ${t} Z`;
1420
+ }
1421
+ }
1422
+ static {
1423
+ this.styles = t`
1424
+ :host {
1425
+ display: block;
1426
+ width: fit-content;
1427
+ min-width: 100%;
1428
+ box-sizing: border-box;
1429
+ background-color: transparent;
1430
+ }
1431
+ .row-container {
1432
+ display: flex;
1433
+ height: 100%;
1434
+ box-sizing: border-box;
1435
+ background: inherit;
1436
+ position: relative;
1437
+ }
1438
+ .row-container.drop-top::before {
1439
+ content: '';
1440
+ position: absolute;
1441
+ top: 0;
1442
+ left: 0;
1443
+ right: 0;
1444
+ height: 2px;
1445
+ background-color: #3b82f6;
1446
+ z-index: 110;
1447
+ pointer-events: none;
1448
+ }
1449
+ .row-container.drop-bottom::after {
1450
+ content: '';
1451
+ position: absolute;
1452
+ bottom: 0;
1453
+ left: 0;
1454
+ right: 0;
1455
+ height: 2px;
1456
+ background-color: #3b82f6;
1457
+ z-index: 110;
1458
+ pointer-events: none;
1459
+ }
1460
+ .row-header {
1461
+ font-size: 13px;
1462
+ display: flex;
1463
+ align-items: center;
1464
+ gap: 0;
1465
+ flex-shrink: 0;
1466
+ box-sizing: border-box;
1467
+ position: sticky;
1468
+ left: 0;
1469
+ z-index: 100;
1470
+ }
1471
+ .row-header-content {
1472
+ flex-grow: 1;
1473
+ padding: 6px 12px;
1474
+ white-space: nowrap;
1475
+ overflow: hidden;
1476
+ text-overflow: ellipsis;
1477
+ }
1478
+ :host([isexporting]) .row-header-content,
1479
+ :host([isexporting]) .row-header-content * {
1480
+ text-overflow: clip !important;
1481
+ }
1482
+ .bars-container {
1483
+ flex: none;
1484
+ position: relative;
1485
+ }
1486
+ .grid-background {
1487
+ position: absolute;
1488
+ top: 0;
1489
+ left: 0;
1490
+ width: 100%;
1491
+ height: 100%;
1492
+ pointer-events: none;
1493
+ }
1494
+ `;
1495
+ }
1496
+ handleDragStart(e) {
1497
+ if (this.isSelected || this.dispatchEvent(new CustomEvent("row-clicked", {
1498
+ detail: {
1499
+ rowId: this.row.id,
1500
+ event: e
1501
+ },
1502
+ bubbles: !0,
1503
+ composed: !0
1504
+ })), e.dataTransfer) {
1505
+ e.dataTransfer.setData("text/plain", this.row.id), e.dataTransfer.effectAllowed = "move";
1506
+ let t = I(this.theme, this.option.customTheme), n = document.createElement("div");
1507
+ n.style.position = "absolute", n.style.top = "-1000px", n.style.left = "-1000px", n.style.display = "flex", n.style.flexDirection = "column", n.style.zIndex = "9999", n.style.width = "fit-content", n.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)", n.style.border = `1px solid ${t.border}`, n.style.borderRadius = "4px", n.style.overflow = "hidden";
1508
+ let r = [];
1509
+ if (this.isSelected) {
1510
+ let e = this.getRootNode(), t = Array.from(e.querySelectorAll("gantt-row[isselected]"));
1511
+ r = t.length > 0 ? t : [this];
1512
+ } else r = [this];
1513
+ let i = r.slice(0, 10);
1514
+ if (i.forEach((e, r) => {
1515
+ let a = e.shadowRoot?.querySelector(".row-header");
1516
+ if (a) {
1517
+ let o = a.cloneNode(!0), s = window.getComputedStyle(a);
1518
+ o.style.width = s.width, o.style.minWidth = s.minWidth, o.style.height = `${e.offsetHeight}px`, o.style.boxSizing = s.boxSizing, o.style.background = s.backgroundColor, o.style.color = s.color, o.style.fontSize = s.fontSize, o.style.display = s.display, o.style.alignItems = s.alignItems, o.style.padding = s.padding, o.style.border = "none", o.style.borderBottom = r < i.length - 1 ? `1px solid ${t.border}` : "none", o.style.cursor = "grabbing", n.appendChild(o);
1519
+ }
1520
+ }), r.length > 10) {
1521
+ let e = document.createElement("div");
1522
+ e.style.padding = "4px 8px", e.style.background = t.bg, e.style.color = t.text, e.style.fontSize = "11px", e.style.textAlign = "center", e.textContent = `+ ${r.length - 10} more`, n.appendChild(e);
1523
+ }
1524
+ document.body.appendChild(n), e.dataTransfer.setDragImage(n, 0, 0), setTimeout(() => {
1525
+ document.body.removeChild(n);
1526
+ }, 0);
1527
+ }
1528
+ }
1529
+ handleHeaderClick(e) {
1530
+ this.dispatchEvent(new CustomEvent("row-clicked", {
1531
+ detail: {
1532
+ rowId: this.row.id,
1533
+ event: e
1534
+ },
1535
+ bubbles: !0,
1536
+ composed: !0
1537
+ })), e.stopPropagation();
1538
+ }
1539
+ handleHeaderContextMenu(e) {
1540
+ e.preventDefault(), this.dispatchEvent(new CustomEvent("row-header-contextmenu", {
1541
+ detail: {
1542
+ rowId: this.row.id,
1543
+ row: this.row,
1544
+ event: e,
1545
+ target: e.currentTarget
1546
+ },
1547
+ bubbles: !0,
1548
+ composed: !0
1549
+ }));
1550
+ }
1551
+ handleHeaderDblClick(e) {
1552
+ this.dispatchEvent(new CustomEvent("row-header-dblclick", {
1553
+ detail: {
1554
+ rowId: this.row.id,
1555
+ row: this.row,
1556
+ event: e,
1557
+ target: e.currentTarget
1558
+ },
1559
+ bubbles: !0,
1560
+ composed: !0
1561
+ }));
1562
+ }
1563
+ updated(e) {
1564
+ if (super.updated(e), !(e.has("row") || e.has("option") || e.has("isSelected") || e.has("theme"))) return;
1565
+ let t = this.shadowRoot?.querySelector(".row-header-content");
1566
+ t && r(this.option.customRendering?.rowHeaderContent ? this.option.customRendering.rowHeaderContent(this.row) : this.row.name, t);
1567
+ }
1568
+ render() {
1569
+ let e = I(this.theme, this.option.customTheme), t = [...this.row.tasks];
1570
+ if (this.externalDragTask) {
1571
+ let e = {
1572
+ ...this.externalDragTask.task,
1573
+ start: this.externalDragTask.currentStart,
1574
+ end: this.externalDragTask.currentEnd,
1575
+ style: `${this.externalDragTask.task.style || ""}; opacity: 0.6; pointer-events: none;`
1576
+ };
1577
+ t = [...t, e];
1578
+ }
1579
+ let r, i, a = this.row.tasks.find((e) => this.draggingTask && e.id === this.draggingTask.id);
1580
+ if (this.draggingTask?.mode === "copy" && a) {
1581
+ let e = t.filter((e) => e.id !== this.draggingTask.id);
1582
+ e.push({
1583
+ ...a,
1584
+ id: `${a.id}-static`,
1585
+ movable: "none",
1586
+ resizable: !1,
1587
+ style: `${a.style || ""}; opacity: 0.5;`
1588
+ });
1589
+ let n = F(e);
1590
+ r = n.tasksWithLanes, i = n.laneCount;
1591
+ let o = r.find((e) => e.id === `${a.id}-static`);
1592
+ o && r.push({
1593
+ ...a,
1594
+ lane: o.lane
1595
+ });
1596
+ } else {
1597
+ let e = F(t);
1598
+ r = e.tasksWithLanes, i = e.laneCount;
1599
+ }
1600
+ let o = this.option.bar?.height ?? 28, s = this.option.bar?.margin ?? 4, c = i * (o + s) + s;
1601
+ this.style.height = `${c}px`;
1602
+ let l = "", d = null, f = this.option.calendar.start.getTime(), p = this.option.calendar.end.getTime(), m = this.option.calendar.pxPerDay, h = this.option.calendar.pxPerMonth ?? 0;
1603
+ if (!this._cachedMonthGridLines || f !== this._cachedMonthGridStartTime || p !== this._cachedMonthGridEndTime || m !== this._cachedMonthGridPxPerDay || h !== this._cachedMonthGridPxPerMonth) {
1604
+ this._cachedMonthGridStartTime = f, this._cachedMonthGridEndTime = p, this._cachedMonthGridPxPerDay = m, this._cachedMonthGridPxPerMonth = h;
1605
+ let e = new Date(this.option.calendar.start), t = this.getDateX(e), n = this.option.calendar.end, r = new Date(n.getFullYear(), n.getMonth() + 1, 1), i = this.option.calendar.pxPerMonth === void 0 ? this.getDateX(n) : this.getDateX(r), a = [], o = new Date(e);
1606
+ for (o.setDate(1), o.setHours(0, 0, 0, 0); o <= r;) {
1607
+ let e = this.getDateX(o);
1608
+ if (e > t && e <= i) {
1609
+ let t = o.getMonth() === 0;
1610
+ a.push({
1611
+ left: e,
1612
+ isYearBoundary: t
1613
+ });
1614
+ }
1615
+ o.setMonth(o.getMonth() + 1);
1616
+ }
1617
+ this._cachedMonthGridLines = a;
1618
+ }
1619
+ if (d = this._cachedMonthGridLines, this.option.calendar.showMonthsRow) l = "";
1620
+ else if (this.option.calendar.showTime) {
1621
+ let t = this.option.calendar.pxPerDay / 24, n = this.option.snapDuration ?? 60, r = this.option.calendar.pxPerDay / 1440 * n, i = this.option.calendar.pxPerDay, a = this.option.customTheme?.showTimeDateLine ?? e.monthGridLine ?? e.gridLine, o = this.option.calendar.start, s = (o.getHours() * 60 * 60 * 1e3 + o.getMinutes() * 60 * 1e3 + o.getSeconds() * 1e3) / (1440 * 60 * 1e3) * i, c = s % t, u = s % r, d = s === 0 ? "0px 0" : `${-s}px 0`, f = c === 0 ? "0px 0" : `${-c}px 0`, p = u === 0 ? "0px 0" : `${-u}px 0`, m = [
1622
+ `linear-gradient(90deg, transparent ${i - 1}px, ${a} ${i - 1}px)`,
1623
+ `linear-gradient(90deg, transparent ${t - 1}px, ${e.gridLine} ${t - 1}px)`,
1624
+ `linear-gradient(90deg, transparent ${r - 1}px, ${e.subGridLine} ${r - 1}px)`
1625
+ ], h = [
1626
+ `${i}px 100%`,
1627
+ `${t}px 100%`,
1628
+ `${r}px 100%`
1629
+ ], g = [
1630
+ d,
1631
+ f,
1632
+ p
1633
+ ];
1634
+ l = `
1635
+ background-image: ${m.join(", ")};
1636
+ background-size: ${h.join(", ")};
1637
+ background-position: ${g.join(", ")};
1638
+ `;
1639
+ } else {
1640
+ let t = this.option.calendar.pxPerDay, n = this.option.calendar.start, r = (n.getHours() * 60 * 60 * 1e3 + n.getMinutes() * 60 * 1e3 + n.getSeconds() * 1e3) / (1440 * 60 * 1e3) * t, i = r === 0 ? "0px 0" : `${-r}px 0`;
1641
+ l = `
1642
+ background-image: linear-gradient(90deg, transparent ${t - 1}px, ${e.gridLine} ${t - 1}px);
1643
+ background-size: ${t}px 100%;
1644
+ background-position: ${i};
1645
+ `;
1646
+ }
1647
+ let g = this.option.enableRowReordering && !this.option.readOnly, _ = this.row.visible === !1, v = this.isSelected ? e.rowSelectedHeader : _ ? e.rowHiddenBg : e.rowHeaderBg, y = v.includes("gradient") ? `background: ${v};` : `background-color: ${v};`;
1648
+ return n`
1649
+ <style>
1650
+ :host {
1651
+ color: ${e.text};
1652
+ background-color: ${_ ? e.rowHiddenBg : "transparent"};
1653
+ }
1654
+
1655
+ .row-header {
1656
+ cursor: ${g ? "grab" : "pointer"};
1657
+ border-right: 1px solid ${e.border};
1658
+ border-bottom: 1px solid ${e.border};
1659
+ box-sizing: border-box;
1660
+ }
1661
+ .row-header:active {
1662
+ cursor: ${g ? "grabbing" : "pointer"};
1663
+ }
1664
+ .bars-container {
1665
+ border-bottom: 1px solid ${e.border};
1666
+ box-sizing: border-box;
1667
+ }
1668
+ .hidden-row-overlay {
1669
+ position: absolute;
1670
+ top: 0;
1671
+ left: 0;
1672
+ width: 100%;
1673
+ height: 100%;
1674
+ z-index: 5;
1675
+ pointer-events: none;
1676
+ opacity: 0.5;
1677
+ }
1678
+ .selected-row-overlay {
1679
+ position: absolute;
1680
+ top: 0;
1681
+ left: 0;
1682
+ width: 100%;
1683
+ height: 100%;
1684
+ z-index: 1;
1685
+ pointer-events: none;
1686
+ background-color: ${e.rowSelected};
1687
+ opacity: 0.5;
1688
+ }
1689
+ </style>
1690
+ <div class="row-container ${this.dropPosition ? `drop-${this.dropPosition}` : ""}">
1691
+ <div
1692
+ class="row-header"
1693
+ style="width: ${this.option.rowHeader?.width ?? 150}px; ${y}"
1694
+ draggable="${g ? "true" : "false"}"
1695
+ @dragstart="${g ? this.handleDragStart : void 0}"
1696
+ @click="${this.handleHeaderClick}"
1697
+ @dblclick="${this.handleHeaderDblClick}"
1698
+ @contextmenu="${this.handleHeaderContextMenu}"
1699
+ >
1700
+ <div
1701
+ class="row-header-content"
1702
+ style="${this.option.customRendering?.rowHeaderContent ? "padding: 0; height: 100%;" : ""}"
1703
+ ></div>
1704
+ </div>
1705
+ <div class="bars-container" style="width: ${(() => {
1706
+ if (this.option.calendar.pxPerMonth !== void 0) {
1707
+ let e = this.option.calendar.end;
1708
+ return this.getDateX(new Date(e.getFullYear(), e.getMonth() + 1, 1));
1709
+ }
1710
+ return this.getDateX(this.option.calendar.end);
1711
+ })()}px">
1712
+ ${this.option.calendar.showRowBackground !== !1 && !this.option.calendar.showMonthsRow ? n`<gantt-row-background .option="${this.option}" .theme="${this.theme}" .rowId="${this.row.id}" /> ` : ""}
1713
+ ${this.isSelected ? n`<div class="selected-row-overlay"></div>` : ""}
1714
+ ${l ? n`<div class="grid-background" style="${l}"></div>` : ""}
1715
+ ${d ? d.map((t) => {
1716
+ let r;
1717
+ return r = t.isYearBoundary ? e.yearGridLine || e.monthGridLine || e.gridLine : this.option.calendar.showMonthsRow || this.option.calendar.showDays === !1 && !this.option.calendar.showWeeks ? e.gridLine : e.monthGridLine || e.gridLine, n`<div style="position: absolute; top: 0; left: ${t.left - 1}px; width: 1px; height: 100%; background-color: ${r}; pointer-events: none; z-index: 1;"></div>`;
1718
+ }) : ""}
1719
+ ${_ ? n`<div class="hidden-row-overlay" style="background: ${e.rowHiddenBg};"></div>` : ""}
1720
+ ${u(r, (e) => e.id, (e) => {
1721
+ let t = this.draggingTask?.id === e.id, r = !t && this.draggingTaskIds.length >= 2 && this.draggingTaskIds.includes(e.id), i = t ? {
1722
+ ...e,
1723
+ start: this.draggingTask.start,
1724
+ end: this.draggingTask.end
1725
+ } : e, a = this.selectedTaskIds.includes(e.id), o = r ? this.multiDragDx : 0, s = t && this.draggingTaskIds.length >= 2;
1726
+ return n`
1727
+ <gantt-bar
1728
+ .task="${i}"
1729
+ .option="${this.option}"
1730
+ .lane="${e.lane}"
1731
+ .selected="${a}"
1732
+ .focused="${this.focusedTaskId === e.id}"
1733
+ .multiDragDx="${o}"
1734
+ .multiDragActive="${s}"
1735
+ .isExporting="${this.isExporting}"
1736
+ />
1737
+ `;
1738
+ })}
1739
+ ${(this.row.markers ?? []).map((e) => {
1740
+ let t = Math.min(o, 12), r = this.getDateX(e.date), i = e.color ?? "#ef4444", a = e.anchor === "center", s = a ? c / 2 - t : (c - t) / 2, l = e.anchor === "start" ? r : e.anchor === "end" ? r - t : r - t / 2, u = e.anchor === "end";
1741
+ return n`
1742
+ <div
1743
+ class="marker-wrapper"
1744
+ style="
1745
+ position: absolute;
1746
+ left: ${l}px;
1747
+ top: ${s}px;
1748
+ z-index: 2;
1749
+ display: flex;
1750
+ ${a ? `flex-direction: column; align-items: center; width: ${t}px; overflow: visible;` : `align-items: center; ${u ? "flex-direction: row-reverse;" : ""}`}
1751
+ pointer-events: auto;
1752
+ cursor: default;
1753
+ white-space: nowrap;
1754
+ "
1755
+ title="${e.name ?? ""}"
1756
+ >
1757
+ <svg
1758
+ class="marker-icon"
1759
+ width="${t}"
1760
+ height="${t}"
1761
+ viewBox="0 0 ${t} ${t}"
1762
+ style="
1763
+ flex-shrink: 0;
1764
+ filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3));
1765
+ ${e.style ?? ""}
1766
+ "
1767
+ >
1768
+ <path d="${this.getMarkerPath(e.type, t)}" fill="${i}" />
1769
+ </svg>
1770
+ ${e.name ? n`<span style="
1771
+ font-size: 10px;
1772
+ color: ${i};
1773
+ line-height: 1;
1774
+ ${a ? "padding: 1px 0 0 0;" : "padding: 0 2px;"}
1775
+ ">${e.name}</span>` : ""}
1776
+ </div>
1777
+ `;
1778
+ })}
1779
+ </div>
1780
+ </div>
1781
+ `;
1782
+ }
1783
+ };
1784
+ V([s({ type: Object })], G.prototype, "row", void 0), V([s({ type: Object })], G.prototype, "option", void 0), V([s({ type: Boolean })], G.prototype, "isDragTarget", void 0), V([s({ type: Object })], G.prototype, "draggingTask", void 0), V([s({ type: Array })], G.prototype, "draggingTaskIds", void 0), V([s({ type: Number })], G.prototype, "multiDragDx", void 0), V([s({ type: Object })], G.prototype, "externalDragTask", void 0), V([s({ type: String })], G.prototype, "theme", void 0), V([s({
1785
+ type: Boolean,
1786
+ reflect: !0
1787
+ })], G.prototype, "isSelected", void 0), V([s({ type: String })], G.prototype, "dropPosition", void 0), V([s({ type: Array })], G.prototype, "selectedTaskIds", void 0), V([s({ type: String })], G.prototype, "focusedTaskId", void 0), V([s({
1788
+ type: Boolean,
1789
+ reflect: !0
1790
+ })], G.prototype, "isExporting", void 0), G = V([o("gantt-row")], G);
1791
+ //#endregion
1792
+ //#region src/components/gantt-chart-dependency-path.ts
1793
+ function K(e, t, n, r, i, a, o, s) {
1794
+ let c = (n) => {
1795
+ if (Math.abs(t - r) < 1) return `M ${e} ${t} L ${n} ${r}`;
1796
+ if (e < n) {
1797
+ let i = (e + n) / 2, a = r > t ? 1 : -1, o = Math.min(s, i - e, n - i, Math.abs(r - t) / 2);
1798
+ return [
1799
+ `M ${e} ${t}`,
1800
+ `L ${i - o} ${t}`,
1801
+ `Q ${i} ${t} ${i} ${t + a * o}`,
1802
+ `L ${i} ${r - a * o}`,
1803
+ `Q ${i} ${r} ${i + o} ${r}`,
1804
+ `L ${n} ${r}`
1805
+ ].join(" ");
1806
+ } else {
1807
+ let i = Math.max(12, s + 4), c = e + i, l = n - i, u = (t + r) / 2, d = Math.abs(t - r) < a ? u + a + o : u, f = d - t, p = r - d, m = f >= 0 ? 1 : -1, h = p >= 0 ? 1 : -1, g = l - c, _ = g >= 0 ? 1 : -1, v = Math.min(s, i, Math.abs(f) / 2), y = Math.min(s, Math.abs(f) / 2, Math.abs(g) / 2), b = Math.min(s, Math.abs(g) / 2, Math.abs(p) / 2), x = Math.min(s, Math.abs(p) / 2, i);
1808
+ return [
1809
+ `M ${e} ${t}`,
1810
+ `L ${c - v} ${t}`,
1811
+ `Q ${c} ${t} ${c} ${t + m * v}`,
1812
+ `L ${c} ${d - m * y}`,
1813
+ `Q ${c} ${d} ${c + _ * y} ${d}`,
1814
+ `L ${l - _ * b} ${d}`,
1815
+ `Q ${l} ${d} ${l} ${d + h * b}`,
1816
+ `L ${l} ${r - h * x}`,
1817
+ `Q ${l} ${r} ${l + x} ${r}`,
1818
+ `L ${n} ${r}`
1819
+ ].join(" ");
1820
+ }
1821
+ };
1822
+ return {
1823
+ pathD: c(i),
1824
+ hitPathD: c(n)
1825
+ };
1826
+ }
1827
+ //#endregion
1828
+ //#region src/components/gantt-chart-styles.ts
1829
+ var q = t`
1830
+ :host {
1831
+ display: block;
1832
+ width: 100%;
1833
+ height: 100%;
1834
+ box-sizing: border-box;
1835
+ position: relative;
1836
+ }
1837
+ :host(:focus-visible) {
1838
+ outline: 2px solid #3b82f6;
1839
+ outline-offset: -2px;
1840
+ }
1841
+ .scroll-container {
1842
+ width: 100%;
1843
+ height: 100%;
1844
+ overflow-x: auto;
1845
+ overflow-y: auto;
1846
+ position: relative;
1847
+ overflow-anchor: none;
1848
+ }
1849
+ .dependency-lines {
1850
+ position: absolute;
1851
+ top: 0;
1852
+ left: 0;
1853
+ pointer-events: none;
1854
+ z-index: 10;
1855
+ }
1856
+ .tooltip {
1857
+ position: fixed;
1858
+ transform: translate(-50%, -100%);
1859
+ padding: 4px 8px;
1860
+ border-radius: 4px;
1861
+ font-size: 11px;
1862
+ white-space: nowrap;
1863
+ pointer-events: none;
1864
+ z-index: 1000;
1865
+ margin-top: -6px;
1866
+ text-align: left;
1867
+ line-height: 1.4;
1868
+ opacity: 0;
1869
+ transition: opacity 0.2s ease;
1870
+ }
1871
+ .tooltip.visible {
1872
+ opacity: 1;
1873
+ }
1874
+ .tooltip-row {
1875
+ display: block;
1876
+ }
1877
+ .tooltip::after {
1878
+ content: '';
1879
+ position: absolute;
1880
+ top: 100%;
1881
+ left: 50%;
1882
+ margin-left: -4px;
1883
+ border-width: 4px;
1884
+ border-style: solid;
1885
+ }
1886
+ .drag-info-overlay {
1887
+ position: fixed;
1888
+ top: 0;
1889
+ left: 50%;
1890
+ transform: translateX(-50%);
1891
+ padding: 10px 20px;
1892
+ border-radius: 8px;
1893
+ font-size: 14px;
1894
+ pointer-events: none;
1895
+ z-index: 2000;
1896
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1897
+ display: flex;
1898
+ flex-direction: column;
1899
+ align-items: center;
1900
+ gap: 4px;
1901
+ text-align: center;
1902
+ opacity: 0;
1903
+ transition: opacity 0.2s ease;
1904
+ }
1905
+ .drag-info-overlay.visible {
1906
+ opacity: 1;
1907
+ }
1908
+ .drag-info-sub {
1909
+ font-size: 12px;
1910
+ }
1911
+ .dependency-line {
1912
+ stroke-width: 2;
1913
+ fill: none;
1914
+ pointer-events: none;
1915
+ }
1916
+ .dependency-arrow-line {
1917
+ stroke-width: 0;
1918
+ }
1919
+ .dependency-hit-area {
1920
+ stroke-width: 16;
1921
+ stroke: transparent;
1922
+ fill: none;
1923
+ pointer-events: stroke;
1924
+ cursor: pointer;
1925
+ }
1926
+ .dependency-group:hover .dependency-line {
1927
+ stroke-width: 3;
1928
+ filter: drop-shadow(0 0 3px currentColor);
1929
+ }
1930
+ .dependency-group:hover .dependency-arrow-line {
1931
+ stroke-width: 0;
1932
+ }
1933
+ .dependency-group:hover .dependency-hit-area ~ .dependency-line {
1934
+ opacity: 1;
1935
+ }
1936
+ .current-time-line {
1937
+ position: absolute;
1938
+ width: 2px;
1939
+ z-index: 60;
1940
+ pointer-events: none;
1941
+ }
1942
+ .current-time-dot {
1943
+ position: absolute;
1944
+ width: 6px;
1945
+ height: 6px;
1946
+ border-radius: 50%;
1947
+ z-index: 80;
1948
+ pointer-events: none;
1949
+ transform: translate(-50%, -50%);
1950
+ }
1951
+ .milestone-line {
1952
+ position: absolute;
1953
+ z-index: 59;
1954
+ pointer-events: auto;
1955
+ transition: opacity 0.2s ease;
1956
+ cursor: default;
1957
+ }
1958
+ .cursor-line {
1959
+ position: absolute;
1960
+ width: 2px;
1961
+ top: 0;
1962
+ pointer-events: none;
1963
+ z-index: 58;
1964
+ }
1965
+ `;
1966
+ function J(e, t) {
1967
+ let n = I(e, t);
1968
+ return `
1969
+ :host {
1970
+ background: ${n.bg};
1971
+ border: 1px solid ${n.border};
1972
+ border-radius: 8px;
1973
+ overflow: hidden;
1974
+ color: ${n.text};
1975
+ }
1976
+ .tooltip {
1977
+ background-color: ${n.tooltipBg};
1978
+ color: ${n.tooltipText};
1979
+ }
1980
+ .tooltip::after {
1981
+ border-color: ${n.tooltipBg} transparent transparent transparent;
1982
+ }
1983
+ .drag-info-overlay {
1984
+ background: ${n.dragOverlayBg};
1985
+ color: ${n.dragOverlayText};
1986
+ }
1987
+ .drag-info-sub {
1988
+ color: ${n.dragOverlaySubText};
1989
+ }
1990
+ .dependency-line {
1991
+ stroke: ${n.dependencyLine};
1992
+ }
1993
+ .connector-preview-line {
1994
+ stroke: ${n.dependencyLine};
1995
+ stroke-width: 2;
1996
+ stroke-dasharray: 6 3;
1997
+ fill: none;
1998
+ opacity: 0.7;
1999
+ }
2000
+ .header-resizer {
2001
+ width: 4px;
2002
+ cursor: col-resize;
2003
+ z-index: 510;
2004
+ background-color: transparent;
2005
+ transition: background-color 0.2s;
2006
+ }
2007
+ .header-resizer:hover,
2008
+ .header-resizer.resizing {
2009
+ background-color: ${n.border};
2010
+ }
2011
+ `;
2012
+ }
2013
+ //#endregion
2014
+ //#region src/components/gantt-chart-export.ts
2015
+ function Y(e, t) {
2016
+ let n = document.createElement("a");
2017
+ n.href = e, n.download = t, n.click();
2018
+ }
2019
+ async function X(e, t = "png", n = {}) {
2020
+ let { filename: r = "gantt-chart", download: i = !1, scale: a = 2, splitHeight: o } = n, s = e.shadowRoot?.querySelector(".scroll-container"), c = s ? s.scrollWidth : e.scrollWidth, l = s ? s.scrollHeight : e.scrollHeight;
2021
+ console.log("[export] splitHeight:", o, "scrollHeight:", l);
2022
+ let u = await p(e, {
2023
+ backgroundColor: "#ffffff",
2024
+ scale: a,
2025
+ width: c,
2026
+ height: l,
2027
+ windowWidth: c,
2028
+ windowHeight: l
2029
+ });
2030
+ if (o && l > o) {
2031
+ let t = 50, n = e.shadowRoot?.querySelector("gantt-calendar");
2032
+ n && n.offsetHeight > 0 ? t = n.offsetHeight : e.calendarHeight && (t = e.calendarHeight), console.log("[export] Splitting Canvas. calendarHeight:", t);
2033
+ let r = u.height / l, i = Math.floor(o * r), a = Math.floor(t * r), s = u.height, c = u.width, d = s - a, f = i - a;
2034
+ if (f > 0) {
2035
+ let e = Math.ceil(d / f), t = s + (e - 1) * a, n = document.createElement("canvas");
2036
+ n.width = c, n.height = t;
2037
+ let o = n.getContext("2d");
2038
+ if (o) {
2039
+ o.drawImage(u, 0, 0, c, i, 0, 0, c, i);
2040
+ let d = i, p = i;
2041
+ for (let t = 1; t < e; t++) {
2042
+ o.drawImage(u, 0, 0, c, a, 0, p, c, a), p += a;
2043
+ let e = s - d, t = Math.min(f, e);
2044
+ o.drawImage(u, 0, d, c, t, 0, p, c, t), d += t, p += t;
2045
+ }
2046
+ u = n, l = t / r, console.log("[export] Split complete. new scrollHeight:", l);
2047
+ } else console.warn("[export] Failed to get 2D context for new canvas. It might be too large.");
2048
+ }
2049
+ }
2050
+ if (t === "pdf") {
2051
+ let e = u.toDataURL("image/jpeg", .9), t = new m({
2052
+ orientation: c > l ? "l" : "p",
2053
+ unit: "px",
2054
+ format: [c, l],
2055
+ compress: !0
2056
+ });
2057
+ return t.addImage(e, "JPEG", 0, 0, c, l, void 0, "FAST"), i && t.save(`${r}.pdf`), t.output("blob");
2058
+ } else {
2059
+ let e = u.toDataURL("image/png");
2060
+ return i && Y(e, `${r}.png`), e;
2061
+ }
2062
+ }
2063
+ //#endregion
2064
+ //#region src/components/gantt-chart.ts
2065
+ var Z = class extends e {
2066
+ constructor(...e) {
2067
+ super(...e), this.rows = [], this.theme = "light", this.selectedRowIds = [], this.selectedTaskIds = [], this.externalDraggingTask = null, this.selectedRows = /* @__PURE__ */ new Set(), this.selectedTasks = /* @__PURE__ */ new Set(), this.lastClickedRowId = null, this.virtualScrollTop = 0, this.dragTargetRowIndex = null, this.draggingTask = null, this.draggingTaskIds = [], this.multiDragDx = 0, this.viewportHeight = 400, this.dragOverlayInfo = null, this.calendarHeight = 0, this.tooltip = null, this.dragOverRowId = null, this.dragOverPosition = null, this.currentTime = /* @__PURE__ */ new Date(), this.dragPreview = null, this.currentRowHeaderWidth = 150, this.isResizingHeader = !1, this.hoveredMilestoneId = null, this.cursorLineX = null, this.connectorDrag = null, this._systemThemeMediaQuery = null, this.isExporting = !1, this.focusedTaskId = null, this.focusedRowId = null, this._layoutCache = null, this.resizeObserver = null, this._cachedSelectedTaskIds = [], this._cachedSelectedTasksSize = -1, this._cachedCurrentOption = null, this._lastOptionRef = null, this._lastLabelWidth = -1, this.handleSystemThemeChange = (e) => {
2068
+ (this.option?.theme === "system" || this.option?.theme !== "light" && this.option?.theme !== "dark") && (this.theme = e.matches ? "dark" : "light");
2069
+ }, this.handleScroll = (e) => {
2070
+ let t = e.target;
2071
+ this.updateScrollTop(t.scrollTop), this.hoverTimer !== void 0 && window.clearTimeout(this.hoverTimer), this.tooltip &&= {
2072
+ ...this.tooltip,
2073
+ visible: !1
2074
+ };
2075
+ }, this.updateScrollTop = f((e) => {
2076
+ this.virtualScrollTop = e;
2077
+ }, 100), this.handleContainerMouseMove = (e) => {
2078
+ if (!this.option.calendar.showCursorLine) return;
2079
+ let t = this.shadowRoot?.querySelector(".scroll-container");
2080
+ if (!t) return;
2081
+ let n = t.getBoundingClientRect(), r = e.clientX - n.left + t.scrollLeft;
2082
+ if (r < this.currentRowHeaderWidth) {
2083
+ this.cursorLineX = null;
2084
+ return;
2085
+ }
2086
+ this.cursorLineX = r;
2087
+ }, this.handleContainerMouseLeave = () => {
2088
+ this.cursorLineX = null;
2089
+ }, this.handleKeyDown = (e) => {
2090
+ if (this.option.keyboard?.enabled === !1) return;
2091
+ let t = e.composedPath()[0];
2092
+ if (!(t !== this && t?.tagName && [
2093
+ "INPUT",
2094
+ "TEXTAREA",
2095
+ "SELECT"
2096
+ ].includes(t.tagName))) switch (e.key) {
2097
+ case "ArrowRight":
2098
+ e.shiftKey && !this.option.readOnly ? this.moveSelectedTasksByKeyboard(1) : this.moveFocusHorizontal(1), e.preventDefault();
2099
+ break;
2100
+ case "ArrowLeft":
2101
+ e.shiftKey && !this.option.readOnly ? this.moveSelectedTasksByKeyboard(-1) : this.moveFocusHorizontal(-1), e.preventDefault();
2102
+ break;
2103
+ case "ArrowDown":
2104
+ this.moveFocusVertical(1), e.preventDefault();
2105
+ break;
2106
+ case "ArrowUp":
2107
+ this.moveFocusVertical(-1), e.preventDefault();
2108
+ break;
2109
+ case "Enter":
2110
+ case " ":
2111
+ this.focusedTaskId && (e.ctrlKey || e.metaKey ? this.toggleTaskSelection(this.focusedTaskId) : this.selectSingleTask(this.focusedTaskId)), e.preventDefault();
2112
+ break;
2113
+ case "Escape":
2114
+ this.clearSelection(), this.focusedTaskId = null, this.focusedRowId = null;
2115
+ break;
2116
+ case "Delete":
2117
+ case "Backspace":
2118
+ !this.option.readOnly && this.selectedTasks.size > 0 && this.dispatchEvent(new CustomEvent("task-delete", {
2119
+ detail: {
2120
+ taskIds: [...this.selectedTasks],
2121
+ event: e
2122
+ },
2123
+ bubbles: !0,
2124
+ composed: !0
2125
+ })), e.preventDefault();
2126
+ break;
2127
+ case "Home":
2128
+ this.focusFirstOrLastTaskInRow("first"), e.preventDefault();
2129
+ break;
2130
+ case "End":
2131
+ this.focusFirstOrLastTaskInRow("last"), e.preventDefault();
2132
+ break;
2133
+ }
2134
+ };
2135
+ }
2136
+ get displayRows() {
2137
+ return this.option.showHiddenRows ? this.rows : this.rows.filter((e) => e.visible !== !1);
2138
+ }
2139
+ static {
2140
+ this.styles = q;
2141
+ }
2142
+ firstUpdated() {
2143
+ this.setupCurrentTimeTimer();
2144
+ let e = this.shadowRoot?.getElementById("calendar");
2145
+ this.resizeObserver = new ResizeObserver((t) => {
2146
+ for (let n of t) n.target === this ? this.viewportHeight = n.contentRect.height : n.target === e && (this.calendarHeight = n.target.offsetHeight);
2147
+ }), this.resizeObserver.observe(this), e && this.resizeObserver.observe(e);
2148
+ }
2149
+ connectedCallback() {
2150
+ super.connectedCallback(), this._systemThemeMediaQuery = window.matchMedia ? window.matchMedia("(prefers-color-scheme: dark)") : null, this._systemThemeMediaQuery?.addEventListener("change", this.handleSystemThemeChange), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), this.setAttribute("aria-label", "Gantt Chart"), this.addEventListener("keydown", this.handleKeyDown), this.option?.theme === "system" || this.option?.theme !== "light" && this.option?.theme !== "dark" ? this.theme = this._systemThemeMediaQuery?.matches ? "dark" : "light" : this.theme = this.option.theme;
2151
+ }
2152
+ disconnectedCallback() {
2153
+ super.disconnectedCallback(), this.resizeObserver?.disconnect(), this.stopCurrentTimeTimer(), this._systemThemeMediaQuery?.removeEventListener("change", this.handleSystemThemeChange), this.removeEventListener("keydown", this.handleKeyDown);
2154
+ }
2155
+ willUpdate(e) {
2156
+ if (e.has("option") && (this.option?.theme === "light" || this.option?.theme === "dark" ? this.theme = this.option.theme : this._systemThemeMediaQuery && (this.theme = this._systemThemeMediaQuery.matches ? "dark" : "light")), e.has("option") && (this.setupCurrentTimeTimer(), this.isResizingHeader || (this.currentRowHeaderWidth = this.option.rowHeader?.width ?? 150)), (e.has("rows") || e.has("option") || e.has("currentRowHeaderWidth")) && (this._layoutCache = null), e.has("selectedRowIds")) {
2157
+ let e = new Set(this.selectedRowIds);
2158
+ (e.size !== this.selectedRows.size || ![...e].every((e) => this.selectedRows.has(e))) && (this.selectedRows = e);
2159
+ }
2160
+ if (e.has("selectedTaskIds")) {
2161
+ let e = new Set(this.selectedTaskIds);
2162
+ (e.size !== this.selectedTasks.size || ![...e].every((e) => this.selectedTasks.has(e))) && (this.selectedTasks = e);
2163
+ }
2164
+ (e.has("selectedTasks") || this._cachedSelectedTasksSize !== this.selectedTasks.size) && (this._cachedSelectedTaskIds = [...this.selectedTasks], this._cachedSelectedTasksSize = this.selectedTasks.size);
2165
+ }
2166
+ updated(e) {
2167
+ if (super.updated(e), this.tooltip) {
2168
+ let e = this.shadowRoot?.querySelector(".tooltip");
2169
+ if (e) {
2170
+ let t = this.option.customRendering?.tooltip ? this.option.customRendering.tooltip(this.tooltip.task) : void 0;
2171
+ if (t) r(typeof t == "string" ? d(t) : t, e);
2172
+ else {
2173
+ let t = this.option.locale ?? A, i = !!this.option.calendar.pxPerMonth, a = Math.round((this.tooltip.task.end.getTime() - this.tooltip.task.start.getTime()) / (1e3 * 60 * 60 * 24));
2174
+ if (i) {
2175
+ let i = new Date(this.tooltip.task.end);
2176
+ i.setMonth(i.getMonth() - 1), r(n`
2177
+ <div style="font-weight: bold;">${this.tooltip.task.name}</div>
2178
+ <div class="tooltip-row">
2179
+ ${t.yearMonthFormat(this.tooltip.task.start)} - ${t.yearMonthFormat(i)}
2180
+ </div>
2181
+ <div class="tooltip-row">${t.tooltip.duration(a)}</div>
2182
+ `, e);
2183
+ } else r(n`
2184
+ <div style="font-weight: bold;">${this.tooltip.task.name}</div>
2185
+ <div class="tooltip-row">
2186
+ ${t.dateFormat(this.tooltip.task.start)} - ${t.dateFormat(this.tooltip.task.end)}
2187
+ </div>
2188
+ <div class="tooltip-row">${t.tooltip.duration(a)}</div>
2189
+ `, e);
2190
+ }
2191
+ }
2192
+ }
2193
+ }
2194
+ updateDragOverlay() {
2195
+ if (!this.dragOverlayInfo || this.option.showDragInfoOverlay === !1) return;
2196
+ let e = I(this.theme, this.option.customTheme), t = this.shadowRoot?.querySelector(".drag-info-overlay");
2197
+ if (!t) return;
2198
+ t.classList.toggle("visible", this.dragOverlayInfo.visible), t.innerHTML = "";
2199
+ let { targetRow: n } = this.dragOverlayInfo, i = this.option.customRendering?.dragInfo ? this.option.customRendering.dragInfo({
2200
+ id: this.dragOverlayInfo.id,
2201
+ name: this.dragOverlayInfo.name,
2202
+ start: this.dragOverlayInfo.start,
2203
+ end: this.dragOverlayInfo.end
2204
+ }, this.dragOverlayInfo.currentStart, this.dragOverlayInfo.currentEnd, n) : void 0;
2205
+ if (i && r(i, t), t.innerHTML === "") {
2206
+ let r = this.option.locale ?? A, i = !!this.option.calendar.pxPerMonth, a, o;
2207
+ if (i) {
2208
+ let e = new Date(this.dragOverlayInfo.currentEnd);
2209
+ e.setMonth(e.getMonth() - 1), a = r.yearMonthFormat(this.dragOverlayInfo.currentStart), o = r.yearMonthFormat(e);
2210
+ } else a = r.dateTimeFormat(this.dragOverlayInfo.currentStart), o = r.dateTimeFormat(this.dragOverlayInfo.currentEnd);
2211
+ t.innerHTML = `
2212
+ <div style="font-weight: bold;">
2213
+ ${this.dragOverlayInfo.name || r.dragOverlay.noTitle}
2214
+ </div>
2215
+ <div class="drag-info-sub">
2216
+ ${a} -
2217
+ ${o}
2218
+ (${z(this.dragOverlayInfo.currentStart, this.dragOverlayInfo.currentEnd, this.option.locale)})
2219
+ </div>
2220
+ ${n ? `<div class="drag-info-sub" style="margin-top: 4px; border-top: 1px solid ${e.dragOverlayDivider}; padding-top: 4px; width: 100%;">${(this.option.locale ?? A).dragOverlay.moveTo(n.name)}</div>` : ""}`;
2221
+ }
2222
+ if (this.dragOverlayInfo.clientY !== void 0) {
2223
+ let e = this.dragOverlayInfo.clientX ?? 0, n = this.dragOverlayInfo.clientY, r = this.getBoundingClientRect();
2224
+ if (e < r.left || e > r.right || n < r.top || n > r.bottom) {
2225
+ t.classList.remove("visible");
2226
+ return;
2227
+ }
2228
+ let i = t.offsetWidth || 200, a = t.offsetHeight || 60, o = window.innerWidth, s = window.innerHeight, c = e - i / 2;
2229
+ c = Math.max(8, Math.min(c, o - i - 8));
2230
+ let l = n - a - 40;
2231
+ l < 8 && (l = n + 40), l + a > s - 8 && (l = s - a - 8), t.style.left = `${c}px`, t.style.transform = "none", t.style.top = `${l}px`, t.style.bottom = "auto";
2232
+ }
2233
+ }
2234
+ hideDragOverlay() {
2235
+ let e = this.shadowRoot?.querySelector(".drag-info-overlay");
2236
+ e && e.classList.remove("visible");
2237
+ }
2238
+ setupCurrentTimeTimer() {
2239
+ this.stopCurrentTimeTimer();
2240
+ let e = this.option.calendar.currentTimeUpdateInterval;
2241
+ e && e > 0 && (this.currentTimeTimer = window.setInterval(() => {
2242
+ this.currentTime = /* @__PURE__ */ new Date();
2243
+ }, e));
2244
+ }
2245
+ stopCurrentTimeTimer() {
2246
+ this.currentTimeTimer !== void 0 && (window.clearInterval(this.currentTimeTimer), this.currentTimeTimer = void 0);
2247
+ }
2248
+ handleHeaderResizeStart(e) {
2249
+ e.preventDefault(), e.stopPropagation(), this.isResizingHeader = !0;
2250
+ let t = e.clientX, n = this.currentRowHeaderWidth, r = e.target;
2251
+ r.setPointerCapture(e.pointerId);
2252
+ let i = this.option.rowHeader?.minWidth ?? 50, a = this.option.rowHeader?.maxWidth ?? 2 ** 53 - 1, o = (e) => {
2253
+ let r = n + (e.clientX - t);
2254
+ this.currentRowHeaderWidth = Math.max(i, Math.min(a, r));
2255
+ }, s = () => {
2256
+ this.isResizingHeader = !1, r.releasePointerCapture(e.pointerId), r.removeEventListener("pointermove", o), r.removeEventListener("pointerup", s);
2257
+ let t = Math.round(this.currentRowHeaderWidth);
2258
+ this.currentRowHeaderWidth = t, this.dispatchEvent(new CustomEvent("row-header-resize", {
2259
+ detail: { width: t },
2260
+ bubbles: !0,
2261
+ composed: !0
2262
+ }));
2263
+ };
2264
+ r.addEventListener("pointermove", o), r.addEventListener("pointerup", s);
2265
+ }
2266
+ getDateX(e) {
2267
+ return N(e, this.option.calendar.start, this.option.calendar.pxPerDay ?? 50, this.option.calendar.pxPerMonth);
2268
+ }
2269
+ calculateLayout() {
2270
+ if (this._layoutCache) return this._layoutCache;
2271
+ let e = 0, t = this.currentRowHeaderWidth, n = /* @__PURE__ */ new Map(), r = {
2272
+ layouts: this.displayRows.map((r) => {
2273
+ let { tasksWithLanes: i, laneCount: a } = F(r.tasks), o = this.option.bar?.height ?? 28, s = this.option.bar?.margin ?? 4;
2274
+ i.forEach((r) => {
2275
+ let i = this.getDateX(r.start) + t, a = this.getDateX(r.end) + t - i, c = e + r.lane * (o + s) + s;
2276
+ n.set(r.id, {
2277
+ x: i,
2278
+ y: c,
2279
+ width: a,
2280
+ height: o,
2281
+ dependencies: r.dependencies
2282
+ });
2283
+ });
2284
+ let c = a * (o + s) + s, l = {
2285
+ top: e,
2286
+ height: c
2287
+ };
2288
+ return e += c, l;
2289
+ }),
2290
+ taskCoords: n,
2291
+ totalHeight: e
2292
+ };
2293
+ return this._layoutCache = r, r;
2294
+ }
2295
+ isMultiDrag(e) {
2296
+ return this.selectedTasks.size >= 2 && this.selectedTasks.has(e);
2297
+ }
2298
+ handleTaskUpdate(e) {
2299
+ e.stopPropagation();
2300
+ let { id: t, start: n, end: r, dx: i, isDragging: a, mode: o } = e.detail, { dy: s } = e.detail, c = this.isMultiDrag(t);
2301
+ c && (s = 0);
2302
+ let l = n, u = r;
2303
+ if (i !== void 0) {
2304
+ let e = this.option.calendar.pxPerDay ?? 50, t = this.option.calendar.pxPerMonth, a = this.getDateX(n), o = this.getDateX(r);
2305
+ l = P(a + i, this.option.calendar.start, e, t), u = P(o + i, this.option.calendar.start, e, t);
2306
+ }
2307
+ (this.option.calendar.pxPerMonth || this.option.snapDuration && this.option.snapDuration >= 43200) && (l.getDate() > 15 && l.setMonth(l.getMonth() + 1), l.setDate(1), l.setHours(0, 0, 0, 0), u.getDate() > 15 && u.setMonth(u.getMonth() + 1), u.setDate(1), u.setHours(0, 0, 0, 0));
2308
+ let d = -1, f, p = -1;
2309
+ if (this.rows.find((e, n) => {
2310
+ let r = e.tasks.findIndex((e) => e.id === t);
2311
+ return r === -1 ? !1 : (d = n, f = e.tasks[r], p = r, !0);
2312
+ }), d === -1 || !f) return;
2313
+ let { layouts: m } = this.calculateLayout(), h = this.displayRows.findIndex((e) => e.id === this.rows[d].id);
2314
+ if (h === -1) return;
2315
+ let g = m[h].top, { tasksWithLanes: _ } = F(this.rows[d].tasks), v = _.find((e) => e.id === t), y = v ? v.lane : 0, b = this.option.bar?.height ?? 28, x = this.option.bar?.margin ?? 4, S = g + (y * (b + x) + x) + s + b / 2, C = -1;
2316
+ for (let e = 0; e < m.length; e++) {
2317
+ let t = m[e];
2318
+ if (S >= t.top && S < t.top + t.height) {
2319
+ C = e;
2320
+ break;
2321
+ }
2322
+ }
2323
+ let w = C === -1 ? void 0 : this.displayRows[C].id, T = c ? [...this.selectedTasks] : void 0;
2324
+ if (this.dispatchEvent(new CustomEvent("task-update", {
2325
+ detail: {
2326
+ ...e.detail,
2327
+ dy: s,
2328
+ start: l,
2329
+ end: u,
2330
+ targetRowId: w,
2331
+ selectedTaskIds: T
2332
+ },
2333
+ bubbles: !0,
2334
+ composed: !0
2335
+ })), a) {
2336
+ if (this.hoverTimer !== void 0 && window.clearTimeout(this.hoverTimer), this.tooltip &&= null, (!this.draggingTask || this.draggingTask.id !== t) && (this.draggingTask = {
2337
+ id: t,
2338
+ name: e.detail.name,
2339
+ start: n,
2340
+ end: r,
2341
+ currentStart: l,
2342
+ currentEnd: u,
2343
+ mode: o
2344
+ }, c ? this.draggingTaskIds = [...this.selectedTasks] : this.draggingTaskIds = []), c ? this.multiDragDx = i ?? 0 : this.multiDragDx !== 0 && (this.multiDragDx = 0), !c) {
2345
+ let e = C >= 0 ? C : null;
2346
+ this.dragTargetRowIndex !== e && (this.dragTargetRowIndex = e);
2347
+ }
2348
+ c ? this.dragOverlayInfo = {
2349
+ id: t,
2350
+ name: (this.option.locale ?? A).dragOverlay.movingTasks(this.selectedTasks.size),
2351
+ start: n,
2352
+ end: r,
2353
+ currentStart: l,
2354
+ currentEnd: u,
2355
+ visible: !0,
2356
+ clientX: e.detail.x,
2357
+ clientY: e.detail.y
2358
+ } : this.dragOverlayInfo = {
2359
+ id: t,
2360
+ name: e.detail.name,
2361
+ start: n,
2362
+ end: r,
2363
+ currentStart: l,
2364
+ currentEnd: u,
2365
+ targetRow: C >= 0 ? this.displayRows[C] : void 0,
2366
+ visible: !0,
2367
+ clientX: e.detail.x,
2368
+ clientY: e.detail.y
2369
+ }, this.updateDragOverlay();
2370
+ return;
2371
+ }
2372
+ let E = this.draggingTaskIds.length >= 2;
2373
+ this.draggingTask = null, this.draggingTaskIds = [], this.multiDragDx = 0, this.dragTargetRowIndex = null, this.dragOverlayInfo && (this.dragOverlayInfo = {
2374
+ ...this.dragOverlayInfo,
2375
+ visible: !1
2376
+ }, this.hideDragOverlay()), this.tooltip &&= {
2377
+ ...this.tooltip,
2378
+ visible: !1
2379
+ };
2380
+ let D = -1;
2381
+ if (C !== -1) {
2382
+ let e = this.displayRows[C];
2383
+ D = this.rows.findIndex((t) => t.id === e.id);
2384
+ }
2385
+ if (E && i !== void 0) {
2386
+ let e = this.option.calendar.pxPerDay ?? 50, t = this.option.calendar.pxPerMonth, n = this.rows.map((n) => n.tasks.some((e) => this.selectedTasks.has(e.id)) ? {
2387
+ ...n,
2388
+ tasks: n.tasks.map((n) => {
2389
+ if (!this.selectedTasks.has(n.id)) return n;
2390
+ let r = this.getDateX(n.start), a = this.getDateX(n.end), o = P(r + i, this.option.calendar.start, e, t), s = P(a + i, this.option.calendar.start, e, t);
2391
+ return (this.option.calendar.pxPerMonth || this.option.snapDuration && this.option.snapDuration >= 43200) && (o.getDate() > 15 && o.setMonth(o.getMonth() + 1), o.setDate(1), o.setHours(0, 0, 0, 0), s.getDate() > 15 && s.setMonth(s.getMonth() + 1), s.setDate(1), s.setHours(0, 0, 0, 0)), {
2392
+ ...n,
2393
+ start: o,
2394
+ end: s
2395
+ };
2396
+ })
2397
+ } : n);
2398
+ requestAnimationFrame(() => {
2399
+ this.rows = n, this.dispatchEvent(new CustomEvent("rows-change", {
2400
+ detail: this.rows,
2401
+ bubbles: !0,
2402
+ composed: !0
2403
+ }));
2404
+ });
2405
+ return;
2406
+ }
2407
+ if (o === "copy") {
2408
+ if (D !== -1) {
2409
+ let e = [...this.rows], t = { ...e[D] };
2410
+ t.tasks = [...t.tasks];
2411
+ let n = `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, r = {
2412
+ ...f,
2413
+ id: n,
2414
+ start: l,
2415
+ end: u,
2416
+ dependencies: []
2417
+ };
2418
+ t.tasks.push(r), e[D] = t, requestAnimationFrame(() => {
2419
+ this.rows = e, this.dispatchEvent(new CustomEvent("rows-change", {
2420
+ detail: this.rows,
2421
+ bubbles: !0,
2422
+ composed: !0
2423
+ }));
2424
+ });
2425
+ }
2426
+ } else {
2427
+ let e = [...this.rows], t = { ...e[d] };
2428
+ if (t.tasks = [...t.tasks], e[d] = t, D !== -1 && d !== D) {
2429
+ let n = { ...e[D] };
2430
+ n.tasks = [...n.tasks], e[D] = n;
2431
+ let [r] = t.tasks.splice(p, 1);
2432
+ n.tasks.push({
2433
+ ...r,
2434
+ start: l,
2435
+ end: u
2436
+ });
2437
+ } else t.tasks[p] = {
2438
+ ...f,
2439
+ start: l,
2440
+ end: u
2441
+ };
2442
+ requestAnimationFrame(() => {
2443
+ this.rows = e, this.dispatchEvent(new CustomEvent("rows-change", {
2444
+ detail: this.rows,
2445
+ bubbles: !0,
2446
+ composed: !0
2447
+ }));
2448
+ });
2449
+ }
2450
+ }
2451
+ handleBarMouseEnter(e) {
2452
+ if (this.draggingTask || this.option.showTooltip === !1) return;
2453
+ this.hoverTimer !== void 0 && window.clearTimeout(this.hoverTimer);
2454
+ let t = this.option.tooltipDelay ?? 500;
2455
+ t > 0 ? this.hoverTimer = window.setTimeout(() => {
2456
+ this.tooltip = {
2457
+ ...e.detail,
2458
+ visible: !0
2459
+ };
2460
+ }, t) : this.tooltip = {
2461
+ ...e.detail,
2462
+ visible: !0
2463
+ };
2464
+ }
2465
+ handleBarMouseLeave() {
2466
+ this.hoverTimer !== void 0 && window.clearTimeout(this.hoverTimer), this.tooltip &&= {
2467
+ ...this.tooltip,
2468
+ visible: !1
2469
+ };
2470
+ }
2471
+ async reorderRows(e, t, n) {
2472
+ let r = Array.isArray(e) ? e : [e], i = Array.from(this.shadowRoot?.querySelectorAll("gantt-row") ?? []), a = /* @__PURE__ */ new Map();
2473
+ i.forEach((e) => {
2474
+ e.row && a.set(e.row.id, e.getBoundingClientRect().top);
2475
+ });
2476
+ let o = [...this.rows], s = [];
2477
+ if (o.findIndex((e) => e.id === t) === -1) return;
2478
+ r.forEach((e) => {
2479
+ let t = o.findIndex((t) => t.id === e);
2480
+ t !== -1 && s.push(o[t]);
2481
+ });
2482
+ let c = o.filter((e) => !r.includes(e.id));
2483
+ if (r.includes(t)) return;
2484
+ let l = c.findIndex((e) => e.id === t);
2485
+ n === "bottom" && l++, c.splice(l, 0, ...s), this.rows = c, await this.updateComplete, Array.from(this.shadowRoot?.querySelectorAll("gantt-row") ?? []).forEach((e) => {
2486
+ if (e.row) {
2487
+ let t = a.get(e.row.id);
2488
+ if (t !== void 0) {
2489
+ let n = t - e.getBoundingClientRect().top;
2490
+ n !== 0 && e.animate([{
2491
+ transform: `translateY(${n}px)`,
2492
+ zIndex: "1"
2493
+ }, {
2494
+ transform: "translateY(0)",
2495
+ zIndex: "1"
2496
+ }], {
2497
+ duration: 300,
2498
+ easing: "ease-out"
2499
+ });
2500
+ }
2501
+ }
2502
+ }), this.dispatchEvent(new CustomEvent("row-reordered", {
2503
+ detail: {
2504
+ sourceId: r[0],
2505
+ sourceIds: r,
2506
+ targetId: t,
2507
+ position: n,
2508
+ rows: this.rows
2509
+ },
2510
+ bubbles: !0,
2511
+ composed: !0
2512
+ })), this.dispatchEvent(new CustomEvent("rows-change", {
2513
+ detail: this.rows,
2514
+ bubbles: !0,
2515
+ composed: !0
2516
+ }));
2517
+ }
2518
+ handleContainerDragOver(e) {
2519
+ e.preventDefault();
2520
+ let t = e.dataTransfer && e.dataTransfer.types.includes("application/json");
2521
+ if (t && (e.dataTransfer.dropEffect = "copy"), !this.option.enableRowReordering && !t) return;
2522
+ let n = this.shadowRoot?.querySelector(".scroll-container");
2523
+ if (!n) return;
2524
+ let r = n.getBoundingClientRect(), i = e.clientY - r.top + n.scrollTop - this.calendarHeight, { layouts: a } = this.calculateLayout(), o = -1;
2525
+ for (let e = 0; e < a.length; e++) {
2526
+ let t = a[e];
2527
+ if (i >= t.top && i < t.top + t.height) {
2528
+ o = e;
2529
+ break;
2530
+ }
2531
+ }
2532
+ if (o !== -1) {
2533
+ let s = this.displayRows[o];
2534
+ if (t) {
2535
+ if ((this.dragOverRowId !== s.id || this.dragOverPosition !== null) && (this.dragOverRowId = s.id, this.dragOverPosition = null), this.externalDraggingTask) {
2536
+ let t = this.currentRowHeaderWidth, i = n.scrollLeft, a = e.clientX - r.left + i - t, o = this.option.calendar.pxPerDay ?? 50, c = this.option.calendar.pxPerMonth, l = this.option.snapDuration ?? 1440, u = o / 1440 * l, d = P(Math.round(a / u) * u, this.option.calendar.start, o, c), f = this.externalDraggingTask.end.getTime() - this.externalDraggingTask.start.getTime(), p = new Date(d.getTime() + f);
2537
+ (!this.dragPreview || this.dragPreview.rowId !== s.id || this.dragPreview.currentStart.getTime() !== d.getTime()) && (this.dragPreview = {
2538
+ task: this.externalDraggingTask,
2539
+ currentStart: d,
2540
+ currentEnd: p,
2541
+ rowId: s.id
2542
+ });
2543
+ }
2544
+ } else {
2545
+ let e = a[o], t = i - e.top < e.height / 2 ? "top" : "bottom";
2546
+ (this.dragOverRowId !== s.id || this.dragOverPosition !== t) && (this.dragOverRowId = s.id, this.dragOverPosition = t);
2547
+ }
2548
+ } else this.dragOverRowId = null, this.dragOverPosition = null, this.dragPreview = null;
2549
+ }
2550
+ handleContainerDragLeave(e) {
2551
+ let t = this.shadowRoot?.querySelector(".scroll-container"), n = e.relatedTarget;
2552
+ t && t.contains(n) || (this.dragOverRowId = null, this.dragOverPosition = null, this.dragPreview = null);
2553
+ }
2554
+ handleContainerDrop(e) {
2555
+ e.preventDefault();
2556
+ let t = e.dataTransfer?.getData("application/json");
2557
+ if (t) {
2558
+ this.handleExternalTaskDrop(e, t), this.dragOverRowId = null, this.dragOverPosition = null, this.dragPreview = null;
2559
+ return;
2560
+ }
2561
+ if (!this.option.enableRowReordering) return;
2562
+ let n = e.dataTransfer?.getData("text/plain"), r = this.dragOverRowId, i = this.dragOverPosition;
2563
+ if (this.dragOverRowId = null, this.dragOverPosition = null, this.dragPreview = null, n && r && n !== r && i) if (this.selectedRows.has(n) && this.selectedRows.size > 1) {
2564
+ let e = Array.from(this.selectedRows);
2565
+ this.reorderRows(e, r, i);
2566
+ } else this.reorderRows(n, r, i);
2567
+ }
2568
+ handleExternalTaskDrop(e, t) {
2569
+ try {
2570
+ let n = JSON.parse(t), r = this.shadowRoot?.querySelector(".scroll-container");
2571
+ if (!r) return;
2572
+ let i = r.getBoundingClientRect(), a = r.scrollLeft, o = r.scrollTop, s = this.currentRowHeaderWidth, c = e.clientX - i.left + a - s, l = this.option.calendar.pxPerDay ?? 50, u = this.option.calendar.pxPerMonth, d = P(c, this.option.calendar.start, l, u), f = e.clientY - i.top + o - this.calendarHeight, { layouts: p } = this.calculateLayout(), m;
2573
+ for (let e = 0; e < p.length; e++) {
2574
+ let t = p[e];
2575
+ if (f >= t.top && f < t.top + t.height) {
2576
+ m = this.displayRows[e].id;
2577
+ break;
2578
+ }
2579
+ }
2580
+ m && this.dispatchEvent(new CustomEvent("task-drop", {
2581
+ detail: {
2582
+ task: n,
2583
+ dropDate: d,
2584
+ targetRowId: m
2585
+ },
2586
+ bubbles: !0,
2587
+ composed: !0
2588
+ }));
2589
+ } catch (e) {
2590
+ console.warn("Failed to parse dropped task data", e);
2591
+ }
2592
+ }
2593
+ handleRowClicked(e) {
2594
+ let { rowId: t, event: n } = e.detail, { shiftKey: r, ctrlKey: i, metaKey: a } = n, o = new Set(this.selectedRows);
2595
+ if (r && this.lastClickedRowId) {
2596
+ let e = this.rows.findIndex((e) => e.id === this.lastClickedRowId), n = this.rows.findIndex((e) => e.id === t);
2597
+ if (e !== -1 && n !== -1) {
2598
+ let t = Math.min(e, n), r = Math.max(e, n);
2599
+ for (let e = t; e <= r; e++) o.add(this.rows[e].id);
2600
+ }
2601
+ } else if (i || a) o.has(t) ? o.delete(t) : o.add(t), this.lastClickedRowId = t;
2602
+ else {
2603
+ if (o.has(t)) {
2604
+ this.lastClickedRowId = t;
2605
+ return;
2606
+ }
2607
+ o.clear(), o.add(t), this.lastClickedRowId = t;
2608
+ }
2609
+ this.selectedRows = o, this.dispatchEvent(new CustomEvent("row-selection-change", {
2610
+ detail: { selectedIds: Array.from(this.selectedRows) },
2611
+ bubbles: !0,
2612
+ composed: !0
2613
+ }));
2614
+ }
2615
+ handleRowContextMenu(e) {
2616
+ this.selectedRows.has(e.detail.rowId) || this.handleRowClicked(e);
2617
+ }
2618
+ handleContainerClick(e) {
2619
+ e.defaultPrevented || this.clearSelection();
2620
+ }
2621
+ handleContainerContextMenu(e) {
2622
+ if (e.defaultPrevented) return;
2623
+ e.preventDefault();
2624
+ let t = this.shadowRoot?.querySelector(".scroll-container");
2625
+ if (!t) return;
2626
+ let n = t.getBoundingClientRect(), r = t.scrollLeft, i = t.scrollTop, a = this.currentRowHeaderWidth, o = e.clientY - n.top + i - this.calendarHeight, { layouts: s } = this.calculateLayout(), c;
2627
+ for (let e = 0; e < s.length; e++) {
2628
+ let t = s[e];
2629
+ if (o >= t.top && o < t.top + t.height) {
2630
+ c = this.displayRows[e].id;
2631
+ break;
2632
+ }
2633
+ }
2634
+ if (c) {
2635
+ let t = e.clientX - n.left + r - a, i = this.option.calendar.pxPerDay ?? 50, o = this.option.calendar.pxPerMonth, s = P(t, this.option.calendar.start, i, o);
2636
+ this.dispatchEvent(new CustomEvent("chart-contextmenu", {
2637
+ detail: {
2638
+ event: e,
2639
+ date: s,
2640
+ rowId: c
2641
+ },
2642
+ bubbles: !0,
2643
+ composed: !0
2644
+ }));
2645
+ }
2646
+ this.clearSelection();
2647
+ }
2648
+ hitTest(e, t) {
2649
+ let n = this.shadowRoot?.querySelector(".scroll-container");
2650
+ if (!n) return null;
2651
+ let r = n.getBoundingClientRect(), i = n.scrollLeft, a = n.scrollTop, o = this.currentRowHeaderWidth, s = t - r.top + a - this.calendarHeight, { layouts: c } = this.calculateLayout(), l;
2652
+ for (let e = 0; e < c.length; e++) {
2653
+ let t = c[e];
2654
+ if (s >= t.top && s < t.top + t.height) {
2655
+ l = this.displayRows[e].id;
2656
+ break;
2657
+ }
2658
+ }
2659
+ if (!l) return null;
2660
+ let u = e - r.left + i - o, d = this.option.calendar.pxPerDay ?? 50, f = this.option.calendar.pxPerMonth, p = P(u, this.option.calendar.start, d, f);
2661
+ return {
2662
+ rowId: l,
2663
+ date: p
2664
+ };
2665
+ }
2666
+ async exportImage(e = "png", t = {}) {
2667
+ this.isExporting = !0, await this.updateComplete, await new Promise((e) => requestAnimationFrame(e));
2668
+ try {
2669
+ return await X(this, e, t);
2670
+ } finally {
2671
+ this.isExporting = !1, await this.updateComplete;
2672
+ }
2673
+ }
2674
+ clearSelection() {
2675
+ this.selectedRows.size === 0 && this.selectedTasks.size === 0 || (this.selectedRows.size > 0 && (this.selectedRows = /* @__PURE__ */ new Set(), this.dispatchEvent(new CustomEvent("row-selection-change", {
2676
+ detail: { selectedIds: [] },
2677
+ bubbles: !0,
2678
+ composed: !0
2679
+ }))), this.selectedTasks.size > 0 && (this.selectedTasks = /* @__PURE__ */ new Set(), this.dispatchEvent(new CustomEvent("bar-selection-change", {
2680
+ detail: { selectedIds: [] },
2681
+ bubbles: !0,
2682
+ composed: !0
2683
+ }))));
2684
+ }
2685
+ moveFocusHorizontal(e) {
2686
+ let t = this.displayRows;
2687
+ if (t.length === 0) return;
2688
+ if (!this.focusedTaskId || !this.focusedRowId) {
2689
+ this.focusFirstAvailableTask();
2690
+ return;
2691
+ }
2692
+ let n = t.findIndex((e) => e.id === this.focusedRowId);
2693
+ if (n === -1) {
2694
+ this.focusFirstAvailableTask();
2695
+ return;
2696
+ }
2697
+ let r = t[n], i = [...r.tasks].sort((e, t) => e.start.getTime() - t.start.getTime()), a = i.findIndex((e) => e.id === this.focusedTaskId);
2698
+ if (a === -1) {
2699
+ i.length > 0 && this.setFocus(i[0].id, r.id);
2700
+ return;
2701
+ }
2702
+ let o = a + e;
2703
+ o >= 0 && o < i.length ? this.setFocus(i[o].id, r.id) : this.moveFocusVertical(e);
2704
+ }
2705
+ moveFocusVertical(e) {
2706
+ let t = this.displayRows;
2707
+ if (t.length === 0) return;
2708
+ if (!this.focusedTaskId || !this.focusedRowId) {
2709
+ this.focusFirstAvailableTask();
2710
+ return;
2711
+ }
2712
+ let n = t.findIndex((e) => e.id === this.focusedRowId);
2713
+ if (n === -1) {
2714
+ this.focusFirstAvailableTask();
2715
+ return;
2716
+ }
2717
+ for (let r = n + e; r >= 0 && r < t.length; r += e) {
2718
+ let n = t[r];
2719
+ if (n.tasks.length > 0) {
2720
+ let t = [...n.tasks].sort((e, t) => e.start.getTime() - t.start.getTime()), r = e > 0 ? t[0] : t[t.length - 1];
2721
+ this.setFocus(r.id, n.id);
2722
+ return;
2723
+ }
2724
+ }
2725
+ }
2726
+ focusFirstAvailableTask() {
2727
+ for (let e of this.displayRows) if (e.tasks.length > 0) {
2728
+ let t = [...e.tasks].sort((e, t) => e.start.getTime() - t.start.getTime());
2729
+ this.setFocus(t[0].id, e.id);
2730
+ return;
2731
+ }
2732
+ }
2733
+ focusFirstOrLastTaskInRow(e) {
2734
+ if (!this.focusedRowId) {
2735
+ this.focusFirstAvailableTask();
2736
+ return;
2737
+ }
2738
+ let t = this.displayRows.find((e) => e.id === this.focusedRowId);
2739
+ if (!t || t.tasks.length === 0) return;
2740
+ let n = [...t.tasks].sort((e, t) => e.start.getTime() - t.start.getTime()), r = e === "first" ? n[0] : n[n.length - 1];
2741
+ this.setFocus(r.id, t.id);
2742
+ }
2743
+ setFocus(e, t) {
2744
+ this.focusedTaskId = e, this.focusedRowId = t, this.scrollToTask(e);
2745
+ }
2746
+ toggleTaskSelection(e) {
2747
+ let t = new Set(this.selectedTasks);
2748
+ t.has(e) ? t.delete(e) : t.add(e), this.selectedTasks = t, this.dispatchEvent(new CustomEvent("bar-selection-change", {
2749
+ detail: { selectedIds: [...t] },
2750
+ bubbles: !0,
2751
+ composed: !0
2752
+ }));
2753
+ }
2754
+ selectSingleTask(e) {
2755
+ this.selectedTasks = new Set([e]), this.dispatchEvent(new CustomEvent("bar-selection-change", {
2756
+ detail: { selectedIds: [e] },
2757
+ bubbles: !0,
2758
+ composed: !0
2759
+ }));
2760
+ }
2761
+ moveSelectedTasksByKeyboard(e) {
2762
+ if (this.selectedTasks.size === 0) return;
2763
+ let t = (this.option.keyboard?.moveStep ?? this.option.snapDuration ?? 1440) * 60 * 1e3 * e, n = this.rows.map((e) => e.tasks.some((e) => this.selectedTasks.has(e.id)) ? {
2764
+ ...e,
2765
+ tasks: e.tasks.map((e) => this.selectedTasks.has(e.id) ? {
2766
+ ...e,
2767
+ start: new Date(e.start.getTime() + t),
2768
+ end: new Date(e.end.getTime() + t)
2769
+ } : e)
2770
+ } : e);
2771
+ for (let e of this.rows) for (let n of e.tasks) {
2772
+ if (!this.selectedTasks.has(n.id)) continue;
2773
+ let r = new Date(n.start.getTime() + t), i = new Date(n.end.getTime() + t);
2774
+ this.dispatchEvent(new CustomEvent("task-update", {
2775
+ detail: {
2776
+ id: n.id,
2777
+ name: n.name,
2778
+ start: r,
2779
+ end: i,
2780
+ dx: 0,
2781
+ dy: 0,
2782
+ isDragging: !1,
2783
+ mode: "move",
2784
+ targetRowId: e.id
2785
+ },
2786
+ bubbles: !0,
2787
+ composed: !0
2788
+ }));
2789
+ }
2790
+ this.rows = n, this.dispatchEvent(new CustomEvent("rows-change", {
2791
+ detail: this.rows,
2792
+ bubbles: !0,
2793
+ composed: !0
2794
+ }));
2795
+ }
2796
+ handleBarClick(e) {
2797
+ e.stopPropagation();
2798
+ let { task: t, isMultiSelect: n } = e.detail;
2799
+ this.draggingTask = null, this.dragTargetRowIndex = null, this.dragOverlayInfo && (this.dragOverlayInfo = {
2800
+ ...this.dragOverlayInfo,
2801
+ visible: !1
2802
+ }, this.hideDragOverlay());
2803
+ let r;
2804
+ n ? (r = new Set(this.selectedTasks), r.has(t.id) ? r.delete(t.id) : r.add(t.id)) : r = new Set([t.id]), this.selectedTasks = r, this.dispatchEvent(new CustomEvent("bar-selection-change", {
2805
+ detail: { selectedIds: [...r] },
2806
+ bubbles: !0,
2807
+ composed: !0
2808
+ }));
2809
+ }
2810
+ handleBarContextMenu(e) {
2811
+ let { task: t } = e.detail;
2812
+ this.selectedTasks.has(t.id) || (this.selectedTasks = new Set([t.id]), this.dispatchEvent(new CustomEvent("bar-selection-change", {
2813
+ detail: { selectedIds: [t.id] },
2814
+ bubbles: !0,
2815
+ composed: !0
2816
+ })));
2817
+ }
2818
+ handleConnectorDragStart(e) {
2819
+ let { taskId: t, endpoint: n, clientX: r, clientY: i } = e.detail;
2820
+ e.stopPropagation();
2821
+ let { taskCoords: a } = this.calculateLayout(), o = a.get(t), s = this.currentRowHeaderWidth, c = e.detail.startX + s, l = e.detail.startY;
2822
+ o && (c = n === "start" ? o.x : o.x + o.width, l = o.y + o.height / 2), this.connectorDrag = {
2823
+ sourceTaskId: t,
2824
+ sourceEndpoint: n,
2825
+ startX: c,
2826
+ startY: l,
2827
+ currentClientX: r,
2828
+ currentClientY: i,
2829
+ targetTaskId: null,
2830
+ targetEndpoint: null
2831
+ }, this.tooltip &&= null;
2832
+ }
2833
+ handleConnectorDragMove(e) {
2834
+ if (!this.connectorDrag) return;
2835
+ e.stopPropagation();
2836
+ let { clientX: t, clientY: n } = e.detail, r = this.shadowRoot?.querySelector(".scroll-container");
2837
+ if (!r) return;
2838
+ let i = r.getBoundingClientRect(), a = t - i.left + r.scrollLeft, o = n - i.top + r.scrollTop - this.calendarHeight, { taskCoords: s } = this.calculateLayout(), c = null, l = null, u = 30;
2839
+ for (let [e, t] of s) {
2840
+ if (e === this.connectorDrag.sourceTaskId) continue;
2841
+ let n = t.y + t.height / 2, r = t.x, i = t.x + t.width, s = Math.sqrt((a - r) ** 2 + (o - n) ** 2), d = Math.sqrt((a - i) ** 2 + (o - n) ** 2);
2842
+ s < u && (u = s, c = e, l = "start"), d < u && (u = d, c = e, l = "end");
2843
+ }
2844
+ let d = this.connectorDrag.targetTaskId;
2845
+ d !== c && (d && this._setConnectorDropTarget(d, !1), c && this._setConnectorDropTarget(c, !0)), this.connectorDrag = {
2846
+ ...this.connectorDrag,
2847
+ currentClientX: t,
2848
+ currentClientY: n,
2849
+ targetTaskId: c,
2850
+ targetEndpoint: l
2851
+ };
2852
+ }
2853
+ handleConnectorDragEnd(e) {
2854
+ if (!this.connectorDrag) return;
2855
+ e.stopPropagation();
2856
+ let { cancelled: t } = e.detail, { sourceTaskId: n, sourceEndpoint: r, targetTaskId: i, targetEndpoint: a } = this.connectorDrag;
2857
+ i && this._setConnectorDropTarget(i, !1), !t && i && a && this.dispatchEvent(new CustomEvent("dependency-create", {
2858
+ detail: {
2859
+ sourceTaskId: n,
2860
+ sourceEndpoint: r,
2861
+ targetTaskId: i,
2862
+ targetEndpoint: a
2863
+ },
2864
+ bubbles: !0,
2865
+ composed: !0
2866
+ })), this.connectorDrag = null;
2867
+ }
2868
+ _setConnectorDropTarget(e, t) {
2869
+ let n = this.shadowRoot?.querySelectorAll("gantt-row");
2870
+ if (n) for (let r of n) {
2871
+ let n = r.shadowRoot?.querySelectorAll("gantt-bar");
2872
+ if (n) {
2873
+ for (let r of n) if (r.task?.id === e) {
2874
+ r.connectorDropTarget = t;
2875
+ return;
2876
+ }
2877
+ }
2878
+ }
2879
+ }
2880
+ handleDependencyLineClick(e, t, n) {
2881
+ this.dispatchEvent(new CustomEvent("dependency-click", {
2882
+ detail: {
2883
+ event: e,
2884
+ sourceTaskId: n,
2885
+ targetTaskId: t
2886
+ },
2887
+ bubbles: !0,
2888
+ composed: !0
2889
+ }));
2890
+ }
2891
+ selectTask(e) {
2892
+ let t = !1;
2893
+ for (let n of this.displayRows) if (n.tasks.some((t) => t.id === e)) {
2894
+ t = !0;
2895
+ break;
2896
+ }
2897
+ return t ? (this.selectedTasks = new Set([e]), this.dispatchEvent(new CustomEvent("bar-selection-change", {
2898
+ detail: { selectedIds: [e] },
2899
+ bubbles: !0,
2900
+ composed: !0
2901
+ })), this.scrollToTask(e), !0) : !1;
2902
+ }
2903
+ scrollToTask(e) {
2904
+ let { taskCoords: t } = this.calculateLayout(), n = t.get(e);
2905
+ if (!n) return;
2906
+ let r = this.shadowRoot?.querySelector(".scroll-container");
2907
+ if (!r) return;
2908
+ let i = this.currentRowHeaderWidth, a = n.y + this.calendarHeight, o = a + n.height, s = r.scrollTop, c = r.scrollTop + r.clientHeight;
2909
+ if (a < s || o > c) {
2910
+ let e = a - r.clientHeight / 2 + n.height / 2;
2911
+ r.scrollTo({
2912
+ top: Math.max(0, e),
2913
+ behavior: "smooth"
2914
+ });
2915
+ }
2916
+ let l = n.x, u = n.x + n.width, d = r.scrollLeft + i, f = r.scrollLeft + r.clientWidth;
2917
+ if (l < d || u > f) {
2918
+ let e = l - i - 20;
2919
+ r.scrollTo({
2920
+ left: Math.max(0, e),
2921
+ behavior: "smooth"
2922
+ });
2923
+ }
2924
+ }
2925
+ render() {
2926
+ let e = I(this.theme, this.option.customTheme), { layouts: t, taskCoords: r, totalHeight: a } = this.calculateLayout(), o = this.currentRowHeaderWidth;
2927
+ (this._lastOptionRef !== this.option || this._lastLabelWidth !== o) && (this._cachedCurrentOption = {
2928
+ ...this.option,
2929
+ rowHeader: {
2930
+ ...this.option.rowHeader,
2931
+ width: o
2932
+ }
2933
+ }, this._lastOptionRef = this.option, this._lastLabelWidth = o);
2934
+ let s = this._cachedCurrentOption, c = 0, l = this.displayRows.length - 1;
2935
+ if (!this.isExporting) {
2936
+ for (let e = 0; e < t.length; e++) if (t[e].top + t[e].height > this.virtualScrollTop) {
2937
+ c = Math.max(0, e - 5);
2938
+ break;
2939
+ }
2940
+ for (let e = c; e < t.length; e++) if (t[e].top > this.virtualScrollTop + this.viewportHeight) {
2941
+ l = Math.min(this.displayRows.length - 1, e + 5);
2942
+ break;
2943
+ }
2944
+ }
2945
+ let d = this.displayRows.slice(c, l + 1), f = this.isExporting ? 0 : t[c] ? t[c].top : 0, p = t[l], m = p ? p.top + p.height : 0, h = Math.max(0, a - m), g = a > this.viewportHeight, _ = [], v = this.option.readOnly === !0, y = this.option.dependency?.showArrows !== !1, b = this.option.dependency?.arrowSize ?? 8, x = this.option.dependency?.lineStyle ?? "orthogonal", S = this.option.dependency?.cornerRadius ?? 8;
2946
+ for (let [e, t] of r) if (t.dependencies) for (let n of t.dependencies) {
2947
+ let a = r.get(n);
2948
+ if (a) {
2949
+ let r = a.x + a.width, o = a.y + a.height / 2, s = t.x, c = t.y + t.height / 2, l = r < s, u = y ? s - b : s, d = l ? Math.max(r, u) : u, f, p, m, h = this.option.bar?.height ?? 28, g = this.option.bar?.margin ?? 4;
2950
+ if (Math.abs(o - c) < 1 && l) f = d > r ? `M ${r} ${o} L ${d} ${c}` : "", p = s > r ? `M ${r} ${o} L ${s} ${c}` : "";
2951
+ else if (x === "orthogonal") {
2952
+ let e = K(r, o, s, c, d, h, g, S);
2953
+ f = e.pathD, p = e.hitPathD;
2954
+ } else if (l) {
2955
+ let e = (r + d) / 2;
2956
+ f = `M ${r} ${o} C ${e} ${o} ${e} ${c} ${d} ${c}`, p = `M ${r} ${o} C ${(r + s) / 2} ${o} ${(r + s) / 2} ${c} ${s} ${c}`;
2957
+ } else {
2958
+ let e = Math.max(12, (r - s) * .15), t = (o + c) / 2, n = Math.abs(o - c) < h ? t + h + g : t;
2959
+ f = `M ${r} ${o} C ${r + e} ${o}, ${r + e} ${n}, ${(r + d) / 2} ${n} S ${d - e} ${c}, ${d} ${c}`, p = `M ${r} ${o} C ${r + e} ${o}, ${r + e} ${n}, ${(r + s) / 2} ${n} S ${s - e} ${c}, ${s} ${c}`;
2960
+ }
2961
+ m = y ? `M ${d} ${c} L ${s} ${c}` : "", _.push(i`<g class="dependency-group">
2962
+ ${v ? "" : i`<path class="dependency-hit-area" d="${p}" @click="${(t) => {
2963
+ t.stopPropagation(), this.handleDependencyLineClick(t, e, n);
2964
+ }}" />`}
2965
+ <path class="dependency-line" d="${f}" />
2966
+ ${y ? i`<path class="dependency-line dependency-arrow-line" d="${m}" marker-end="url(#dependency-arrowhead)" />` : ""}
2967
+ </g>`);
2968
+ }
2969
+ }
2970
+ let C = null;
2971
+ if (this.connectorDrag) {
2972
+ let e = this.shadowRoot?.querySelector(".scroll-container");
2973
+ if (e) {
2974
+ let t = e.getBoundingClientRect(), n = this.connectorDrag.startX, a = this.connectorDrag.startY, o, s;
2975
+ if (this.connectorDrag.targetTaskId && this.connectorDrag.targetEndpoint) {
2976
+ let n = r.get(this.connectorDrag.targetTaskId);
2977
+ n ? (o = this.connectorDrag.targetEndpoint === "start" ? n.x : n.x + n.width, s = n.y + n.height / 2) : (o = this.connectorDrag.currentClientX - t.left + e.scrollLeft, s = this.connectorDrag.currentClientY - t.top + e.scrollTop - this.calendarHeight);
2978
+ } else o = this.connectorDrag.currentClientX - t.left + e.scrollLeft, s = this.connectorDrag.currentClientY - t.top + e.scrollTop - this.calendarHeight;
2979
+ let c = (n + o) / 2;
2980
+ C = i`<path class="connector-preview-line" d="M ${n} ${a} C ${c} ${a} ${c} ${s} ${o} ${s}" />`;
2981
+ }
2982
+ }
2983
+ return n`
2984
+ <style>${J(this.theme, this.option.customTheme)}</style>
2985
+ ${this.isExporting ? n`<style>:host { overflow: visible !important; height: ${this.calendarHeight + a + 2}px !important; width: max-content !important; min-width: auto !important; }</style>` : ""}
2986
+ <div
2987
+ class="scroll-container"
2988
+ style="overflow-x: ${this.isExporting ? "visible" : "auto"}; overflow-y: ${this.isExporting ? "visible" : g ? "auto" : "hidden"}; height: ${this.isExporting ? "auto" : "100%"}; width: ${this.isExporting ? "max-content" : "100%"}; min-width: auto;"
2989
+ @scroll="${this.handleScroll}"
2990
+ @bar-mouseenter="${this.handleBarMouseEnter}"
2991
+ @bar-mouseleave="${this.handleBarMouseLeave}"
2992
+ @dragover="${this.handleContainerDragOver}"
2993
+ @dragleave="${this.handleContainerDragLeave}"
2994
+ @drop="${this.handleContainerDrop}"
2995
+ @click="${this.handleContainerClick}"
2996
+ @contextmenu="${this.handleContainerContextMenu}"
2997
+ @mousemove="${this.handleContainerMouseMove}"
2998
+ @mouseleave="${this.handleContainerMouseLeave}"
2999
+ @connector-drag-start="${this.handleConnectorDragStart}"
3000
+ @connector-drag-move="${this.handleConnectorDragMove}"
3001
+ @connector-drag-end="${this.handleConnectorDragEnd}"
3002
+ >
3003
+ ${this.option.rowHeader?.resizable === !1 ? "" : n`
3004
+ <div
3005
+ style="
3006
+ position: sticky;
3007
+ left: ${o - 2}px;
3008
+ top: 0;
3009
+ width: 0;
3010
+ height: 0;
3011
+ z-index: 510;
3012
+ overflow: visible;
3013
+ "
3014
+ >
3015
+ <div
3016
+ class="header-resizer ${this.isResizingHeader ? "resizing" : ""}"
3017
+ style="height: ${this.isExporting ? a : Math.max(a, this.viewportHeight)}px;"
3018
+ @pointerdown="${this.handleHeaderResizeStart}"
3019
+ ></div>
3020
+ </div>
3021
+ `}
3022
+ <gantt-calendar
3023
+ id="calendar"
3024
+ .option="${s}"
3025
+ .theme="${this.theme}"
3026
+ .currentTime="${this.currentTime}"
3027
+ .hoveredMilestoneId="${this.hoveredMilestoneId}"
3028
+ .cornerContent="${this.option.customRendering?.cornerContent}"
3029
+ .calendarMonthContent="${this.option.customRendering?.calendarMonthContent}"
3030
+ .calendarDayContent="${this.option.customRendering?.calendarDayContent}"
3031
+ .calendarWeekContent="${this.option.customRendering?.calendarWeekContent}"
3032
+ .calendarHourContent="${this.option.customRendering?.calendarHourContent}"
3033
+ @milestone-hover-change="${(e) => {
3034
+ this.hoveredMilestoneId = e.detail.milestoneId;
3035
+ }}"
3036
+ ></gantt-calendar>
3037
+
3038
+ <svg
3039
+ class="dependency-lines"
3040
+ style="top: 0;"
3041
+ width="${this.getDateX(this.option.calendar.end) + o}"
3042
+ height="${a + this.calendarHeight}"
3043
+ >
3044
+ ${y ? i`<defs>
3045
+ <marker
3046
+ id="dependency-arrowhead"
3047
+ markerWidth="${b}"
3048
+ markerHeight="${b}"
3049
+ refX="${b}"
3050
+ refY="${b / 2}"
3051
+ orient="auto"
3052
+ markerUnits="userSpaceOnUse"
3053
+ >
3054
+ <polygon
3055
+ points="0 0, ${b} ${b / 2}, 0 ${b}"
3056
+ fill="${e.dependencyLine}"
3057
+ class="dependency-arrowhead-fill"
3058
+ />
3059
+ </marker>
3060
+ </defs>` : ""}
3061
+ <g transform="translate(0, ${this.calendarHeight})">
3062
+ ${_}
3063
+ ${C}
3064
+ </g>
3065
+ </svg>
3066
+
3067
+ ${this.option.calendar.showCurrentTime && this.currentTime >= this.option.calendar.start && this.currentTime <= this.option.calendar.end ? n`
3068
+ <div
3069
+ class="current-time-line"
3070
+ style="
3071
+ top: ${this.calendarHeight}px;
3072
+ left: ${this.getDateX(this.currentTime) + o}px;
3073
+ height: ${a}px;
3074
+ background-color: ${e.currentTimeLine};
3075
+ "
3076
+ ></div>
3077
+ <div
3078
+ class="current-time-dot"
3079
+ style="
3080
+ top: ${this.calendarHeight + 3}px;
3081
+ left: ${this.getDateX(this.currentTime) + o + 1}px;
3082
+ background-color: ${e.currentTimeLine};
3083
+ "
3084
+ ></div>
3085
+ ` : ""}
3086
+ ${(this.option.calendar.milestones ?? []).map((e) => n`
3087
+ <div
3088
+ class="milestone-line"
3089
+ style="
3090
+ top: ${this.calendarHeight}px;
3091
+ left: ${this.getDateX(e.start) + o}px;
3092
+ height: ${a}px;
3093
+ width: ${e.width ?? 2}px;
3094
+ background-color: ${e.color};
3095
+ opacity: ${this.hoveredMilestoneId === e.id ? 1 : .5};
3096
+ ${e.style ?? ""}
3097
+ "
3098
+ @mouseenter="${() => {
3099
+ this.hoveredMilestoneId = e.id;
3100
+ }}"
3101
+ @mouseleave="${() => {
3102
+ this.hoveredMilestoneId = null;
3103
+ }}"
3104
+ ></div>
3105
+ `)}
3106
+ ${this.option.calendar.showCursorLine && this.cursorLineX !== null ? n`
3107
+ <div
3108
+ class="cursor-line"
3109
+ style="
3110
+ left: ${this.cursorLineX}px;
3111
+ height: ${this.calendarHeight + (this.isExporting ? a : a || this.viewportHeight)}px;
3112
+ background-color: ${this.option.calendar.cursorLineColor ?? e.currentTimeLine};
3113
+ "
3114
+ ></div>
3115
+ ` : ""}
3116
+
3117
+ <div style="height: ${f}px; width: 1px;"></div>
3118
+
3119
+ ${u(d, (e) => e.id, (e, t) => {
3120
+ let r = c + t;
3121
+ return n`
3122
+ <gantt-row
3123
+ .row="${e}"
3124
+ .option="${s}"
3125
+ .isSelected="${this.selectedRows.has(e.id)}"
3126
+ .isDragTarget="${this.dragTargetRowIndex === r || this.dragOverRowId === e.id && this.dragOverPosition === null}"
3127
+ .draggingTask="${this.draggingTask}"
3128
+ .draggingTaskIds="${this.draggingTaskIds}"
3129
+ .multiDragDx="${this.multiDragDx}"
3130
+ .theme="${this.theme}"
3131
+ .dropPosition="${this.dragOverRowId === e.id ? this.dragOverPosition : null}"
3132
+ .externalDragTask="${this.dragPreview?.rowId === e.id ? this.dragPreview : null}"
3133
+ .selectedTaskIds="${this._cachedSelectedTaskIds}"
3134
+ .focusedTaskId="${this.focusedTaskId}"
3135
+ .isExporting="${this.isExporting}"
3136
+ @task-update="${this.handleTaskUpdate}"
3137
+ @row-clicked="${this.handleRowClicked}"
3138
+ @row-header-contextmenu="${this.handleRowContextMenu}"
3139
+ @bar-click="${this.handleBarClick}"
3140
+ @task-contextmenu="${this.handleBarContextMenu}"
3141
+ />
3142
+ `;
3143
+ })}
3144
+
3145
+ <div style="height: ${h}px; width: 1px;"></div>
3146
+ </div>
3147
+
3148
+ ${this.option.showDragInfoOverlay === !1 ? "" : n` <div class="drag-info-overlay"></div> `}
3149
+ ${this.tooltip ? n`
3150
+ <div
3151
+ class="tooltip ${this.tooltip.visible ? "visible" : ""}"
3152
+ style="top: ${this.tooltip.y}px; left: ${this.tooltip.x}px;"
3153
+ />
3154
+ ` : ""}
3155
+ `;
3156
+ }
3157
+ };
3158
+ V([s({ type: Array })], Z.prototype, "rows", void 0), V([s({ type: Object })], Z.prototype, "option", void 0), V([s({
3159
+ type: String,
3160
+ reflect: !0
3161
+ })], Z.prototype, "theme", void 0), V([s({ type: Array })], Z.prototype, "selectedRowIds", void 0), V([s({ type: Array })], Z.prototype, "selectedTaskIds", void 0), V([s({ attribute: !1 })], Z.prototype, "externalDraggingTask", void 0), V([c()], Z.prototype, "selectedRows", void 0), V([c()], Z.prototype, "selectedTasks", void 0), V([c()], Z.prototype, "lastClickedRowId", void 0), V([c()], Z.prototype, "virtualScrollTop", void 0), V([c()], Z.prototype, "dragTargetRowIndex", void 0), V([c()], Z.prototype, "draggingTask", void 0), V([c()], Z.prototype, "draggingTaskIds", void 0), V([c()], Z.prototype, "multiDragDx", void 0), V([c()], Z.prototype, "viewportHeight", void 0), V([c()], Z.prototype, "calendarHeight", void 0), V([c()], Z.prototype, "tooltip", void 0), V([c()], Z.prototype, "dragOverRowId", void 0), V([c()], Z.prototype, "dragOverPosition", void 0), V([c()], Z.prototype, "currentTime", void 0), V([c()], Z.prototype, "dragPreview", void 0), V([c()], Z.prototype, "currentRowHeaderWidth", void 0), V([c()], Z.prototype, "isResizingHeader", void 0), V([c()], Z.prototype, "hoveredMilestoneId", void 0), V([c()], Z.prototype, "cursorLineX", void 0), V([c()], Z.prototype, "connectorDrag", void 0), V([c()], Z.prototype, "isExporting", void 0), V([c()], Z.prototype, "focusedTaskId", void 0), V([c()], Z.prototype, "focusedRowId", void 0), Z = V([o("gantt-chart")], Z);
3162
+ //#endregion
3163
+ export { h as ALL_BAR_PATTERNS, H as GanttBarElement, U as GanttCalendarElement, Z as GanttChartElement, G as GanttRowElement, b as PATTERN_CHECKERBOARD, C as PATTERN_CIRCLE, T as PATTERN_DIAGONAL_GRID, g as PATTERN_DIAGONAL_STRIPE, _ as PATTERN_DIAGONAL_STRIPE_REVERSE, x as PATTERN_DOTS, O as PATTERN_DOTS_DENSE, w as PATTERN_GRID, y as PATTERN_HORIZONTAL_STRIPE, D as PATTERN_STRIPE_THICK, E as PATTERN_STRIPE_THIN, S as PATTERN_TRIANGLE, v as PATTERN_VERTICAL_STRIPE, j as enLocale, k as getPatternStyle, A as jaLocale };