@workiom/frappe-gantt 1.0.5

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,1760 @@
1
+ const M = "year", D = "month", T = "day", L = "hour", Y = "minute", A = "second", H = "millisecond", d = {
2
+ parse_duration(r) {
3
+ const e = /([0-9]+)(y|m|d|h|min|s|ms)/gm.exec(r);
4
+ if (e !== null) {
5
+ if (e[2] === "y")
6
+ return { duration: parseInt(e[1]), scale: "year" };
7
+ if (e[2] === "m")
8
+ return { duration: parseInt(e[1]), scale: "month" };
9
+ if (e[2] === "d")
10
+ return { duration: parseInt(e[1]), scale: "day" };
11
+ if (e[2] === "h")
12
+ return { duration: parseInt(e[1]), scale: "hour" };
13
+ if (e[2] === "min")
14
+ return { duration: parseInt(e[1]), scale: "minute" };
15
+ if (e[2] === "s")
16
+ return { duration: parseInt(e[1]), scale: "second" };
17
+ if (e[2] === "ms")
18
+ return { duration: parseInt(e[1]), scale: "millisecond" };
19
+ }
20
+ },
21
+ parse(r, t = "-", e = /[.:]/) {
22
+ if (r instanceof Date)
23
+ return r;
24
+ if (typeof r == "string") {
25
+ let i, s;
26
+ const n = r.split(" ");
27
+ i = n[0].split(t).map((o) => parseInt(o, 10)), s = n[1] && n[1].split(e), i[1] = i[1] ? i[1] - 1 : 0;
28
+ let a = i;
29
+ return s && s.length && (s.length === 4 && (s[3] = "0." + s[3], s[3] = parseFloat(s[3]) * 1e3), a = a.concat(s)), new Date(...a);
30
+ }
31
+ },
32
+ to_string(r, t = !1) {
33
+ if (!(r instanceof Date))
34
+ throw new TypeError("Invalid argument type");
35
+ const e = this.get_date_values(r).map((n, a) => (a === 1 && (n = n + 1), a === 6 ? v(n + "", 3, "0") : v(n + "", 2, "0"))), i = `${e[0]}-${e[1]}-${e[2]}`, s = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
36
+ return i + (t ? " " + s : "");
37
+ },
38
+ format(r, t = "YYYY-MM-DD HH:mm:ss.SSS", e = "en") {
39
+ const i = new Intl.DateTimeFormat(e, {
40
+ month: "long"
41
+ }), s = new Intl.DateTimeFormat(e, {
42
+ month: "short"
43
+ }), n = i.format(r), a = n.charAt(0).toUpperCase() + n.slice(1), o = this.get_date_values(r).map((l) => v(l, 2, 0)), h = {
44
+ YYYY: o[0],
45
+ MM: v(+o[1] + 1, 2, 0),
46
+ DD: o[2],
47
+ HH: o[3],
48
+ mm: o[4],
49
+ ss: o[5],
50
+ SSS: o[6],
51
+ D: o[2],
52
+ MMMM: a,
53
+ MMM: s.format(r)
54
+ };
55
+ let _ = t;
56
+ const g = [];
57
+ return Object.keys(h).sort((l, c) => c.length - l.length).forEach((l) => {
58
+ _.includes(l) && (_ = _.replaceAll(l, `$${g.length}`), g.push(h[l]));
59
+ }), g.forEach((l, c) => {
60
+ _ = _.replaceAll(`$${c}`, l);
61
+ }), _;
62
+ },
63
+ diff(r, t, e = "day") {
64
+ let i, s, n, a, o, h, _;
65
+ i = r - t + (t.getTimezoneOffset() - r.getTimezoneOffset()) * 6e4, s = i / 1e3, a = s / 60, n = a / 60, o = n / 24;
66
+ let g = r.getFullYear() - t.getFullYear(), l = r.getMonth() - t.getMonth();
67
+ return l += o % 30 / 30, h = g * 12 + l, r.getDate() < t.getDate() && h--, _ = h / 12, e.endsWith("s") || (e += "s"), Math.round(
68
+ {
69
+ milliseconds: i,
70
+ seconds: s,
71
+ minutes: a,
72
+ hours: n,
73
+ days: o,
74
+ months: h,
75
+ years: _
76
+ }[e] * 100
77
+ ) / 100;
78
+ },
79
+ today() {
80
+ const r = this.get_date_values(/* @__PURE__ */ new Date()).slice(0, 3);
81
+ return new Date(...r);
82
+ },
83
+ now() {
84
+ return /* @__PURE__ */ new Date();
85
+ },
86
+ add(r, t, e) {
87
+ t = parseInt(t, 10);
88
+ const i = [
89
+ r.getFullYear() + (e === M ? t : 0),
90
+ r.getMonth() + (e === D ? t : 0),
91
+ r.getDate() + (e === T ? t : 0),
92
+ r.getHours() + (e === L ? t : 0),
93
+ r.getMinutes() + (e === Y ? t : 0),
94
+ r.getSeconds() + (e === A ? t : 0),
95
+ r.getMilliseconds() + (e === H ? t : 0)
96
+ ];
97
+ return new Date(...i);
98
+ },
99
+ start_of(r, t) {
100
+ const e = {
101
+ [M]: 6,
102
+ [D]: 5,
103
+ [T]: 4,
104
+ [L]: 3,
105
+ [Y]: 2,
106
+ [A]: 1,
107
+ [H]: 0
108
+ };
109
+ function i(n) {
110
+ const a = e[t];
111
+ return e[n] <= a;
112
+ }
113
+ const s = [
114
+ r.getFullYear(),
115
+ i(M) ? 0 : r.getMonth(),
116
+ i(D) ? 1 : r.getDate(),
117
+ i(T) ? 0 : r.getHours(),
118
+ i(L) ? 0 : r.getMinutes(),
119
+ i(Y) ? 0 : r.getSeconds(),
120
+ i(A) ? 0 : r.getMilliseconds()
121
+ ];
122
+ return new Date(...s);
123
+ },
124
+ clone(r) {
125
+ return new Date(...this.get_date_values(r));
126
+ },
127
+ get_date_values(r) {
128
+ return [
129
+ r.getFullYear(),
130
+ r.getMonth(),
131
+ r.getDate(),
132
+ r.getHours(),
133
+ r.getMinutes(),
134
+ r.getSeconds(),
135
+ r.getMilliseconds()
136
+ ];
137
+ },
138
+ convert_scales(r, t) {
139
+ const e = {
140
+ millisecond: 11574074074074074e-24,
141
+ second: 11574074074074073e-21,
142
+ minute: 6944444444444445e-19,
143
+ hour: 0.041666666666666664,
144
+ day: 1,
145
+ month: 30,
146
+ year: 365
147
+ }, { duration: i, scale: s } = this.parse_duration(r);
148
+ return i * e[s] / e[t];
149
+ },
150
+ get_days_in_month(r) {
151
+ const t = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], e = r.getMonth();
152
+ if (e !== 1)
153
+ return t[e];
154
+ const i = r.getFullYear();
155
+ return i % 4 === 0 && i % 100 != 0 || i % 400 === 0 ? 29 : 28;
156
+ },
157
+ get_days_in_year(r) {
158
+ return r.getFullYear() % 4 ? 365 : 366;
159
+ }
160
+ };
161
+ function v(r, t, e) {
162
+ return r = r + "", t = t >> 0, e = String(typeof e < "u" ? e : " "), r.length > t ? String(r) : (t = t - r.length, t > e.length && (e += e.repeat(t / e.length)), e.slice(0, t) + String(r));
163
+ }
164
+ function p(r, t) {
165
+ return typeof r == "string" ? (t || document).querySelector(r) : r || null;
166
+ }
167
+ function f(r, t) {
168
+ const e = document.createElementNS("http://www.w3.org/2000/svg", r);
169
+ for (let i in t)
170
+ i === "append_to" ? t.append_to.appendChild(e) : i === "innerHTML" ? e.innerHTML = t.innerHTML : i === "clipPath" ? e.setAttribute("clip-path", "url(#" + t[i] + ")") : e.setAttribute(i, t[i]);
171
+ return e;
172
+ }
173
+ function E(r, t, e, i) {
174
+ const s = W(r, t, e, i);
175
+ if (s === r) {
176
+ const n = document.createEvent("HTMLEvents");
177
+ n.initEvent("click", !0, !0), n.eventName = "click", s.dispatchEvent(n);
178
+ }
179
+ }
180
+ function W(r, t, e, i, s = "0.4s", n = "0.1s") {
181
+ const a = r.querySelector("animate");
182
+ if (a)
183
+ return p.attr(a, {
184
+ attributeName: t,
185
+ from: e,
186
+ to: i,
187
+ dur: s,
188
+ begin: "click + " + n
189
+ // artificial click
190
+ }), r;
191
+ const o = f("animate", {
192
+ attributeName: t,
193
+ from: e,
194
+ to: i,
195
+ dur: s,
196
+ begin: n,
197
+ calcMode: "spline",
198
+ values: e + ";" + i,
199
+ keyTimes: "0; 1",
200
+ keySplines: C("ease-out")
201
+ });
202
+ return r.appendChild(o), r;
203
+ }
204
+ function C(r) {
205
+ return {
206
+ ease: ".25 .1 .25 1",
207
+ linear: "0 0 1 1",
208
+ "ease-in": ".42 0 1 1",
209
+ "ease-out": "0 0 .58 1",
210
+ "ease-in-out": ".42 0 .58 1"
211
+ }[r];
212
+ }
213
+ p.on = (r, t, e, i) => {
214
+ i ? p.delegate(r, t, e, i) : (i = e, p.bind(r, t, i));
215
+ };
216
+ p.off = (r, t, e) => {
217
+ r.removeEventListener(t, e);
218
+ };
219
+ p.bind = (r, t, e) => {
220
+ t.split(/\s+/).forEach(function(i) {
221
+ r.addEventListener(i, e);
222
+ });
223
+ };
224
+ p.delegate = (r, t, e, i) => {
225
+ r.addEventListener(t, function(s) {
226
+ const n = s.target.closest(e);
227
+ n && (s.delegatedTarget = n, i.call(this, s, n));
228
+ });
229
+ };
230
+ p.closest = (r, t) => t ? t.matches(r) ? t : p.closest(r, t.parentNode) : null;
231
+ p.attr = (r, t, e) => {
232
+ if (!e && typeof t == "string")
233
+ return r.getAttribute(t);
234
+ if (typeof t == "object") {
235
+ for (let i in t)
236
+ p.attr(r, i, t[i]);
237
+ return;
238
+ }
239
+ r.setAttribute(t, e);
240
+ };
241
+ class q {
242
+ constructor(t, e, i) {
243
+ this.gantt = t, this.from_task = e, this.to_task = i, this.calculate_path(), this.draw();
244
+ }
245
+ calculate_path() {
246
+ let t = this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;
247
+ const e = () => this.to_task.$bar.getX() < t + this.gantt.options.padding && t > this.from_task.$bar.getX() + this.gantt.options.padding;
248
+ for (; e(); )
249
+ t -= 10;
250
+ t -= 10;
251
+ let i = this.gantt.config.header_height + this.gantt.options.bar_height + (this.gantt.options.padding + this.gantt.options.bar_height) * this.from_task.task._index + this.gantt.options.padding / 2, s = this.to_task.$bar.getX() - 13, n = this.gantt.config.header_height + this.gantt.options.bar_height / 2 + (this.gantt.options.padding + this.gantt.options.bar_height) * this.to_task.task._index + this.gantt.options.padding / 2;
252
+ const a = this.from_task.task._index > this.to_task.task._index;
253
+ let o = this.gantt.options.arrow_curve;
254
+ const h = a ? 1 : 0;
255
+ let _ = a ? -o : o;
256
+ if (this.to_task.$bar.getX() <= this.from_task.$bar.getX() + this.gantt.options.padding) {
257
+ let g = this.gantt.options.padding / 2 - o;
258
+ g < 0 && (g = 0, o = this.gantt.options.padding / 2, _ = a ? -o : o);
259
+ const l = this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - _, c = this.to_task.$bar.getX() - this.gantt.options.padding;
260
+ this.path = `
261
+ M ${t} ${i}
262
+ v ${g}
263
+ a ${o} ${o} 0 0 1 ${-o} ${o}
264
+ H ${c}
265
+ a ${o} ${o} 0 0 ${h} ${-o} ${_}
266
+ V ${l}
267
+ a ${o} ${o} 0 0 ${h} ${o} ${_}
268
+ L ${s} ${n}
269
+ m -5 -5
270
+ l 5 5
271
+ l -5 5`;
272
+ } else {
273
+ s < t + o && (o = s - t);
274
+ let g = a ? n + o : n - o;
275
+ this.path = `
276
+ M ${t} ${i}
277
+ V ${g}
278
+ a ${o} ${o} 0 0 ${h} ${o} ${o}
279
+ L ${s} ${n}
280
+ m -5 -5
281
+ l 5 5
282
+ l -5 5`;
283
+ }
284
+ }
285
+ draw() {
286
+ this.element = f("path", {
287
+ d: this.path,
288
+ "data-from": this.from_task.task.id,
289
+ "data-to": this.to_task.task.id
290
+ });
291
+ }
292
+ update() {
293
+ this.calculate_path(), this.element.setAttribute("d", this.path);
294
+ }
295
+ }
296
+ class F {
297
+ constructor(t, e) {
298
+ this.set_defaults(t, e), this.prepare_wrappers(), this.prepare_helpers(), this.refresh();
299
+ }
300
+ refresh() {
301
+ this.bar_group.innerHTML = "", this.handle_group.innerHTML = "", this.task.custom_class ? this.group.classList.add(this.task.custom_class) : this.group.classList = ["bar-wrapper"], this.prepare_values(), this.draw(), this.bind();
302
+ }
303
+ set_defaults(t, e) {
304
+ this.action_completed = !1, this.gantt = t, this.task = e, this.name = this.name || "";
305
+ }
306
+ prepare_wrappers() {
307
+ this.group = f("g", {
308
+ class: "bar-wrapper" + (this.task.custom_class ? " " + this.task.custom_class : ""),
309
+ "data-id": this.task.id
310
+ }), this.bar_group = f("g", {
311
+ class: "bar-group",
312
+ append_to: this.group
313
+ }), this.handle_group = f("g", {
314
+ class: "handle-group",
315
+ append_to: this.group
316
+ });
317
+ }
318
+ prepare_values() {
319
+ this.invalid = this.task.invalid, this.height = this.gantt.options.bar_height, this.image_size = this.height - 5, this.task._start = new Date(this.task.start), this.task._end = new Date(this.task.end), this.compute_x(), this.compute_y(), this.compute_duration(), this.corner_radius = this.gantt.options.bar_corner_radius, this.width = this.gantt.config.column_width * this.duration, (!this.task.progress || this.task.progress < 0) && (this.task.progress = 0), this.task.progress > 100 && (this.task.progress = 100);
320
+ }
321
+ prepare_helpers() {
322
+ SVGElement.prototype.getX = function() {
323
+ return +this.getAttribute("x");
324
+ }, SVGElement.prototype.getY = function() {
325
+ return +this.getAttribute("y");
326
+ }, SVGElement.prototype.getWidth = function() {
327
+ return +this.getAttribute("width");
328
+ }, SVGElement.prototype.getHeight = function() {
329
+ return +this.getAttribute("height");
330
+ }, SVGElement.prototype.getEndX = function() {
331
+ return this.getX() + this.getWidth();
332
+ };
333
+ }
334
+ prepare_expected_progress_values() {
335
+ this.compute_expected_progress(), this.expected_progress_width = this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0;
336
+ }
337
+ draw() {
338
+ this.draw_bar(), this.draw_progress_bar(), this.gantt.options.show_expected_progress && (this.prepare_expected_progress_values(), this.draw_expected_progress_bar()), this.draw_label(), this.draw_resize_handles(), this.task.thumbnail && this.draw_thumbnail();
339
+ }
340
+ draw_bar() {
341
+ this.$bar = f("rect", {
342
+ x: this.x,
343
+ y: this.y,
344
+ width: this.width,
345
+ height: this.height,
346
+ rx: this.corner_radius,
347
+ ry: this.corner_radius,
348
+ class: "bar",
349
+ append_to: this.bar_group
350
+ }), this.task.color && (this.$bar.style.fill = this.task.color), E(this.$bar, "width", 0, this.width), this.invalid && this.$bar.classList.add("bar-invalid");
351
+ }
352
+ draw_expected_progress_bar() {
353
+ this.invalid || (this.$expected_bar_progress = f("rect", {
354
+ x: this.x,
355
+ y: this.y,
356
+ width: this.expected_progress_width,
357
+ height: this.height,
358
+ rx: this.corner_radius,
359
+ ry: this.corner_radius,
360
+ class: "bar-expected-progress",
361
+ append_to: this.bar_group
362
+ }), E(
363
+ this.$expected_bar_progress,
364
+ "width",
365
+ 0,
366
+ this.expected_progress_width
367
+ ));
368
+ }
369
+ draw_progress_bar() {
370
+ if (this.invalid) return;
371
+ this.progress_width = this.calculate_progress_width();
372
+ let t = this.corner_radius;
373
+ /^((?!chrome|android).)*safari/i.test(navigator.userAgent) || (t = this.corner_radius + 2), this.$bar_progress = f("rect", {
374
+ x: this.x,
375
+ y: this.y,
376
+ width: this.progress_width,
377
+ height: this.height,
378
+ rx: t,
379
+ ry: t,
380
+ class: "bar-progress",
381
+ append_to: this.bar_group
382
+ }), this.task.color_progress && (this.$bar_progress.style.fill = this.task.color_progress);
383
+ const e = d.diff(
384
+ this.task._start,
385
+ this.gantt.gantt_start,
386
+ this.gantt.config.unit
387
+ ) / this.gantt.config.step * this.gantt.config.column_width;
388
+ let i = this.gantt.create_el({
389
+ classes: `date-range-highlight hide highlight-${this.task.id}`,
390
+ width: this.width,
391
+ left: e
392
+ });
393
+ this.$date_highlight = i, this.gantt.$lower_header.prepend(this.$date_highlight), E(this.$bar_progress, "width", 0, this.progress_width);
394
+ }
395
+ calculate_progress_width() {
396
+ const t = this.$bar.getWidth(), e = this.x + t, i = this.gantt.config.ignored_positions.reduce((h, _) => h + (_ >= this.x && _ < e), 0) * this.gantt.config.column_width;
397
+ let s = (t - i) * this.task.progress / 100;
398
+ const n = this.x + s, a = this.gantt.config.ignored_positions.reduce((h, _) => h + (_ >= this.x && _ < n), 0) * this.gantt.config.column_width;
399
+ s += a;
400
+ let o = this.gantt.get_ignored_region(
401
+ this.x + s
402
+ );
403
+ for (; o.length; )
404
+ s += this.gantt.config.column_width, o = this.gantt.get_ignored_region(
405
+ this.x + s
406
+ );
407
+ return this.progress_width = s, s;
408
+ }
409
+ draw_label() {
410
+ let t = this.x + this.$bar.getWidth() / 2;
411
+ this.task.thumbnail && (t = this.x + this.image_size + 5), f("text", {
412
+ x: t,
413
+ y: this.y + this.height / 2,
414
+ innerHTML: this.task.name,
415
+ class: "bar-label",
416
+ append_to: this.bar_group
417
+ }), requestAnimationFrame(() => this.update_label_position());
418
+ }
419
+ draw_thumbnail() {
420
+ let t = 10, e = 2, i, s;
421
+ i = f("defs", {
422
+ append_to: this.bar_group
423
+ }), f("rect", {
424
+ id: "rect_" + this.task.id,
425
+ x: this.x + t,
426
+ y: this.y + e,
427
+ width: this.image_size,
428
+ height: this.image_size,
429
+ rx: "15",
430
+ class: "img_mask",
431
+ append_to: i
432
+ }), s = f("clipPath", {
433
+ id: "clip_" + this.task.id,
434
+ append_to: i
435
+ }), f("use", {
436
+ href: "#rect_" + this.task.id,
437
+ append_to: s
438
+ }), f("image", {
439
+ x: this.x + t,
440
+ y: this.y + e,
441
+ width: this.image_size,
442
+ height: this.image_size,
443
+ class: "bar-img",
444
+ href: this.task.thumbnail,
445
+ clipPath: "clip_" + this.task.id,
446
+ append_to: this.bar_group
447
+ });
448
+ }
449
+ draw_resize_handles() {
450
+ if (this.invalid || this.gantt.options.readonly) return;
451
+ const t = this.$bar, e = 3;
452
+ if (this.handles = [], this.gantt.options.readonly_dates || (this.handles.push(
453
+ f("rect", {
454
+ x: t.getEndX() - e / 2,
455
+ y: t.getY() + this.height / 4,
456
+ width: e,
457
+ height: this.height / 2,
458
+ rx: 2,
459
+ ry: 2,
460
+ class: "handle right",
461
+ append_to: this.handle_group
462
+ })
463
+ ), this.handles.push(
464
+ f("rect", {
465
+ x: t.getX() - e / 2,
466
+ y: t.getY() + this.height / 4,
467
+ width: e,
468
+ height: this.height / 2,
469
+ rx: 2,
470
+ ry: 2,
471
+ class: "handle left",
472
+ append_to: this.handle_group
473
+ })
474
+ )), !this.gantt.options.readonly_progress) {
475
+ const i = this.$bar_progress;
476
+ this.$handle_progress = f("circle", {
477
+ cx: i.getEndX(),
478
+ cy: i.getY() + i.getHeight() / 2,
479
+ r: 4.5,
480
+ class: "handle progress",
481
+ append_to: this.handle_group
482
+ }), this.handles.push(this.$handle_progress);
483
+ }
484
+ for (let i of this.handles)
485
+ p.on(i, "mouseenter", () => i.classList.add("active")), p.on(i, "mouseleave", () => i.classList.remove("active"));
486
+ }
487
+ bind() {
488
+ this.invalid || this.setup_click_event();
489
+ }
490
+ setup_click_event() {
491
+ let t = this.task.id;
492
+ p.on(this.group, "mouseover", (s) => {
493
+ this.gantt.trigger_event("hover", [
494
+ this.task,
495
+ s.screenX,
496
+ s.screenY,
497
+ s
498
+ ]);
499
+ }), this.gantt.options.popup_on === "click" && p.on(this.group, "mouseup", (s) => {
500
+ const n = s.offsetX || s.layerX;
501
+ if (this.$handle_progress) {
502
+ const a = +this.$handle_progress.getAttribute("cx");
503
+ if (a > n - 1 && a < n + 1 || this.gantt.bar_being_dragged) return;
504
+ }
505
+ this.gantt.show_popup({
506
+ x: s.offsetX || s.layerX,
507
+ y: s.offsetY || s.layerY,
508
+ task: this.task,
509
+ target: this.$bar
510
+ });
511
+ });
512
+ let e;
513
+ p.on(this.group, "mouseenter", (s) => {
514
+ e = setTimeout(() => {
515
+ this.gantt.options.popup_on === "hover" && this.gantt.show_popup({
516
+ x: s.offsetX || s.layerX,
517
+ y: s.offsetY || s.layerY,
518
+ task: this.task,
519
+ target: this.$bar
520
+ }), this.gantt.$container.querySelector(`.highlight-${t}`).classList.remove("hide");
521
+ }, 200);
522
+ }), p.on(this.group, "mouseleave", () => {
523
+ var s, n;
524
+ clearTimeout(e), this.gantt.options.popup_on === "hover" && ((n = (s = this.gantt.popup) == null ? void 0 : s.hide) == null || n.call(s)), this.gantt.$container.querySelector(`.highlight-${t}`).classList.add("hide");
525
+ }), p.on(this.group, "click", () => {
526
+ this.gantt.trigger_event("click", [this.task]);
527
+ }), p.on(this.group, "dblclick", (s) => {
528
+ this.action_completed || (this.group.classList.remove("active"), this.gantt.popup && this.gantt.popup.parent.classList.remove("hide"), this.gantt.trigger_event("double_click", [this.task]));
529
+ });
530
+ let i = !1;
531
+ p.on(this.group, "touchstart", (s) => {
532
+ if (!i)
533
+ return i = !0, setTimeout(function() {
534
+ i = !1;
535
+ }, 300), !1;
536
+ s.preventDefault(), !this.action_completed && (this.group.classList.remove("active"), this.gantt.popup && this.gantt.popup.parent.classList.remove("hide"), this.gantt.trigger_event("double_click", [this.task]));
537
+ });
538
+ }
539
+ update_bar_position({ x: t = null, width: e = null }) {
540
+ const i = this.$bar;
541
+ if (t) {
542
+ if (!this.validate_dependency_constraints(t, e))
543
+ return;
544
+ this.update_attr(i, "x", t), this.x = t, this.$date_highlight.style.left = t + "px";
545
+ }
546
+ e > 0 && (this.update_attr(i, "width", e), this.$date_highlight.style.width = e + "px"), this.update_label_position(), this.update_handle_position(), this.date_changed(), this.compute_duration(), this.gantt.options.show_expected_progress && this.update_expected_progressbar_position(), this.update_progressbar_position(), this.update_arrow_position();
547
+ }
548
+ validate_dependency_constraints(t, e = null) {
549
+ const i = this.task.dependencies_type || this.gantt.options.dependencies_type;
550
+ if (i === "fixed")
551
+ return this.task.dependencies.map((g) => this.gantt.get_bar(g).$bar.getX()).reduce((g, l) => g && t >= l, !0);
552
+ const s = t / this.gantt.config.column_width, n = d.add(
553
+ this.gantt.gantt_start,
554
+ s * this.gantt.config.step,
555
+ this.gantt.config.unit
556
+ ), o = (e || this.$bar.getWidth()) / this.gantt.config.column_width, h = d.add(
557
+ n,
558
+ o * this.gantt.config.step,
559
+ this.gantt.config.unit
560
+ );
561
+ for (const _ of this.task.dependencies) {
562
+ const g = this.gantt.get_bar(_);
563
+ if (!g) continue;
564
+ const l = g.task;
565
+ switch (i) {
566
+ case "finish-to-start":
567
+ if (n < l._end)
568
+ return !1;
569
+ break;
570
+ case "start-to-start":
571
+ if (n < l._start)
572
+ return !1;
573
+ break;
574
+ case "finish-to-finish":
575
+ if (h < l._end)
576
+ return !1;
577
+ break;
578
+ case "start-to-finish":
579
+ if (h < l._start)
580
+ return !1;
581
+ break;
582
+ }
583
+ }
584
+ return !0;
585
+ }
586
+ update_label_position_on_horizontal_scroll({ x: t, sx: e }) {
587
+ const i = this.gantt.$container, s = this.group.querySelector(".bar-label"), n = this.group.querySelector(".bar-img") || "", a = this.bar_group.querySelector(".img_mask") || "";
588
+ let o = this.$bar.getX() + this.$bar.getWidth(), h = s.getX() + t, _ = n && n.getX() + t || 0, g = n && n.getBBox().width + 7 || 7, l = h + s.getBBox().width + 7, c = e + i.clientWidth / 2;
589
+ s.classList.contains("big") || (l < o && t > 0 && l < c || h - g > this.$bar.getX() && t < 0 && l > c) && (s.setAttribute("x", h), n && (n.setAttribute("x", _), a.setAttribute("x", _)));
590
+ }
591
+ date_changed() {
592
+ let t = !1;
593
+ const { new_start_date: e, new_end_date: i } = this.compute_start_end_date();
594
+ Number(this.task._start) !== Number(e) && (t = !0, this.task._start = e), Number(this.task._end) !== Number(i) && (t = !0, this.task._end = i), t && this.gantt.trigger_event("date_change", [
595
+ this.task,
596
+ e,
597
+ d.add(i, -1, "second")
598
+ ]);
599
+ }
600
+ progress_changed() {
601
+ this.task.progress = this.compute_progress(), this.gantt.trigger_event("progress_change", [
602
+ this.task,
603
+ this.task.progress
604
+ ]);
605
+ }
606
+ set_action_completed() {
607
+ this.action_completed = !0, setTimeout(() => this.action_completed = !1, 1e3);
608
+ }
609
+ compute_start_end_date() {
610
+ const t = this.$bar, e = t.getX() / this.gantt.config.column_width;
611
+ let i = d.add(
612
+ this.gantt.gantt_start,
613
+ e * this.gantt.config.step,
614
+ this.gantt.config.unit
615
+ );
616
+ const s = t.getWidth() / this.gantt.config.column_width, n = d.add(
617
+ i,
618
+ s * this.gantt.config.step,
619
+ this.gantt.config.unit
620
+ );
621
+ return { new_start_date: i, new_end_date: n };
622
+ }
623
+ compute_progress() {
624
+ this.progress_width = this.$bar_progress.getWidth(), this.x = this.$bar_progress.getBBox().x;
625
+ const t = this.x + this.progress_width, e = this.progress_width - this.gantt.config.ignored_positions.reduce((s, n) => s + (n >= this.x && n <= t), 0) * this.gantt.config.column_width;
626
+ if (e < 0) return 0;
627
+ const i = this.$bar.getWidth() - this.ignored_duration_raw * this.gantt.config.column_width;
628
+ return parseInt(e / i * 100, 10);
629
+ }
630
+ compute_expected_progress() {
631
+ this.expected_progress = d.diff(d.today(), this.task._start, "hour") / this.gantt.config.step, this.expected_progress = (this.expected_progress < this.duration ? this.expected_progress : this.duration) * 100 / this.duration;
632
+ }
633
+ compute_x() {
634
+ const { column_width: t } = this.gantt.config, e = this.task._start, i = this.gantt.gantt_start;
635
+ let n = d.diff(e, i, this.gantt.config.unit) / this.gantt.config.step * t;
636
+ this.x = n;
637
+ }
638
+ compute_y() {
639
+ this.y = this.gantt.config.header_height + this.gantt.options.padding / 2 + this.task._index * (this.height + this.gantt.options.padding);
640
+ }
641
+ compute_duration() {
642
+ let t = 0, e = 0;
643
+ for (let i = new Date(this.task._start); i < this.task._end; i.setDate(i.getDate() + 1))
644
+ e++, !this.gantt.config.ignored_dates.find(
645
+ (s) => s.getTime() === i.getTime()
646
+ ) && (!this.gantt.config.ignored_function || !this.gantt.config.ignored_function(i)) && t++;
647
+ this.task.actual_duration = t, this.task.ignored_duration = e - t, this.duration = d.convert_scales(
648
+ e + "d",
649
+ this.gantt.config.unit
650
+ ) / this.gantt.config.step, this.actual_duration_raw = d.convert_scales(
651
+ t + "d",
652
+ this.gantt.config.unit
653
+ ) / this.gantt.config.step, this.ignored_duration_raw = this.duration - this.actual_duration_raw;
654
+ }
655
+ update_attr(t, e, i) {
656
+ return i = +i, isNaN(i) || t.setAttribute(e, i), t;
657
+ }
658
+ update_expected_progressbar_position() {
659
+ this.invalid || (this.$expected_bar_progress.setAttribute("x", this.$bar.getX()), this.compute_expected_progress(), this.$expected_bar_progress.setAttribute(
660
+ "width",
661
+ this.gantt.config.column_width * this.actual_duration_raw * (this.expected_progress / 100) || 0
662
+ ));
663
+ }
664
+ update_progressbar_position() {
665
+ this.invalid || this.gantt.options.readonly || (this.$bar_progress.setAttribute("x", this.$bar.getX()), this.$bar_progress.setAttribute(
666
+ "width",
667
+ this.calculate_progress_width()
668
+ ));
669
+ }
670
+ update_label_position() {
671
+ const t = this.bar_group.querySelector(".img_mask") || "", e = this.$bar, i = this.group.querySelector(".bar-label"), s = this.group.querySelector(".bar-img");
672
+ let n = 5, a = this.image_size + 10;
673
+ const o = i.getBBox().width, h = e.getWidth();
674
+ o > h ? (i.classList.add("big"), s ? (s.setAttribute("x", e.getEndX() + n), t.setAttribute("x", e.getEndX() + n), i.setAttribute("x", e.getEndX() + a)) : i.setAttribute("x", e.getEndX() + n)) : (i.classList.remove("big"), s ? (s.setAttribute("x", e.getX() + n), t.setAttribute("x", e.getX() + n), i.setAttribute(
675
+ "x",
676
+ e.getX() + h / 2 + a
677
+ )) : i.setAttribute(
678
+ "x",
679
+ e.getX() + h / 2 - o / 2
680
+ ));
681
+ }
682
+ update_handle_position() {
683
+ if (this.invalid || this.gantt.options.readonly) return;
684
+ const t = this.$bar;
685
+ this.handle_group.querySelector(".handle.left").setAttribute("x", t.getX()), this.handle_group.querySelector(".handle.right").setAttribute("x", t.getEndX());
686
+ const e = this.group.querySelector(".handle.progress");
687
+ e && e.setAttribute("cx", this.$bar_progress.getEndX());
688
+ }
689
+ update_arrow_position() {
690
+ this.arrows = this.arrows || [];
691
+ for (let t of this.arrows)
692
+ t.update();
693
+ }
694
+ }
695
+ class O {
696
+ constructor(t, e, i) {
697
+ this.parent = t, this.popup_func = e, this.gantt = i, this.make();
698
+ }
699
+ make() {
700
+ this.parent.innerHTML = `
701
+ <div class="title"></div>
702
+ <div class="subtitle"></div>
703
+ <div class="details"></div>
704
+ <div class="actions"></div>
705
+ `, this.hide(), this.title = this.parent.querySelector(".title"), this.subtitle = this.parent.querySelector(".subtitle"), this.details = this.parent.querySelector(".details"), this.actions = this.parent.querySelector(".actions");
706
+ }
707
+ show({ x: t, y: e, task: i, target: s }) {
708
+ this.actions.innerHTML = "";
709
+ let n = this.popup_func({
710
+ task: i,
711
+ chart: this.gantt,
712
+ get_title: () => this.title,
713
+ set_title: (a) => this.title.innerHTML = a,
714
+ get_subtitle: () => this.subtitle,
715
+ set_subtitle: (a) => this.subtitle.innerHTML = a,
716
+ get_details: () => this.details,
717
+ set_details: (a) => this.details.innerHTML = a,
718
+ add_action: (a, o) => {
719
+ let h = this.gantt.create_el({
720
+ classes: "action-btn",
721
+ type: "button",
722
+ append_to: this.actions
723
+ });
724
+ typeof a == "function" && (a = a(i)), h.innerHTML = a, h.onclick = (_) => o(i, this.gantt, _);
725
+ }
726
+ });
727
+ n !== !1 && (n && (this.parent.innerHTML = n), this.actions.innerHTML === "" ? this.actions.remove() : this.parent.appendChild(this.actions), this.parent.style.left = t + 10 + "px", this.parent.style.top = e - 10 + "px", this.parent.classList.remove("hide"));
728
+ }
729
+ hide() {
730
+ this.parent.classList.add("hide");
731
+ }
732
+ }
733
+ function S(r) {
734
+ const t = r.getFullYear();
735
+ return t - t % 10 + "";
736
+ }
737
+ function I(r, t, e) {
738
+ let i = d.add(r, 6, "day"), s = i.getMonth() !== r.getMonth() ? "D MMM" : "D", n = !t || r.getMonth() !== t.getMonth() ? "D MMM" : "D";
739
+ return `${d.format(r, n, e)} - ${d.format(i, s, e)}`;
740
+ }
741
+ const y = [
742
+ {
743
+ name: "Hour",
744
+ padding: "7d",
745
+ step: "1h",
746
+ date_format: "YYYY-MM-DD HH:",
747
+ lower_text: "HH",
748
+ upper_text: (r, t, e) => !t || r.getDate() !== t.getDate() ? d.format(r, "D MMMM", e) : "",
749
+ upper_text_frequency: 24
750
+ },
751
+ {
752
+ name: "Quarter Day",
753
+ padding: "7d",
754
+ step: "6h",
755
+ date_format: "YYYY-MM-DD HH:",
756
+ lower_text: "HH",
757
+ upper_text: (r, t, e) => !t || r.getDate() !== t.getDate() ? d.format(r, "D MMM", e) : "",
758
+ upper_text_frequency: 4
759
+ },
760
+ {
761
+ name: "Half Day",
762
+ padding: "14d",
763
+ step: "12h",
764
+ date_format: "YYYY-MM-DD HH:",
765
+ lower_text: "HH",
766
+ upper_text: (r, t, e) => !t || r.getDate() !== t.getDate() ? r.getMonth() !== r.getMonth() ? d.format(r, "D MMM", e) : d.format(r, "D", e) : "",
767
+ upper_text_frequency: 2
768
+ },
769
+ {
770
+ name: "Day",
771
+ padding: "7d",
772
+ date_format: "YYYY-MM-DD",
773
+ step: "1d",
774
+ lower_text: (r, t, e) => !t || r.getDate() !== t.getDate() ? d.format(r, "D", e) : "",
775
+ upper_text: (r, t, e) => !t || r.getMonth() !== t.getMonth() ? d.format(r, "MMMM", e) : "",
776
+ thick_line: (r) => r.getDay() === 1
777
+ },
778
+ {
779
+ name: "Week",
780
+ padding: "1m",
781
+ step: "7d",
782
+ date_format: "YYYY-MM-DD",
783
+ column_width: 140,
784
+ lower_text: I,
785
+ upper_text: (r, t, e) => !t || r.getMonth() !== t.getMonth() ? d.format(r, "MMMM", e) : "",
786
+ thick_line: (r) => r.getDate() >= 1 && r.getDate() <= 7,
787
+ upper_text_frequency: 4
788
+ },
789
+ {
790
+ name: "Month",
791
+ padding: "2m",
792
+ step: "1m",
793
+ column_width: 120,
794
+ date_format: "YYYY-MM",
795
+ lower_text: "MMMM",
796
+ upper_text: (r, t, e) => !t || r.getFullYear() !== t.getFullYear() ? d.format(r, "YYYY", e) : "",
797
+ thick_line: (r) => r.getMonth() % 3 === 0,
798
+ snap_at: "7d"
799
+ },
800
+ {
801
+ name: "Year",
802
+ padding: "2y",
803
+ step: "1y",
804
+ column_width: 120,
805
+ date_format: "YYYY",
806
+ upper_text: (r, t, e) => !t || S(r) !== S(t) ? S(r) : "",
807
+ lower_text: "YYYY",
808
+ snap_at: "30d"
809
+ }
810
+ ], z = {
811
+ arrow_curve: 5,
812
+ auto_move_label: !1,
813
+ bar_corner_radius: 3,
814
+ bar_height: 30,
815
+ container_height: "auto",
816
+ column_width: null,
817
+ date_format: "YYYY-MM-DD HH:mm",
818
+ dependencies_type: "fixed",
819
+ upper_header_height: 45,
820
+ lower_header_height: 30,
821
+ snap_at: null,
822
+ infinite_padding: !0,
823
+ holidays: { "var(--g-weekend-highlight-color)": "weekend" },
824
+ ignore: [],
825
+ language: "en",
826
+ lines: "both",
827
+ move_dependencies: !0,
828
+ padding: 18,
829
+ popup: (r) => {
830
+ r.set_title(r.task.name), r.task.description ? r.set_subtitle(r.task.description) : r.set_subtitle("");
831
+ const t = d.format(
832
+ r.task._start,
833
+ "MMM D",
834
+ r.chart.options.language
835
+ ), e = d.format(
836
+ d.add(r.task._end, -1, "second"),
837
+ "MMM D",
838
+ r.chart.options.language
839
+ );
840
+ r.set_details(
841
+ `${t} - ${e} (${r.task.actual_duration} days${r.task.ignored_duration ? " + " + r.task.ignored_duration + " excluded" : ""})<br/>Progress: ${Math.floor(r.task.progress * 100) / 100}%`
842
+ );
843
+ },
844
+ popup_on: "click",
845
+ readonly_progress: !1,
846
+ readonly_dates: !1,
847
+ readonly: !1,
848
+ scroll_to: "today",
849
+ show_expected_progress: !1,
850
+ today_button: !0,
851
+ view_mode: "Day",
852
+ view_mode_select: !1,
853
+ view_modes: y,
854
+ is_weekend: (r) => r.getDay() === 0 || r.getDay() === 6
855
+ };
856
+ class B {
857
+ constructor(t, e, i) {
858
+ this.setup_wrapper(t), this.setup_options(i), this.setup_tasks(e), this.change_view_mode(), this.bind_events();
859
+ }
860
+ setup_wrapper(t) {
861
+ let e, i;
862
+ if (typeof t == "string") {
863
+ let s = document.querySelector(t);
864
+ if (!s)
865
+ throw new ReferenceError(
866
+ `CSS selector "${t}" could not be found in DOM`
867
+ );
868
+ t = s;
869
+ }
870
+ if (t instanceof HTMLElement)
871
+ i = t, e = t.querySelector("svg");
872
+ else if (t instanceof SVGElement)
873
+ e = t;
874
+ else
875
+ throw new TypeError(
876
+ "Frappe Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter"
877
+ );
878
+ e ? (this.$svg = e, this.$svg.classList.add("gantt")) : this.$svg = f("svg", {
879
+ append_to: i,
880
+ class: "gantt"
881
+ }), this.$container = this.create_el({
882
+ classes: "gantt-container",
883
+ append_to: this.$svg.parentElement
884
+ }), this.$container.appendChild(this.$svg), this.$popup_wrapper = this.create_el({
885
+ classes: "popup-wrapper",
886
+ append_to: this.$container
887
+ });
888
+ }
889
+ setup_options(t) {
890
+ this.original_options = t, t != null && t.view_modes && (t.view_modes = t.view_modes.map((i) => {
891
+ if (typeof i == "string") {
892
+ const s = y.find(
893
+ (n) => n.name === i
894
+ );
895
+ return s || console.error(
896
+ `The view mode "${i}" is not predefined in Frappe Gantt. Please define the view mode object instead.`
897
+ ), s;
898
+ }
899
+ return i;
900
+ }), t.view_mode = t.view_modes[0]), this.options = { ...z, ...t };
901
+ const e = {
902
+ "grid-height": "container_height",
903
+ "bar-height": "bar_height",
904
+ "lower-header-height": "lower_header_height",
905
+ "upper-header-height": "upper_header_height"
906
+ };
907
+ for (let i in e) {
908
+ let s = this.options[e[i]];
909
+ s !== "auto" && this.$container.style.setProperty(
910
+ "--gv-" + i,
911
+ s + "px"
912
+ );
913
+ }
914
+ if (this.config = {
915
+ ignored_dates: [],
916
+ ignored_positions: [],
917
+ extend_by_units: 10
918
+ }, typeof this.options.ignore != "function") {
919
+ typeof this.options.ignore == "string" && (this.options.ignore = [this.options.ignore]);
920
+ for (let i of this.options.ignore) {
921
+ if (typeof i == "function") {
922
+ this.config.ignored_function = i;
923
+ continue;
924
+ }
925
+ typeof i == "string" && (i === "weekend" ? this.config.ignored_function = (s) => s.getDay() == 6 || s.getDay() == 0 : this.config.ignored_dates.push(/* @__PURE__ */ new Date(i + " ")));
926
+ }
927
+ } else
928
+ this.config.ignored_function = this.options.ignore;
929
+ }
930
+ update_options(t) {
931
+ this.setup_options({ ...this.original_options, ...t }), this.change_view_mode(void 0, !0);
932
+ }
933
+ setup_tasks(t) {
934
+ this.tasks = t.map((e, i) => {
935
+ if (!e.start)
936
+ return console.error(
937
+ `task "${e.id}" doesn't have a start date`
938
+ ), !1;
939
+ if (e._start = d.parse(e.start), e.end === void 0 && e.duration !== void 0 && (e.end = e._start, e.duration.split(" ").forEach((o) => {
940
+ let { duration: h, scale: _ } = d.parse_duration(o);
941
+ e.end = d.add(e.end, h, _);
942
+ })), !e.end)
943
+ return console.error(`task "${e.id}" doesn't have an end date`), !1;
944
+ if (e._end = d.parse(e.end), d.diff(e._end, e._start, "year") < 0)
945
+ return console.error(
946
+ `start of task can't be after end of task: in task "${e.id}"`
947
+ ), !1;
948
+ if (d.diff(e._end, e._start, "year") > 10)
949
+ return console.error(
950
+ `the duration of task "${e.id}" is too long (above ten years)`
951
+ ), !1;
952
+ if (e._index = i, d.get_date_values(e._end).slice(3).every((a) => a === 0) && (e._end = d.add(e._end, 24, "hour")), typeof e.dependencies == "string" || !e.dependencies) {
953
+ let a = [];
954
+ e.dependencies && (a = e.dependencies.split(",").map((o) => o.trim().replaceAll(" ", "_")).filter((o) => o)), e.dependencies = a;
955
+ }
956
+ return e.id ? typeof e.id == "string" ? e.id = e.id.replaceAll(" ", "_") : e.id = `${e.id}` : e.id = j(e), e;
957
+ }).filter((e) => e), this.setup_dependencies();
958
+ }
959
+ setup_dependencies() {
960
+ this.dependency_map = {};
961
+ for (let t of this.tasks)
962
+ for (let e of t.dependencies)
963
+ this.dependency_map[e] = this.dependency_map[e] || [], this.dependency_map[e].push(t.id);
964
+ }
965
+ refresh(t) {
966
+ this.setup_tasks(t), this.change_view_mode();
967
+ }
968
+ update_task(t, e) {
969
+ let i = this.tasks.find((n) => n.id === t), s = this.bars[i._index];
970
+ Object.assign(i, e), s.refresh();
971
+ }
972
+ change_view_mode(t = this.options.view_mode, e = !1) {
973
+ typeof t == "string" && (t = this.options.view_modes.find((n) => n.name === t));
974
+ let i, s;
975
+ e && (i = this.$container.scrollLeft, s = this.options.scroll_to, this.options.scroll_to = null), this.options.view_mode = t.name, this.config.view_mode = t, this.update_view_scale(t), this.setup_dates(e), this.render(), e && (this.$container.scrollLeft = i, this.options.scroll_to = s), this.trigger_event("view_change", [t]);
976
+ }
977
+ update_view_scale(t) {
978
+ let { duration: e, scale: i } = d.parse_duration(t.step);
979
+ this.config.step = e, this.config.unit = i, this.config.column_width = this.options.column_width || t.column_width || 45, this.$container.style.setProperty(
980
+ "--gv-column-width",
981
+ this.config.column_width + "px"
982
+ ), this.config.header_height = this.options.lower_header_height + this.options.upper_header_height + 10;
983
+ }
984
+ setup_dates(t = !1) {
985
+ this.setup_gantt_dates(t), this.setup_date_values();
986
+ }
987
+ setup_gantt_dates(t) {
988
+ let e, i;
989
+ this.tasks.length || (e = /* @__PURE__ */ new Date(), i = /* @__PURE__ */ new Date());
990
+ for (let s of this.tasks)
991
+ (!e || s._start < e) && (e = s._start), (!i || s._end > i) && (i = s._end);
992
+ if (e = d.start_of(e, this.config.unit), i = d.start_of(i, this.config.unit), !t)
993
+ if (this.options.infinite_padding)
994
+ this.gantt_start = d.add(
995
+ e,
996
+ -this.config.extend_by_units * 3,
997
+ this.config.unit
998
+ ), this.gantt_end = d.add(
999
+ i,
1000
+ this.config.extend_by_units * 3,
1001
+ this.config.unit
1002
+ );
1003
+ else {
1004
+ typeof this.config.view_mode.padding == "string" && (this.config.view_mode.padding = [
1005
+ this.config.view_mode.padding,
1006
+ this.config.view_mode.padding
1007
+ ]);
1008
+ let [s, n] = this.config.view_mode.padding.map(
1009
+ d.parse_duration
1010
+ );
1011
+ this.gantt_start = d.add(
1012
+ e,
1013
+ -s.duration,
1014
+ s.scale
1015
+ ), this.gantt_end = d.add(
1016
+ i,
1017
+ n.duration,
1018
+ n.scale
1019
+ );
1020
+ }
1021
+ this.config.date_format = this.config.view_mode.date_format || this.options.date_format, this.gantt_start.setHours(0, 0, 0, 0);
1022
+ }
1023
+ setup_date_values() {
1024
+ let t = this.gantt_start;
1025
+ for (this.dates = [t]; t < this.gantt_end; )
1026
+ t = d.add(
1027
+ t,
1028
+ this.config.step,
1029
+ this.config.unit
1030
+ ), this.dates.push(t);
1031
+ }
1032
+ bind_events() {
1033
+ this.bind_grid_click(), this.bind_holiday_labels(), this.bind_bar_events();
1034
+ }
1035
+ render() {
1036
+ this.clear(), this.setup_layers(), this.make_grid(), this.make_dates(), this.make_grid_extras(), this.make_bars(), this.make_arrows(), this.map_arrows_on_bars(), this.set_dimensions(), this.set_scroll_position(this.options.scroll_to);
1037
+ }
1038
+ setup_layers() {
1039
+ this.layers = {};
1040
+ const t = ["grid", "arrow", "progress", "bar"];
1041
+ for (let e of t)
1042
+ this.layers[e] = f("g", {
1043
+ class: e,
1044
+ append_to: this.$svg
1045
+ });
1046
+ this.$extras = this.create_el({
1047
+ classes: "extras",
1048
+ append_to: this.$container
1049
+ }), this.$adjust = this.create_el({
1050
+ classes: "adjust hide",
1051
+ append_to: this.$extras,
1052
+ type: "button"
1053
+ }), this.$adjust.innerHTML = "&larr;";
1054
+ }
1055
+ make_grid() {
1056
+ this.make_grid_background(), this.make_grid_rows(), this.make_grid_header(), this.make_side_header();
1057
+ }
1058
+ make_grid_extras() {
1059
+ this.make_grid_highlights(), this.make_grid_ticks();
1060
+ }
1061
+ make_grid_background() {
1062
+ const t = this.dates.length * this.config.column_width, e = Math.max(
1063
+ this.config.header_height + this.options.padding + (this.options.bar_height + this.options.padding) * this.tasks.length - 10,
1064
+ this.options.container_height !== "auto" ? this.options.container_height : 0
1065
+ );
1066
+ f("rect", {
1067
+ x: 0,
1068
+ y: 0,
1069
+ width: t,
1070
+ height: e,
1071
+ class: "grid-background",
1072
+ append_to: this.$svg
1073
+ }), p.attr(this.$svg, {
1074
+ height: e,
1075
+ width: "100%"
1076
+ }), this.grid_height = e, this.options.container_height === "auto" && (this.$container.style.height = e + "px");
1077
+ }
1078
+ make_grid_rows() {
1079
+ const t = f("g", { append_to: this.layers.grid }), e = this.dates.length * this.config.column_width, i = this.options.bar_height + this.options.padding;
1080
+ this.config.header_height;
1081
+ for (let s = this.config.header_height; s < this.grid_height; s += i)
1082
+ f("rect", {
1083
+ x: 0,
1084
+ y: s,
1085
+ width: e,
1086
+ height: i,
1087
+ class: "grid-row",
1088
+ append_to: t
1089
+ });
1090
+ }
1091
+ make_grid_header() {
1092
+ this.$header = this.create_el({
1093
+ width: this.dates.length * this.config.column_width,
1094
+ classes: "grid-header",
1095
+ append_to: this.$container
1096
+ }), this.$upper_header = this.create_el({
1097
+ classes: "upper-header",
1098
+ append_to: this.$header
1099
+ }), this.$lower_header = this.create_el({
1100
+ classes: "lower-header",
1101
+ append_to: this.$header
1102
+ });
1103
+ }
1104
+ make_side_header() {
1105
+ if (this.$side_header = this.create_el({ classes: "side-header" }), this.$upper_header.prepend(this.$side_header), this.options.view_mode_select) {
1106
+ const t = document.createElement("select");
1107
+ t.classList.add("viewmode-select");
1108
+ const e = document.createElement("option");
1109
+ e.selected = !0, e.disabled = !0, e.textContent = "Mode", t.appendChild(e);
1110
+ for (const i of this.options.view_modes) {
1111
+ const s = document.createElement("option");
1112
+ s.value = i.name, s.textContent = i.name, i.name === this.config.view_mode.name && (s.selected = !0), t.appendChild(s);
1113
+ }
1114
+ t.addEventListener(
1115
+ "change",
1116
+ (function() {
1117
+ this.change_view_mode(t.value, !0);
1118
+ }).bind(this)
1119
+ ), this.$side_header.appendChild(t);
1120
+ }
1121
+ if (this.options.today_button) {
1122
+ let t = document.createElement("button");
1123
+ t.classList.add("today-button"), t.textContent = "Today", t.onclick = this.scroll_current.bind(this), this.$side_header.prepend(t), this.$today_button = t;
1124
+ }
1125
+ }
1126
+ make_grid_ticks() {
1127
+ if (this.options.lines === "none") return;
1128
+ let t = 0, e = this.config.header_height, i = this.grid_height - this.config.header_height, s = f("g", {
1129
+ class: "lines_layer",
1130
+ append_to: this.layers.grid
1131
+ }), n = this.config.header_height;
1132
+ const a = this.dates.length * this.config.column_width, o = this.options.bar_height + this.options.padding;
1133
+ if (this.options.lines !== "vertical")
1134
+ for (let h = this.config.header_height; h < this.grid_height; h += o)
1135
+ f("line", {
1136
+ x1: 0,
1137
+ y1: n + o,
1138
+ x2: a,
1139
+ y2: n + o,
1140
+ class: "row-line",
1141
+ append_to: s
1142
+ }), n += o;
1143
+ if (this.options.lines !== "horizontal")
1144
+ for (let h of this.dates) {
1145
+ let _ = "tick";
1146
+ this.config.view_mode.thick_line && this.config.view_mode.thick_line(h) && (_ += " thick"), f("path", {
1147
+ d: `M ${t} ${e} v ${i}`,
1148
+ class: _,
1149
+ append_to: this.layers.grid
1150
+ }), this.view_is("month") ? t += d.get_days_in_month(h) * this.config.column_width / 30 : this.view_is("year") ? t += d.get_days_in_year(h) * this.config.column_width / 365 : t += this.config.column_width;
1151
+ }
1152
+ }
1153
+ highlight_holidays() {
1154
+ let t = {};
1155
+ if (this.options.holidays)
1156
+ for (let e in this.options.holidays) {
1157
+ let i = this.options.holidays[e];
1158
+ i === "weekend" && (i = this.options.is_weekend);
1159
+ let s;
1160
+ if (typeof i == "object") {
1161
+ let n = i.find((a) => typeof a == "function");
1162
+ if (n && (s = n), this.options.holidays.name) {
1163
+ let a = /* @__PURE__ */ new Date(i.date + " ");
1164
+ i = (o) => a.getTime() === o.getTime(), t[a] = i.name;
1165
+ } else
1166
+ i = (a) => this.options.holidays[e].filter((o) => typeof o != "function").map((o) => {
1167
+ if (o.name) {
1168
+ let h = /* @__PURE__ */ new Date(o.date + " ");
1169
+ return t[h] = o.name, h.getTime();
1170
+ }
1171
+ return (/* @__PURE__ */ new Date(o + " ")).getTime();
1172
+ }).includes(a.getTime());
1173
+ }
1174
+ for (let n = new Date(this.gantt_start); n <= this.gantt_end; n.setDate(n.getDate() + 1))
1175
+ if (!(this.config.ignored_dates.find(
1176
+ (a) => a.getTime() == n.getTime()
1177
+ ) || this.config.ignored_function && this.config.ignored_function(n)) && (i(n) || s && s(n))) {
1178
+ const a = d.diff(
1179
+ n,
1180
+ this.gantt_start,
1181
+ this.config.unit
1182
+ ) / this.config.step * this.config.column_width, o = this.grid_height - this.config.header_height, h = d.format(n, "YYYY-MM-DD", this.options.language).replace(" ", "_");
1183
+ if (t[n]) {
1184
+ let _ = this.create_el({
1185
+ classes: "holiday-label label_" + h,
1186
+ append_to: this.$extras
1187
+ });
1188
+ _.textContent = t[n];
1189
+ }
1190
+ f("rect", {
1191
+ x: Math.round(a),
1192
+ y: this.config.header_height,
1193
+ width: this.config.column_width / d.convert_scales(
1194
+ this.config.view_mode.step,
1195
+ "day"
1196
+ ),
1197
+ height: o,
1198
+ class: "holiday-highlight " + h,
1199
+ style: `fill: ${e};`,
1200
+ append_to: this.layers.grid
1201
+ });
1202
+ }
1203
+ }
1204
+ }
1205
+ /**
1206
+ * Compute the horizontal x-axis distance and associated date for the current date and view.
1207
+ *
1208
+ * @returns Object containing the x-axis distance and date of the current date, or null if the current date is out of the gantt range.
1209
+ */
1210
+ highlight_current() {
1211
+ const t = this.get_closest_date();
1212
+ if (!t) return;
1213
+ const [e, i] = t;
1214
+ i.classList.add("current-date-highlight");
1215
+ const n = d.diff(
1216
+ /* @__PURE__ */ new Date(),
1217
+ this.gantt_start,
1218
+ this.config.unit
1219
+ ) / this.config.step * this.config.column_width;
1220
+ this.$current_highlight = this.create_el({
1221
+ top: this.config.header_height,
1222
+ left: n,
1223
+ height: this.grid_height - this.config.header_height,
1224
+ classes: "current-highlight",
1225
+ append_to: this.$container
1226
+ }), this.$current_ball_highlight = this.create_el({
1227
+ top: this.config.header_height - 6,
1228
+ left: n - 2.5,
1229
+ width: 6,
1230
+ height: 6,
1231
+ classes: "current-ball-highlight",
1232
+ append_to: this.$header
1233
+ });
1234
+ }
1235
+ make_grid_highlights() {
1236
+ this.highlight_holidays(), this.config.ignored_positions = [];
1237
+ const t = (this.options.bar_height + this.options.padding) * this.tasks.length;
1238
+ this.layers.grid.innerHTML += `<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
1239
+ <path d="M-1,1 l2,-2
1240
+ M0,4 l4,-4
1241
+ M3,5 l2,-2"
1242
+ style="stroke:grey; stroke-width:0.3" />
1243
+ </pattern>`;
1244
+ for (let i = new Date(this.gantt_start); i <= this.gantt_end; i.setDate(i.getDate() + 1)) {
1245
+ if (!this.config.ignored_dates.find(
1246
+ (n) => n.getTime() == i.getTime()
1247
+ ) && (!this.config.ignored_function || !this.config.ignored_function(i)))
1248
+ continue;
1249
+ let s = d.convert_scales(
1250
+ d.diff(i, this.gantt_start) + "d",
1251
+ this.config.unit
1252
+ ) / this.config.step;
1253
+ this.config.ignored_positions.push(s * this.config.column_width), f("rect", {
1254
+ x: s * this.config.column_width,
1255
+ y: this.config.header_height,
1256
+ width: this.config.column_width,
1257
+ height: t,
1258
+ class: "ignored-bar",
1259
+ style: "fill: url(#diagonalHatch);",
1260
+ append_to: this.$svg
1261
+ });
1262
+ }
1263
+ this.highlight_current(
1264
+ this.config.view_mode
1265
+ );
1266
+ }
1267
+ create_el({ left: t, top: e, width: i, height: s, id: n, classes: a, append_to: o, type: h }) {
1268
+ let _ = document.createElement(h || "div");
1269
+ for (let g of a.split(" ")) _.classList.add(g);
1270
+ return _.style.top = e + "px", _.style.left = t + "px", n && (_.id = n), i && (_.style.width = i + "px"), s && (_.style.height = s + "px"), o && o.appendChild(_), _;
1271
+ }
1272
+ make_dates() {
1273
+ this.get_dates_to_draw().forEach((t, e) => {
1274
+ if (t.lower_text) {
1275
+ let i = this.create_el({
1276
+ left: t.x,
1277
+ top: t.lower_y,
1278
+ classes: "lower-text date_" + k(t.formatted_date),
1279
+ append_to: this.$lower_header
1280
+ });
1281
+ i.innerText = t.lower_text;
1282
+ }
1283
+ if (t.upper_text) {
1284
+ let i = this.create_el({
1285
+ left: t.x,
1286
+ top: t.upper_y,
1287
+ classes: "upper-text",
1288
+ append_to: this.$upper_header
1289
+ });
1290
+ i.innerText = t.upper_text;
1291
+ }
1292
+ }), this.upperTexts = Array.from(
1293
+ this.$container.querySelectorAll(".upper-text")
1294
+ );
1295
+ }
1296
+ get_dates_to_draw() {
1297
+ let t = null;
1298
+ return this.dates.map((i, s) => {
1299
+ const n = this.get_date_info(i, t, s);
1300
+ return t = n, n;
1301
+ });
1302
+ }
1303
+ get_date_info(t, e) {
1304
+ let i = e ? e.date : null;
1305
+ this.config.column_width;
1306
+ const s = e ? e.x + e.column_width : 0;
1307
+ let n = this.config.view_mode.upper_text, a = this.config.view_mode.lower_text;
1308
+ return n ? typeof n == "string" && (this.config.view_mode.upper_text = (o) => d.format(o, n, this.options.language)) : this.config.view_mode.upper_text = () => "", a ? typeof a == "string" && (this.config.view_mode.lower_text = (o) => d.format(o, a, this.options.language)) : this.config.view_mode.lower_text = () => "", {
1309
+ date: t,
1310
+ formatted_date: k(
1311
+ d.format(
1312
+ t,
1313
+ this.config.date_format,
1314
+ this.options.language
1315
+ )
1316
+ ),
1317
+ column_width: this.config.column_width,
1318
+ x: s,
1319
+ upper_text: this.config.view_mode.upper_text(
1320
+ t,
1321
+ i,
1322
+ this.options.language
1323
+ ),
1324
+ lower_text: this.config.view_mode.lower_text(
1325
+ t,
1326
+ i,
1327
+ this.options.language
1328
+ ),
1329
+ upper_y: 17,
1330
+ lower_y: this.options.upper_header_height + 5
1331
+ };
1332
+ }
1333
+ make_bars() {
1334
+ this.bars = this.tasks.map((t) => {
1335
+ const e = new F(this, t);
1336
+ return this.layers.bar.appendChild(e.group), e;
1337
+ });
1338
+ }
1339
+ make_arrows() {
1340
+ this.arrows = [];
1341
+ for (let t of this.tasks) {
1342
+ let e = [];
1343
+ e = t.dependencies.map((i) => {
1344
+ const s = this.get_task(i);
1345
+ if (!s) return;
1346
+ const n = new q(
1347
+ this,
1348
+ this.bars[s._index],
1349
+ // from_task
1350
+ this.bars[t._index]
1351
+ // to_task
1352
+ );
1353
+ return this.layers.arrow.appendChild(n.element), n;
1354
+ }).filter(Boolean), this.arrows = this.arrows.concat(e);
1355
+ }
1356
+ }
1357
+ map_arrows_on_bars() {
1358
+ for (let t of this.bars)
1359
+ t.arrows = this.arrows.filter((e) => e.from_task.task.id === t.task.id || e.to_task.task.id === t.task.id);
1360
+ }
1361
+ set_dimensions() {
1362
+ const { width: t } = this.$svg.getBoundingClientRect(), e = this.$svg.querySelector(".grid .grid-row") ? this.$svg.querySelector(".grid .grid-row").getAttribute("width") : 0;
1363
+ t < e && this.$svg.setAttribute("width", e);
1364
+ }
1365
+ set_scroll_position(t) {
1366
+ if (this.options.infinite_padding && (!t || t === "start")) {
1367
+ let [a, ...o] = this.get_start_end_positions();
1368
+ this.$container.scrollLeft = a;
1369
+ return;
1370
+ }
1371
+ if (!t || t === "start")
1372
+ t = this.gantt_start;
1373
+ else if (t === "end")
1374
+ t = this.gantt_end;
1375
+ else {
1376
+ if (t === "today")
1377
+ return this.scroll_current();
1378
+ typeof t == "string" && (t = d.parse(t));
1379
+ }
1380
+ const i = d.diff(
1381
+ t,
1382
+ this.gantt_start,
1383
+ this.config.unit
1384
+ ) / this.config.step * this.config.column_width;
1385
+ this.$container.scrollTo({
1386
+ left: i - this.config.column_width / 6,
1387
+ behavior: "smooth"
1388
+ }), this.$current && this.$current.classList.remove("current-upper"), this.current_date = d.add(
1389
+ this.gantt_start,
1390
+ this.$container.scrollLeft / this.config.column_width,
1391
+ this.config.unit
1392
+ );
1393
+ let s = this.config.view_mode.upper_text(
1394
+ this.current_date,
1395
+ null,
1396
+ this.options.language
1397
+ ), n = this.upperTexts.find(
1398
+ (a) => a.textContent === s
1399
+ );
1400
+ this.current_date = d.add(
1401
+ this.gantt_start,
1402
+ (this.$container.scrollLeft + n.clientWidth) / this.config.column_width,
1403
+ this.config.unit
1404
+ ), s = this.config.view_mode.upper_text(
1405
+ this.current_date,
1406
+ null,
1407
+ this.options.language
1408
+ ), n = this.upperTexts.find((a) => a.textContent === s), n.classList.add("current-upper"), this.$current = n;
1409
+ }
1410
+ scroll_current() {
1411
+ let t = this.get_closest_date();
1412
+ t && this.set_scroll_position(t[0]);
1413
+ }
1414
+ get_closest_date() {
1415
+ let t = /* @__PURE__ */ new Date();
1416
+ if (t < this.gantt_start || t > this.gantt_end) return null;
1417
+ let e = /* @__PURE__ */ new Date(), i = this.$container.querySelector(
1418
+ ".date_" + k(
1419
+ d.format(
1420
+ e,
1421
+ this.config.date_format,
1422
+ this.options.language
1423
+ )
1424
+ )
1425
+ ), s = 0;
1426
+ for (; !i && s < this.config.step; )
1427
+ e = d.add(e, -1, this.config.unit), i = this.$container.querySelector(
1428
+ ".date_" + k(
1429
+ d.format(
1430
+ e,
1431
+ this.config.date_format,
1432
+ this.options.language
1433
+ )
1434
+ )
1435
+ ), s++;
1436
+ return [
1437
+ /* @__PURE__ */ new Date(
1438
+ d.format(
1439
+ e,
1440
+ this.config.date_format,
1441
+ this.options.language
1442
+ ) + " "
1443
+ ),
1444
+ i
1445
+ ];
1446
+ }
1447
+ bind_grid_click() {
1448
+ p.on(
1449
+ this.$container,
1450
+ "click",
1451
+ ".grid-row, .grid-header, .ignored-bar, .holiday-highlight",
1452
+ () => {
1453
+ this.unselect_all(), this.hide_popup();
1454
+ }
1455
+ );
1456
+ }
1457
+ bind_holiday_labels() {
1458
+ const t = this.$container.querySelectorAll(".holiday-highlight");
1459
+ for (let e of t) {
1460
+ const i = this.$container.querySelector(
1461
+ ".label_" + e.classList[1]
1462
+ );
1463
+ if (!i) continue;
1464
+ let s;
1465
+ e.onmouseenter = (n) => {
1466
+ s = setTimeout(() => {
1467
+ i.classList.add("show"), i.style.left = (n.offsetX || n.layerX) + "px", i.style.top = (n.offsetY || n.layerY) + "px";
1468
+ }, 300);
1469
+ }, e.onmouseleave = (n) => {
1470
+ clearTimeout(s), i.classList.remove("show");
1471
+ };
1472
+ }
1473
+ }
1474
+ get_start_end_positions() {
1475
+ if (!this.bars.length) return [0, 0, 0];
1476
+ let { x: t, width: e } = this.bars[0].group.getBBox(), i = t, s = t, n = t + e;
1477
+ return Array.prototype.forEach.call(this.bars, function({ group: a }, o) {
1478
+ let { x: h, width: _ } = a.getBBox();
1479
+ h < i && (i = h), h > s && (s = h), h + _ > n && (n = h + _);
1480
+ }), [i, s, n];
1481
+ }
1482
+ bind_bar_events() {
1483
+ let t = !1, e = 0, i = 0, s = !1, n = !1, a = null, o = [];
1484
+ this.bar_being_dragged = null;
1485
+ const h = () => t || s || n;
1486
+ this.$svg.onclick = (g) => {
1487
+ g.target.classList.contains("grid-row") && this.unselect_all();
1488
+ };
1489
+ let _ = 0;
1490
+ if (p.on(this.$svg, "mousemove", ".bar-wrapper, .handle", (g) => {
1491
+ this.bar_being_dragged === !1 && Math.abs((g.offsetX || g.layerX) - _) > 10 && (this.bar_being_dragged = !0);
1492
+ }), p.on(this.$svg, "mousedown", ".bar-wrapper, .handle", (g, l) => {
1493
+ const c = p.closest(".bar-wrapper", l);
1494
+ l.classList.contains("left") ? (s = !0, l.classList.add("visible")) : l.classList.contains("right") ? (n = !0, l.classList.add("visible")) : l.classList.contains("bar-wrapper") && (t = !0), this.popup && this.popup.hide(), e = g.offsetX || g.layerX, a = c.getAttribute("data-id");
1495
+ const $ = this.get_bar(a).task.dependencies_type || this.options.dependencies_type;
1496
+ let m;
1497
+ this.options.move_dependencies && $ === "fixed" ? m = [
1498
+ a,
1499
+ ...this.get_all_dependent_tasks(a)
1500
+ ] : m = [a], o = m.map((x) => this.get_bar(x)), this.bar_being_dragged = !1, _ = e, o.forEach((x) => {
1501
+ const w = x.$bar;
1502
+ w.ox = w.getX(), w.oy = w.getY(), w.owidth = w.getWidth(), w.finaldx = 0;
1503
+ });
1504
+ }), this.options.infinite_padding) {
1505
+ let g = !1;
1506
+ p.on(this.$container, "mousewheel", (l) => {
1507
+ let c = this.$container.scrollWidth / 2;
1508
+ if (!g && l.currentTarget.scrollLeft <= c) {
1509
+ let u = l.currentTarget.scrollLeft;
1510
+ g = !0, this.gantt_start = d.add(
1511
+ this.gantt_start,
1512
+ -this.config.extend_by_units,
1513
+ this.config.unit
1514
+ ), this.setup_date_values(), this.render(), l.currentTarget.scrollLeft = u + this.config.column_width * this.config.extend_by_units, setTimeout(() => g = !1, 300);
1515
+ }
1516
+ if (!g && l.currentTarget.scrollWidth - (l.currentTarget.scrollLeft + l.currentTarget.clientWidth) <= c) {
1517
+ let u = l.currentTarget.scrollLeft;
1518
+ g = !0, this.gantt_end = d.add(
1519
+ this.gantt_end,
1520
+ this.config.extend_by_units,
1521
+ this.config.unit
1522
+ ), this.setup_date_values(), this.render(), l.currentTarget.scrollLeft = u, setTimeout(() => g = !1, 300);
1523
+ }
1524
+ });
1525
+ }
1526
+ p.on(this.$container, "scroll", (g) => {
1527
+ let l = [];
1528
+ const c = this.bars.map(
1529
+ ({ group: b }) => b.getAttribute("data-id")
1530
+ );
1531
+ let u;
1532
+ i && (u = g.currentTarget.scrollLeft - i), this.current_date = d.add(
1533
+ this.gantt_start,
1534
+ g.currentTarget.scrollLeft / this.config.column_width * this.config.step,
1535
+ this.config.unit
1536
+ );
1537
+ let $ = this.config.view_mode.upper_text(
1538
+ this.current_date,
1539
+ null,
1540
+ this.options.language
1541
+ ), m = this.upperTexts.find(
1542
+ (b) => b.textContent === $
1543
+ );
1544
+ this.current_date = d.add(
1545
+ this.gantt_start,
1546
+ (g.currentTarget.scrollLeft + m.clientWidth) / this.config.column_width * this.config.step,
1547
+ this.config.unit
1548
+ ), $ = this.config.view_mode.upper_text(
1549
+ this.current_date,
1550
+ null,
1551
+ this.options.language
1552
+ ), m = this.upperTexts.find(
1553
+ (b) => b.textContent === $
1554
+ ), m !== this.$current && (this.$current && this.$current.classList.remove("current-upper"), m.classList.add("current-upper"), this.$current = m), i = g.currentTarget.scrollLeft;
1555
+ let [x, w, X] = this.get_start_end_positions();
1556
+ i > X + 100 ? (this.$adjust.innerHTML = "&larr;", this.$adjust.classList.remove("hide"), this.$adjust.onclick = () => {
1557
+ this.$container.scrollTo({
1558
+ left: w,
1559
+ behavior: "smooth"
1560
+ });
1561
+ }) : i + g.currentTarget.offsetWidth < x - 100 ? (this.$adjust.innerHTML = "&rarr;", this.$adjust.classList.remove("hide"), this.$adjust.onclick = () => {
1562
+ this.$container.scrollTo({
1563
+ left: x,
1564
+ behavior: "smooth"
1565
+ });
1566
+ }) : this.$adjust.classList.add("hide"), u && (l = c.map((b) => this.get_bar(b)), this.options.auto_move_label && l.forEach((b) => {
1567
+ b.update_label_position_on_horizontal_scroll({
1568
+ x: u,
1569
+ sx: g.currentTarget.scrollLeft
1570
+ });
1571
+ }));
1572
+ }), p.on(this.$svg, "mousemove", (g) => {
1573
+ if (!h()) return;
1574
+ const l = (g.offsetX || g.layerX) - e;
1575
+ o.forEach((c) => {
1576
+ const u = c.$bar;
1577
+ u.finaldx = this.get_snap_position(l, u.ox), this.hide_popup(), s ? a === c.task.id ? c.update_bar_position({
1578
+ x: u.ox + u.finaldx,
1579
+ width: u.owidth - u.finaldx
1580
+ }) : c.update_bar_position({
1581
+ x: u.ox + u.finaldx
1582
+ }) : n ? a === c.task.id && c.update_bar_position({
1583
+ width: u.owidth + u.finaldx
1584
+ }) : t && !this.options.readonly && !this.options.readonly_dates && c.update_bar_position({ x: u.ox + u.finaldx });
1585
+ });
1586
+ }), document.addEventListener("mouseup", () => {
1587
+ var g, l, c;
1588
+ t = !1, s = !1, n = !1, (c = (l = (g = this.$container.querySelector(".visible")) == null ? void 0 : g.classList) == null ? void 0 : l.remove) == null || c.call(l, "visible");
1589
+ }), p.on(this.$svg, "mouseup", (g) => {
1590
+ this.bar_being_dragged = null, o.forEach((c) => {
1591
+ c.$bar.finaldx && (c.date_changed(), c.compute_progress(), c.set_action_completed());
1592
+ });
1593
+ const l = this.get_bar(a);
1594
+ l && l.$bar.finaldx && this.update_dependent_tasks_by_type(l);
1595
+ }), this.bind_bar_progress();
1596
+ }
1597
+ bind_bar_progress() {
1598
+ let t = 0, e = null, i = null, s = null, n = null;
1599
+ p.on(this.$svg, "mousedown", ".handle.progress", (o, h) => {
1600
+ e = !0, t = o.offsetX || o.layerX;
1601
+ const g = p.closest(".bar-wrapper", h).getAttribute("data-id");
1602
+ i = this.get_bar(g), s = i.$bar_progress, n = i.$bar, s.finaldx = 0, s.owidth = s.getWidth(), s.min_dx = -s.owidth, s.max_dx = n.getWidth() - s.getWidth();
1603
+ });
1604
+ const a = this.config.ignored_positions.map((o) => [
1605
+ o,
1606
+ o + this.config.column_width
1607
+ ]);
1608
+ p.on(this.$svg, "mousemove", (o) => {
1609
+ if (!e) return;
1610
+ let h = o.offsetX || o.layerX;
1611
+ if (h > t) {
1612
+ let l = a.find(
1613
+ ([c, u]) => h >= c && h < u
1614
+ );
1615
+ for (; l; )
1616
+ h = l[1], l = a.find(
1617
+ ([c, u]) => h >= c && h < u
1618
+ );
1619
+ } else {
1620
+ let l = a.find(
1621
+ ([c, u]) => h > c && h <= u
1622
+ );
1623
+ for (; l; )
1624
+ h = l[0], l = a.find(
1625
+ ([c, u]) => h > c && h <= u
1626
+ );
1627
+ }
1628
+ let g = h - t;
1629
+ console.log(s), g > s.max_dx && (g = s.max_dx), g < s.min_dx && (g = s.min_dx), s.setAttribute("width", s.owidth + g), p.attr(i.$handle_progress, "cx", s.getEndX()), s.finaldx = g;
1630
+ }), p.on(this.$svg, "mouseup", () => {
1631
+ e = !1, s && s.finaldx && (s.finaldx = 0, i.progress_changed(), i.set_action_completed(), i = null, s = null, n = null);
1632
+ });
1633
+ }
1634
+ get_all_dependent_tasks(t) {
1635
+ let e = [], i = [t];
1636
+ for (; i.length; ) {
1637
+ const s = i.reduce((n, a) => (n = n.concat(this.dependency_map[a]), n), []);
1638
+ e = e.concat(s), i = s.filter((n) => !i.includes(n));
1639
+ }
1640
+ return e.filter(Boolean);
1641
+ }
1642
+ update_dependent_tasks_by_type(t) {
1643
+ if ((t.task.dependencies_type || this.options.dependencies_type) === "fixed") return;
1644
+ (this.dependency_map[t.task.id] || []).forEach((s) => {
1645
+ const n = this.get_bar(s);
1646
+ if (!n) return;
1647
+ const a = n.task, o = a.dependencies_type || this.options.dependencies_type;
1648
+ let h, _;
1649
+ const g = d.diff(a._end, a._start, "hour");
1650
+ let l = !1;
1651
+ switch (o) {
1652
+ case "finish-to-start":
1653
+ t.task._end > a._start && (h = new Date(t.task._end), _ = d.add(h, g, "hour"), l = !0);
1654
+ break;
1655
+ case "start-to-start":
1656
+ t.task._start > a._start && (h = new Date(t.task._start), _ = d.add(h, g, "hour"), l = !0);
1657
+ break;
1658
+ case "finish-to-finish":
1659
+ t.task._end > a._end && (_ = new Date(t.task._end), h = d.add(_, -g, "hour"), l = !0);
1660
+ break;
1661
+ case "start-to-finish":
1662
+ t.task._start > a._end && (_ = new Date(t.task._start), h = d.add(_, -g, "hour"), l = !0);
1663
+ break;
1664
+ default:
1665
+ return;
1666
+ }
1667
+ l && (a._start = h, a._end = _, n.compute_x(), n.compute_duration(), n.update_bar_position({
1668
+ x: n.x,
1669
+ width: n.width
1670
+ }), this.trigger_event("date_change", [
1671
+ a,
1672
+ h,
1673
+ d.add(_, -1, "second")
1674
+ ]), this.update_dependent_tasks_by_type(n));
1675
+ });
1676
+ }
1677
+ get_snap_position(t, e) {
1678
+ let i = 1;
1679
+ const s = this.options.snap_at || this.config.view_mode.snap_at || "1d";
1680
+ if (s !== "unit") {
1681
+ const { duration: g, scale: l } = d.parse_duration(s);
1682
+ i = d.convert_scales(this.config.view_mode.step, l) / g;
1683
+ }
1684
+ const n = t % (this.config.column_width / i);
1685
+ let a = t - n + (n < this.config.column_width / i * 2 ? 0 : this.config.column_width / i), o = e + a;
1686
+ const h = a > 0 ? 1 : -1;
1687
+ let _ = this.get_ignored_region(o, h);
1688
+ for (; _.length; )
1689
+ o += this.config.column_width * h, _ = this.get_ignored_region(o, h), _.length || (o -= this.config.column_width * h);
1690
+ return o - e;
1691
+ }
1692
+ get_ignored_region(t, e = 1) {
1693
+ return e === 1 ? this.config.ignored_positions.filter((i) => t > i && t <= i + this.config.column_width) : this.config.ignored_positions.filter(
1694
+ (i) => t >= i && t < i + this.config.column_width
1695
+ );
1696
+ }
1697
+ unselect_all() {
1698
+ this.popup && this.popup.parent.classList.add("hide"), this.$container.querySelectorAll(".date-range-highlight").forEach((t) => t.classList.add("hide"));
1699
+ }
1700
+ view_is(t) {
1701
+ return typeof t == "string" ? this.config.view_mode.name === t : Array.isArray(t) ? t.some(view_is) : this.config.view_mode.name === t.name;
1702
+ }
1703
+ get_task(t) {
1704
+ return this.tasks.find((e) => e.id === t);
1705
+ }
1706
+ get_bar(t) {
1707
+ return this.bars.find((e) => e.task.id === t);
1708
+ }
1709
+ show_popup(t) {
1710
+ this.options.popup !== !1 && (this.popup || (this.popup = new O(
1711
+ this.$popup_wrapper,
1712
+ this.options.popup,
1713
+ this
1714
+ )), this.popup.show(t));
1715
+ }
1716
+ hide_popup() {
1717
+ this.popup && this.popup.hide();
1718
+ }
1719
+ trigger_event(t, e) {
1720
+ this.options["on_" + t] && this.options["on_" + t].apply(this, e);
1721
+ }
1722
+ /**
1723
+ * Gets the oldest starting date from the list of tasks
1724
+ *
1725
+ * @returns Date
1726
+ * @memberof Gantt
1727
+ */
1728
+ get_oldest_starting_date() {
1729
+ return this.tasks.length ? this.tasks.map((t) => t._start).reduce(
1730
+ (t, e) => e <= t ? e : t
1731
+ ) : /* @__PURE__ */ new Date();
1732
+ }
1733
+ /**
1734
+ * Clear all elements from the parent svg element
1735
+ *
1736
+ * @memberof Gantt
1737
+ */
1738
+ clear() {
1739
+ var t, e, i, s, n, a, o, h, _, g;
1740
+ this.$svg.innerHTML = "", (e = (t = this.$header) == null ? void 0 : t.remove) == null || e.call(t), (s = (i = this.$side_header) == null ? void 0 : i.remove) == null || s.call(i), (a = (n = this.$current_highlight) == null ? void 0 : n.remove) == null || a.call(n), (h = (o = this.$extras) == null ? void 0 : o.remove) == null || h.call(o), (g = (_ = this.popup) == null ? void 0 : _.hide) == null || g.call(_);
1741
+ }
1742
+ }
1743
+ B.VIEW_MODE = {
1744
+ HOUR: y[0],
1745
+ QUARTER_DAY: y[1],
1746
+ HALF_DAY: y[2],
1747
+ DAY: y[3],
1748
+ WEEK: y[4],
1749
+ MONTH: y[5],
1750
+ YEAR: y[6]
1751
+ };
1752
+ function j(r) {
1753
+ return r.name + "_" + Math.random().toString(36).slice(2, 12);
1754
+ }
1755
+ function k(r) {
1756
+ return r.replaceAll(" ", "_").replaceAll(":", "_").replaceAll(".", "_");
1757
+ }
1758
+ export {
1759
+ B as default
1760
+ };