const D = "year", Y = "month", $ = "day", E = "hour", A = "minute", H = "second", L = "millisecond", W = {
January: "Jan",
February: "Feb",
March: "Mar",
April: "Apr",
May: "May",
June: "Jun",
July: "Jul",
August: "Aug",
September: "Sep",
October: "Oct",
November: "Nov",
December: "Dec"
}, h = {
parse_duration(o) {
const e = /([0-9])+(y|m|d|h|min|s|ms)/gm.exec(o);
if (e !== null) {
if (e[2] === "y")
return { duration: parseInt(e[1]), scale: "year" };
if (e[2] === "m")
return { duration: parseInt(e[1]), scale: "month" };
if (e[2] === "d")
return { duration: parseInt(e[1]), scale: "day" };
if (e[2] === "h")
return { duration: parseInt(e[1]), scale: "hour" };
if (e[2] === "min")
return { duration: parseInt(e[1]), scale: "minute" };
if (e[2] === "s")
return { duration: parseInt(e[1]), scale: "second" };
if (e[2] === "ms")
return { duration: parseInt(e[1]), scale: "millisecond" };
}
},
parse(o, t = "-", e = /[.:]/) {
if (o instanceof Date)
return o;
if (typeof o == "string") {
let s, r;
const i = o.split(" ");
s = i[0].split(t).map((a) => parseInt(a, 10)), r = i[1] && i[1].split(e), s[1] = s[1] ? s[1] - 1 : 0;
let n = s;
return r && r.length && (r.length === 4 && (r[3] = "0." + r[3], r[3] = parseFloat(r[3]) * 1e3), n = n.concat(r)), new Date(...n);
}
},
to_string(o, t = !1) {
if (!(o instanceof Date))
throw new TypeError("Invalid argument type");
const e = this.get_date_values(o).map((i, n) => (n === 1 && (i = i + 1), n === 6 ? M(i + "", 3, "0") : M(i + "", 2, "0"))), s = `${e[0]}-${e[1]}-${e[2]}`, r = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
return s + (t ? " " + r : "");
},
format(o, t = "YYYY-MM-DD HH:mm:ss.SSS", e = "en") {
const r = new Intl.DateTimeFormat(e, {
month: "long"
}).format(o), i = r.charAt(0).toUpperCase() + r.slice(1), n = this.get_date_values(o).map((g) => M(g, 2, 0)), a = {
YYYY: n[0],
MM: M(+n[1] + 1, 2, 0),
DD: n[2],
HH: n[3],
mm: n[4],
ss: n[5],
SSS: n[6],
D: n[2],
MMMM: i,
MMM: W[i]
};
let p = t;
const _ = [];
return Object.keys(a).sort((g, c) => c.length - g.length).forEach((g) => {
p.includes(g) && (p = p.replaceAll(g, `$${_.length}`), _.push(a[g]));
}), _.forEach((g, c) => {
p = p.replaceAll(`$${c}`, g);
}), p;
},
diff(o, t, e = $) {
let s, r, i, n, a, p, _;
return s = o - t, r = s / 1e3, n = r / 60, i = n / 60, a = i / 24, p = a / 30, _ = p / 12, e.endsWith("s") || (e += "s"), Math.floor(
{
milliseconds: s,
seconds: r,
minutes: n,
hours: i,
days: a,
months: p,
years: _
}[e]
);
},
today() {
const o = this.get_date_values(/* @__PURE__ */ new Date()).slice(0, 3);
return new Date(...o);
},
now() {
return /* @__PURE__ */ new Date();
},
add(o, t, e) {
t = parseInt(t, 10);
const s = [
o.getFullYear() + (e === D ? t : 0),
o.getMonth() + (e === Y ? t : 0),
o.getDate() + (e === $ ? t : 0),
o.getHours() + (e === E ? t : 0),
o.getMinutes() + (e === A ? t : 0),
o.getSeconds() + (e === H ? t : 0),
o.getMilliseconds() + (e === L ? t : 0)
];
return new Date(...s);
},
start_of(o, t) {
const e = {
[D]: 6,
[Y]: 5,
[$]: 4,
[E]: 3,
[A]: 2,
[H]: 1,
[L]: 0
};
function s(i) {
const n = e[t];
return e[i] <= n;
}
const r = [
o.getFullYear(),
s(D) ? 0 : o.getMonth(),
s(Y) ? 1 : o.getDate(),
s($) ? 0 : o.getHours(),
s(E) ? 0 : o.getMinutes(),
s(A) ? 0 : o.getSeconds(),
s(H) ? 0 : o.getMilliseconds()
];
return new Date(...r);
},
clone(o) {
return new Date(...this.get_date_values(o));
},
get_date_values(o) {
return [
o.getFullYear(),
o.getMonth(),
o.getDate(),
o.getHours(),
o.getMinutes(),
o.getSeconds(),
o.getMilliseconds()
];
},
get_days_in_month(o) {
const t = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], e = o.getMonth();
if (e !== 1)
return t[e];
const s = o.getFullYear();
return s % 4 === 0 && s % 100 != 0 || s % 400 === 0 ? 29 : 28;
}
};
function M(o, t, e) {
return o = o + "", t = t >> 0, e = String(typeof e < "u" ? e : " "), o.length > t ? String(o) : (t = t - o.length, t > e.length && (e += e.repeat(t / e.length)), e.slice(0, t) + String(o));
}
function l(o, t) {
return typeof o == "string" ? (t || document).querySelector(o) : o || null;
}
function u(o, t) {
const e = document.createElementNS("http://www.w3.org/2000/svg", o);
for (let s in t)
s === "append_to" ? t.append_to.appendChild(e) : s === "innerHTML" ? e.innerHTML = t.innerHTML : s === "clipPath" ? e.setAttribute("clip-path", "url(#" + t[s] + ")") : e.setAttribute(s, t[s]);
return e;
}
function S(o, t, e, s) {
const r = X(o, t, e, s);
if (r === o) {
const i = document.createEvent("HTMLEvents");
i.initEvent("click", !0, !0), i.eventName = "click", r.dispatchEvent(i);
}
}
function X(o, t, e, s, r = "0.4s", i = "0.1s") {
const n = o.querySelector("animate");
if (n)
return l.attr(n, {
attributeName: t,
from: e,
to: s,
dur: r,
begin: "click + " + i
// artificial click
}), o;
const a = u("animate", {
attributeName: t,
from: e,
to: s,
dur: r,
begin: i,
calcMode: "spline",
values: e + ";" + s,
keyTimes: "0; 1",
keySplines: O("ease-out")
});
return o.appendChild(a), o;
}
function O(o) {
return {
ease: ".25 .1 .25 1",
linear: "0 0 1 1",
"ease-in": ".42 0 1 1",
"ease-out": "0 0 .58 1",
"ease-in-out": ".42 0 .58 1"
}[o];
}
l.on = (o, t, e, s) => {
s ? l.delegate(o, t, e, s) : (s = e, l.bind(o, t, s));
};
l.off = (o, t, e) => {
o.removeEventListener(t, e);
};
l.bind = (o, t, e) => {
t.split(/\s+/).forEach(function(s) {
o.addEventListener(s, e);
});
};
l.delegate = (o, t, e, s) => {
o.addEventListener(t, function(r) {
const i = r.target.closest(e);
i && (r.delegatedTarget = i, s.call(this, r, i));
});
};
l.closest = (o, t) => t ? t.matches(o) ? t : l.closest(o, t.parentNode) : null;
l.attr = (o, t, e) => {
if (!e && typeof t == "string")
return o.getAttribute(t);
if (typeof t == "object") {
for (let s in t)
l.attr(o, s, t[s]);
return;
}
o.setAttribute(t, e);
};
class C {
constructor(t, e) {
this.set_defaults(t, e), this.prepare(), this.draw(), this.bind();
}
set_defaults(t, e) {
this.action_completed = !1, this.gantt = t, this.task = e;
}
prepare() {
this.prepare_values(), this.prepare_helpers();
}
prepare_values() {
this.invalid = this.task.invalid, this.height = this.gantt.options.bar_height, this.image_size = this.height - 5, this.compute_x(), this.compute_y(), this.compute_duration(), this.corner_radius = this.gantt.options.bar_corner_radius, this.width = this.gantt.options.column_width * this.duration, this.progress_width = this.gantt.options.column_width * this.duration * (this.task.progress / 100) || 0, this.group = u("g", {
class: "bar-wrapper" + (this.task.custom_class ? " " + this.task.custom_class : "") + (this.task.important ? " important" : ""),
"data-id": this.task.id
}), this.bar_group = u("g", {
class: "bar-group",
append_to: this.group
}), this.handle_group = u("g", {
class: "handle-group",
append_to: this.group
});
}
prepare_helpers() {
SVGElement.prototype.getX = function() {
return +this.getAttribute("x");
}, SVGElement.prototype.getY = function() {
return +this.getAttribute("y");
}, SVGElement.prototype.getWidth = function() {
return +this.getAttribute("width");
}, SVGElement.prototype.getHeight = function() {
return +this.getAttribute("height");
}, SVGElement.prototype.getEndX = function() {
return this.getX() + this.getWidth();
};
}
prepare_expected_progress_values() {
this.compute_expected_progress(), this.expected_progress_width = this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0;
}
draw() {
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();
}
draw_bar() {
this.$bar = u("rect", {
x: this.x,
y: this.y,
width: this.width,
height: this.height,
rx: this.corner_radius,
ry: this.corner_radius,
class: "bar",
append_to: this.bar_group
}), S(this.$bar, "width", 0, this.width), this.invalid && this.$bar.classList.add("bar-invalid");
}
draw_expected_progress_bar() {
this.invalid || (this.$expected_bar_progress = u("rect", {
x: this.x,
y: this.y,
width: this.expected_progress_width,
height: this.height,
rx: this.corner_radius,
ry: this.corner_radius,
class: "bar-expected-progress",
append_to: this.bar_group
}), S(
this.$expected_bar_progress,
"width",
0,
this.expected_progress_width
));
}
draw_progress_bar() {
if (this.invalid)
return;
this.$bar_progress = u("rect", {
x: this.x,
y: this.y,
width: this.progress_width,
height: this.height,
rx: this.corner_radius,
ry: this.corner_radius,
class: "bar-progress",
append_to: this.bar_group
});
const t = h.diff(this.task._start, this.gantt.gantt_start, "hour") / this.gantt.options.step * this.gantt.options.column_width;
let e = document.createElement("div");
e.id = `${this.task.id}-highlight`, e.classList.add("date-highlight"), e.style.height = this.height * 0.8 + "px", e.style.width = this.width + "px", e.style.top = this.gantt.options.header_height - 25 + "px", e.style.left = t + "px", this.$date_highlight = e, this.gantt.$lower_header.prepend(e), S(this.$bar_progress, "width", 0, this.progress_width);
}
draw_label() {
let t = this.x + this.$bar.getWidth() / 2;
this.task.thumbnail && (t = this.x + this.image_size + 5), u("text", {
x: t,
y: this.y + this.height / 2,
innerHTML: this.task.name,
class: "bar-label",
append_to: this.bar_group
}), requestAnimationFrame(() => this.update_label_position());
}
draw_thumbnail() {
let t = 10, e = 2, s, r;
s = u("defs", {
append_to: this.bar_group
}), u("rect", {
id: "rect_" + this.task.id,
x: this.x + t,
y: this.y + e,
width: this.image_size,
height: this.image_size,
rx: "15",
class: "img_mask",
append_to: s
}), r = u("clipPath", {
id: "clip_" + this.task.id,
append_to: s
}), u("use", {
href: "#rect_" + this.task.id,
append_to: r
}), u("image", {
x: this.x + t,
y: this.y + e,
width: this.image_size,
height: this.image_size,
class: "bar-img",
href: this.task.thumbnail,
clipPath: "clip_" + this.task.id,
append_to: this.bar_group
});
}
draw_resize_handles() {
if (this.invalid || this.gantt.options.readonly)
return;
const t = this.$bar, e = 8;
u("rect", {
x: t.getX() + t.getWidth() + e - 4,
y: t.getY() + 1,
width: e,
height: this.height - 2,
rx: this.corner_radius,
ry: this.corner_radius,
class: "handle right",
append_to: this.handle_group
}), u("rect", {
x: t.getX() - e - 4,
y: t.getY() + 1,
width: e,
height: this.height - 2,
rx: this.corner_radius,
ry: this.corner_radius,
class: "handle left",
append_to: this.handle_group
}), this.$handle_progress = u("polygon", {
points: this.get_progress_polygon_points().join(","),
class: "handle progress",
append_to: this.handle_group
});
}
get_progress_polygon_points() {
const t = this.$bar_progress;
let e = 10, s = 15;
return [
t.getEndX() - e / 2,
t.getY() + t.getHeight() / 2,
t.getEndX(),
t.getY() + t.getHeight() / 2 - s / 2,
t.getEndX() + e / 2,
t.getY() + t.getHeight() / 2,
t.getEndX(),
t.getY() + t.getHeight() / 2 + s / 2,
t.getEndX() - e / 2,
t.getY() + t.getHeight() / 2
];
}
bind() {
this.invalid || this.setup_click_event();
}
setup_click_event() {
let t = this.task.id;
l.on(this.group, "mouseover", (s) => {
this.gantt.trigger_event("hover", [
this.task,
s.screenX,
s.screenY,
s
]);
});
let e;
l.on(
this.group,
"mouseenter",
(s) => e = setTimeout(() => {
this.show_popup(s.offsetX), document.querySelector(
`#${t}-highlight`
).style.display = "block";
}, 200)
), l.on(this.group, "mouseleave", () => {
var s, r;
clearTimeout(e), (r = (s = this.gantt.popup) == null ? void 0 : s.hide) == null || r.call(s), document.querySelector(`#${t}-highlight`).style.display = "none";
}), l.on(this.group, this.gantt.options.popup_trigger, () => {
this.gantt.trigger_event("click", [this.task]);
}), l.on(this.group, "dblclick", (s) => {
this.action_completed || this.gantt.trigger_event("double_click", [this.task]);
});
}
show_popup(t) {
if (this.gantt.bar_being_dragged)
return;
const e = h.format(
this.task._start,
"MMM D",
this.gantt.options.language
), s = h.format(
h.add(this.task._end, -1, "second"),
"MMM D",
this.gantt.options.language
), r = `${e} - ${s}
Progress: ${this.task.progress}`;
this.gantt.show_popup({
x: t,
target_element: this.$bar,
title: this.task.name,
subtitle: r,
task: this.task
});
}
update_bar_position({ x: t = null, width: e = null }) {
const s = this.$bar;
if (t) {
if (!this.task.dependencies.map((n) => this.gantt.get_bar(n).$bar.getX()).reduce((n, a) => t >= a, t)) {
e = null;
return;
}
this.update_attr(s, "x", t), this.$date_highlight.style.left = t + "px";
}
e && (this.update_attr(s, "width", e), this.$date_highlight.style.width = e + "px"), this.update_label_position(), this.update_handle_position(), this.gantt.options.show_expected_progress && (this.date_changed(), this.compute_duration(), this.update_expected_progressbar_position()), this.update_progressbar_position(), this.update_arrow_position();
}
update_label_position_on_horizontal_scroll({ x: t, sx: e }) {
const s = document.querySelector(".gantt-container"), r = this.group.querySelector(".bar-label"), i = this.group.querySelector(".bar-img") || "", n = this.bar_group.querySelector(".img_mask") || "";
let a = this.$bar.getX() + this.$bar.getWidth(), p = r.getX() + t, _ = i && i.getX() + t || 0, g = i && i.getBBox().width + 7 || 7, c = p + r.getBBox().width + 7, f = e + s.clientWidth / 2;
r.classList.contains("big") || (c < a && t > 0 && c < f || p - g > this.$bar.getX() && t < 0 && c > f) && (r.setAttribute("x", p), i && (i.setAttribute("x", _), n.setAttribute("x", _)));
}
date_changed() {
let t = !1;
const { new_start_date: e, new_end_date: s } = this.compute_start_end_date();
Number(this.task._start) !== Number(e) && (t = !0, this.task._start = e), Number(this.task._end) !== Number(s) && (t = !0, this.task._end = s), t && this.gantt.trigger_event("date_change", [
this.task,
e,
h.add(s, -1, "second")
]);
}
progress_changed() {
const t = this.compute_progress();
this.task.progress = t, this.gantt.trigger_event("progress_change", [this.task, t]);
}
set_action_completed() {
this.action_completed = !0, setTimeout(() => this.action_completed = !1, 1e3);
}
compute_start_end_date() {
const t = this.$bar, e = t.getX() / this.gantt.options.column_width, s = h.add(
this.gantt.gantt_start,
e * this.gantt.options.step,
"hour"
), r = t.getWidth() / this.gantt.options.column_width, i = h.add(
s,
r * this.gantt.options.step,
"hour"
);
return { new_start_date: s, new_end_date: i };
}
compute_progress() {
const t = this.$bar_progress.getWidth() / this.$bar.getWidth() * 100;
return parseInt(t, 10);
}
compute_expected_progress() {
this.expected_progress = h.diff(h.today(), this.task._start, "hour") / this.gantt.options.step, this.expected_progress = (this.expected_progress < this.duration ? this.expected_progress : this.duration) * 100 / this.duration;
}
compute_x() {
const { step: t, column_width: e } = this.gantt.options, s = this.task._start, r = this.gantt.gantt_start;
let n = h.diff(s, r, "hour") / t * e;
this.gantt.view_is("Month") && (n = h.diff(s, r, "day") * e / 30), this.x = n;
}
compute_y() {
this.y = this.gantt.options.header_height + this.gantt.options.padding + this.task._index * (this.height + this.gantt.options.padding);
}
compute_duration() {
this.duration = h.diff(this.task._end, this.task._start, "hour") / this.gantt.options.step;
}
get_snap_position(t) {
let e = t, s, r;
return this.gantt.view_is("Week") ? (s = t % (this.gantt.options.column_width / 7), r = e - s + (s < this.gantt.options.column_width / 14 ? 0 : this.gantt.options.column_width / 7)) : this.gantt.view_is("Month") ? (s = t % (this.gantt.options.column_width / 30), r = e - s + (s < this.gantt.options.column_width / 60 ? 0 : this.gantt.options.column_width / 30)) : (s = t % this.gantt.options.column_width, r = e - s + (s < this.gantt.options.column_width / 2 ? 0 : this.gantt.options.column_width)), r;
}
update_attr(t, e, s) {
return s = +s, isNaN(s) || t.setAttribute(e, s), t;
}
update_expected_progressbar_position() {
this.invalid || (this.$expected_bar_progress.setAttribute("x", this.$bar.getX()), this.compute_expected_progress(), this.$expected_bar_progress.setAttribute(
"width",
this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0
));
}
update_progressbar_position() {
this.invalid || this.gantt.options.readonly || (this.$bar_progress.setAttribute("x", this.$bar.getX()), this.$bar_progress.setAttribute(
"width",
this.$bar.getWidth() * (this.task.progress / 100)
));
}
update_label_position() {
const t = this.bar_group.querySelector(".img_mask") || "", e = this.$bar, s = this.group.querySelector(".bar-label"), r = this.group.querySelector(".bar-img");
let i = 5, n = this.image_size + 10;
const a = s.getBBox().width, p = e.getWidth();
a > p ? (s.classList.add("big"), r ? (r.setAttribute("x", e.getX() + e.getWidth() + i), t.setAttribute(
"x",
e.getX() + e.getWidth() + i
), s.setAttribute(
"x",
e.getX() + e.getWidth() + n
)) : s.setAttribute("x", e.getX() + e.getWidth() + i)) : (s.classList.remove("big"), r ? (r.setAttribute("x", e.getX() + i), t.setAttribute("x", e.getX() + i), s.setAttribute(
"x",
e.getX() + p / 2 + n
)) : s.setAttribute(
"x",
e.getX() + p / 2 - a / 2
));
}
update_handle_position() {
if (this.invalid || this.gantt.options.readonly)
return;
const t = this.$bar;
this.handle_group.querySelector(".handle.left").setAttribute("x", t.getX() - 12), this.handle_group.querySelector(".handle.right").setAttribute("x", t.getEndX() + 4);
const e = this.group.querySelector(".handle.progress");
e && e.setAttribute("points", this.get_progress_polygon_points());
}
update_arrow_position() {
this.arrows = this.arrows || [];
for (let t of this.arrows)
t.update();
}
}
class N {
constructor(t, e, s) {
this.gantt = t, this.from_task = e, this.to_task = s, this.calculate_path(), this.draw();
}
calculate_path() {
let t = this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;
const e = () => this.to_task.$bar.getX() < t + this.gantt.options.padding && t > this.from_task.$bar.getX() + this.gantt.options.padding;
for (; e(); )
t -= 10;
const s = this.gantt.options.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, r = this.to_task.$bar.getX() - this.gantt.options.padding / 2 - 7, i = this.gantt.options.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, n = this.from_task.task._index > this.to_task.task._index, a = this.gantt.options.arrow_curve, p = n ? 1 : 0, _ = n ? -a : a, g = n ? i + this.gantt.options.arrow_curve : i - this.gantt.options.arrow_curve;
if (this.path = `
M ${t} ${s}
V ${g}
a ${a} ${a} 0 0 ${p} ${a} ${_}
L ${r} ${i}
m -5 -5
l 5 5
l -5 5`, this.to_task.$bar.getX() < this.from_task.$bar.getX() + this.gantt.options.padding) {
const c = this.gantt.options.padding / 2 - a, f = this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - _, m = this.to_task.$bar.getX() - this.gantt.options.padding;
this.path = `
M ${t} ${s}
v ${c}
a ${a} ${a} 0 0 1 -${a} ${a}
H ${m}
a ${a} ${a} 0 0 ${p} -${a} ${_}
V ${f}
a ${a} ${a} 0 0 ${p} ${a} ${_}
L ${r} ${i}
m -5 -5
l 5 5
l -5 5`;
}
}
draw() {
this.element = u("path", {
d: this.path,
"data-from": this.from_task.task.id,
"data-to": this.to_task.task.id
});
}
update() {
this.calculate_path(), this.element.setAttribute("d", this.path);
}
}
class R {
constructor(t, e) {
this.parent = t, this.custom_html = e, this.make();
}
make() {
this.parent.innerHTML = `