UNPKG

@svar-ui/react-gantt

Version:

A customizable, high-performance React Gantt chart component for building project timelines.

1,561 lines 63.3 kB
import { jsxs as xe, jsx as c, Fragment as Ge } from "react/jsx-runtime"; import { createContext as lt, useMemo as M, useState as ce, useContext as ve, useRef as Y, useCallback as y, useEffect as X, Fragment as ct, forwardRef as Ue, useImperativeHandle as Ze } from "react"; import { context as $e, Locale as Je, Field as it, Combo as at, DatePicker as ut, TimePicker as dt, RichSelect as ft, TwoState as ht, Slider as mt, Counter as xt, Material as Pe, Willow as Fe, WillowDark as Oe } from "@svar-ui/react-core"; import { en as We } from "@svar-ui/gantt-locales"; import { EventBusRouter as pt } from "@svar-ui/lib-state"; import { normalizeDates as et, grid as wt, DataStore as gt, defaultTaskTypes as yt, defaultColumns as kt, defaultToolbarButtons as Ve, handleAction as tt, isHandledAction as nt, defaultMenuOptions as je, defaultEditorItems as bt } from "@svar-ui/gantt-store"; import { defaultColumns as vn, defaultEditorItems as Tn, defaultMenuOptions as Cn, defaultTaskTypes as $n, defaultToolbarButtons as Rn, registerScaleUnit as Nn } from "@svar-ui/gantt-store"; import { useWritableProp as ze, useStore as F, useStoreWithCounter as _e, writable as vt, useStoreLater as Se } from "@svar-ui/lib-react"; import { hotkeys as st } from "@svar-ui/grid-store"; import { locate as Ee, locateID as Ie, locateAttr as Tt, locale as Ke, dateToString as Ct } from "@svar-ui/lib-dom"; import { Grid as $t, HeaderMenu as Rt } from "@svar-ui/react-grid"; import { Toolbar as Be } from "@svar-ui/react-toolbar"; import { ContextMenu as Nt } from "@svar-ui/react-menu"; import { en as rt } from "@svar-ui/core-locales"; import { Editor as Lt, registerEditorItem as De } from "@svar-ui/react-editor"; import { registerEditorItem as Mn } from "@svar-ui/react-editor"; const Re = lt(null); function He(e) { const t = e.getAttribute("data-id"), n = parseInt(t); return isNaN(n) || n.toString() != t ? t : n; } function Mt(e, t, n) { const s = e.getBoundingClientRect(), i = t.querySelector(".wx-body").getBoundingClientRect(); return { top: s.top - i.top, left: s.left - i.left, dt: s.bottom - n.clientY, db: n.clientY - s.top }; } function Xe(e) { return e && e.getAttribute("data-context-id"); } const Ye = 5; function St(e, t) { let n, s, i, N, p, l, m, E, x; function I(h) { N = h.clientX, p = h.clientY, l = { ...Mt(n, e, h), y: t.getTask(i).$y }, document.body.style.userSelect = "none"; } function w(h) { n = Ee(h), Xe(n) && (i = He(n), x = setTimeout(() => { E = !0, t && t.touchStart && t.touchStart(), I(h.touches[0]); }, 500), e.addEventListener("touchmove", O), e.addEventListener("contextmenu", a), window.addEventListener("touchend", W)); } function a(h) { if (E || x) return h.preventDefault(), !1; } function $(h) { h.which === 1 && (n = Ee(h), Xe(n) && (i = He(n), e.addEventListener("mousemove", A), window.addEventListener("mouseup", d), I(h))); } function v(h) { e.removeEventListener("mousemove", A), e.removeEventListener("touchmove", O), document.body.removeEventListener("mouseup", d), document.body.removeEventListener("touchend", W), document.body.style.userSelect = "", h && (e.removeEventListener("mousedown", $), e.removeEventListener("touchstart", w)); } function G(h) { const V = h.clientX - N, K = h.clientY - p; if (!s) { if (Math.abs(V) < Ye && Math.abs(K) < Ye || t && t.start && t.start({ id: i, e: h }) === !1) return; s = n.cloneNode(!0), s.style.pointerEvents = "none", s.classList.add("wx-reorder-task"), s.style.position = "absolute", s.style.left = l.left + "px", s.style.top = l.top + "px", n.style.visibility = "hidden", n.parentNode.insertBefore(s, n); } if (s) { const q = Math.round(Math.max(0, l.top + K)); if (t && t.move && t.move({ id: i, top: q, detail: m }) === !1) return; const J = t.getTask(i), D = J.$y; if (!l.start && l.y == D) return L(); l.start = !0, l.y = J.$y - 4, s.style.top = q + "px"; const b = document.elementFromPoint( h.clientX, h.clientY ), z = Ee(b); if (z && z !== n) { const k = He(z), T = z.getBoundingClientRect(), B = T.top + T.height / 2, u = h.clientY + l.db > B && z.nextElementSibling !== n, S = h.clientY - l.dt < B && z.previousElementSibling !== n; m?.after == k || m?.before == k ? m = null : u ? m = { id: i, after: k } : S && (m = { id: i, before: k }); } } } function A(h) { G(h); } function O(h) { E ? (h.preventDefault(), G(h.touches[0])) : x && (clearTimeout(x), x = null); } function W() { E = null, x && (clearTimeout(x), x = null), L(); } function d() { L(); } function L() { n && (n.style.visibility = ""), s && (s.parentNode.removeChild(s), t && t.end && t.end({ id: i, top: l.top })), i = n = s = l = m = null, v(); } return e.style.position !== "absolute" && (e.style.position = "relative"), e.addEventListener("mousedown", $), e.addEventListener("touchstart", w), { destroy() { v(!0); } }; } function Et({ row: e, column: t }) { function n(i, N) { return { justifyContent: N.align, paddingLeft: `${(i.$level - 1) * 20}px` }; } const s = t && t._cell; return /* @__PURE__ */ xe("div", { className: "wx-pqc08MHU wx-content", style: n(e, t), children: [ e.data || e.lazy ? /* @__PURE__ */ c( "i", { className: `wx-pqc08MHU wx-toggle-icon wxi-menu-${e.open ? "down" : "right"}`, "data-action": "open-task" } ) : /* @__PURE__ */ c("i", { className: "wx-pqc08MHU wx-toggle-placeholder" }), /* @__PURE__ */ c("div", { className: "wx-pqc08MHU wx-text", children: s ? /* @__PURE__ */ c(s, { row: e, column: t }) : e.text }) ] }); } function qe({ column: e, cell: t }) { const n = M(() => e.id, [e?.id]); return t || e.id == "add-task" ? /* @__PURE__ */ c("div", { style: { textAlign: e.align }, children: /* @__PURE__ */ c( "i", { className: "wx-9DAESAHW wx-action-icon wxi-plus", "data-action": n } ) }) : null; } function At(e) { const { readonly: t, compactMode: n, width: s = 0, display: i = "all", columnWidth: N = 0, onTableAPIChange: p } = e, [l, m] = ze(N), [E, x] = ce(), I = ve($e.i18n), w = M(() => I.getGroup("gantt"), [I]), a = ve(Re), $ = F(a, "scrollTop"), v = F(a, "cellHeight"), G = F(a, "_scrollTask"), A = F(a, "_selected"), O = F(a, "area"), W = F(a, "_tasks"), d = F(a, "_scales"), L = F(a, "columns"), h = F(a, "_sort"), V = F(a, "durationUnit"), K = Y(null), q = Y(!0), [J, D] = ce(null), b = M(() => !W || !O ? [] : W.slice(O.start, O.end), [W, O]), z = y( (r, f) => { if (f === "add-task") a.exec(f, { target: r, task: { text: w("New Task") }, mode: "child", show: !0 }); else if (f === "open-task") { const g = b.find((_) => _.id === r); (g?.data || g?.lazy) && a.exec(f, { id: r, mode: !g.open }); } }, [b] ), k = y( (r) => { const f = Ie(r), g = r.target.dataset.action; g && r.preventDefault(), f ? g === "add-task" || g === "open-task" ? z(f, g) : a.exec("select-task", { id: f, toggle: r.ctrlKey || r.metaKey, range: r.shiftKey, show: !0 }) : g === "add-task" && z(null, g); }, [a, z] ), T = Y(null), B = Y(null), [u, S] = ce(0), [te, Z] = ce(!1); X(() => { const r = B.current; if (!r || typeof ResizeObserver > "u") return; const f = () => S(r.clientWidth); f(); const g = new ResizeObserver(f); return g.observe(r), () => g.disconnect(); }, []); const ee = Y(null), oe = y( (r) => { const f = r.id, { before: g, after: _ } = r, re = r.onMove; let se = g || _, me = g ? "before" : "after"; if (re) { if (me === "after") { const Te = a.getTask(se); Te.data?.length && Te.open && (me = "before", se = Te.data[0].id); } ee.current = { id: f, [me]: se }; } else ee.current = null; a.exec("move-task", { id: f, mode: me, target: se, inProgress: re }); }, [a] ), ue = M(() => O?.from ?? 0, [O]), ge = M(() => d?.height ?? 0, [d]), H = M(() => !n && i !== "grid" ? (l ?? 0) > (s ?? 0) : (l ?? 0) > (u ?? 0), [n, i, l, s, u]), le = M(() => { const r = {}; return H && i === "all" || i === "grid" && H ? r.width = l : i === "grid" && (r.width = "100%"), r; }, [H, i, l]), fe = M(() => J && !b.find((r) => r.id === J.id) ? [...b, J] : b, [b, J]), C = M(() => { let r = (L || []).map((_) => { _ = { ..._ }; const re = _.header; if (typeof re == "object") { const se = re.text && w(re.text); _.header = { ...re, text: se }; } else _.header = w(re); return _; }); const f = r.findIndex((_) => _.id === "text"), g = r.findIndex((_) => _.id === "add-task"); if (f !== -1 && (r[f].cell && (r[f]._cell = r[f].cell), r[f].cell = Et), g !== -1) { r[g].cell = r[g].cell || qe; const _ = r[g].header; if (typeof _ != "object" && (r[g].header = { text: _ }), r[g].header.cell = _.cell || qe, t) r.splice(g, 1); else if (n) { const [re] = r.splice(g, 1); r.unshift(re); } } return r.length > 0 && (r[r.length - 1].resize = !1), r; }, [L, w, t, n]), j = M(() => i === "all" ? `${s}px` : i === "grid" ? "calc(100% - 4px)" : C.find((r) => r.id === "add-task") ? "50px" : "0", [i, s, C]), ie = M(() => { if (fe && h?.length) { const r = {}; return h.forEach(({ key: f, order: g }, _) => { r[f] = { order: g, ...h.length > 1 && { index: _ } }; }), r; } return {}; }, [fe, h]), ae = y(() => C.some((r) => r.flexgrow && !r.hidden), []), Q = M(() => ae(), [ae, te]), pe = M(() => { let r = i === "chart" ? C.filter((g) => g.id === "add-task") : C; const f = i === "all" ? s : u; if (!Q) { let g = l, _ = !1; if (C.some((re) => re.$width)) { let re = 0; g = C.reduce((se, me) => (me.hidden || (re += me.width, se += me.$width || me.width), se), 0), re > g && g > f && (_ = !0); } if (_ || g < f) { let re = 1; return _ || (re = (f - 50) / (g - 50 || 1)), r.map((se) => (se.id !== "add-task" && !se.hidden && (se.$width || (se.$width = se.width), se.width = se.$width * re), se)); } } return r; }, [i, C, Q, l, s, u]), ye = y( (r) => { if (!ae()) { const f = pe.reduce((g, _) => (r && _.$width && (_.$width = _.width), g + (_.hidden ? 0 : _.width)), 0); f !== l && m(f); } Z(!0), Z(!1); }, [ae, pe, l, m] ), Ce = y(() => { C.filter((f) => f.flexgrow && !f.hidden).length === 1 && C.forEach((f) => { f.$width && !f.flexgrow && !f.hidden && (f.width = f.$width); }); }, []), Ne = y( (r) => { if (!t) { const f = Ie(r), g = Tt(r, "data-col-id"); !(g && C.find((re) => re.id == g))?.editor && f && a.exec("show-editor", { id: f }); } }, [a, t] // cols is defined later; relies on latest value at call time ), o = y(() => { q.current = !1; }, []), R = y( (r) => { q.current = !0, K.current = r.touches[0].clientY + ($ ?? 0); }, [$] ), U = y( (r) => { if (q.current) { const f = (K.current ?? 0) - r.touches[0].clientY; return a.exec("scroll-chart", { top: f }), r.preventDefault(), !1; } }, [a] ), P = M( () => Array.isArray(A) ? A.map((r) => r.id) : [], [A] ); X(() => { const r = () => o(); return window.addEventListener("touchend", r), () => window.removeEventListener("touchend", r); }, [o]); const ne = y(() => { if (T.current && fe !== null) { const r = T.current.querySelector(".wx-body"); r && (r.style.top = -(($ ?? 0) - (ue ?? 0)) + "px"); } B.current && (B.current.scrollTop = 0); }, [fe, $, ue]); X(() => { T.current && ne(); }, [$, ue, ne]), X(() => { const r = T.current; if (!r) return; const f = r.querySelector(".wx-table-box .wx-body"); if (!f || typeof ResizeObserver > "u") return; const g = new ResizeObserver(() => { ne(); }); return g.observe(f), () => { g.disconnect(); }; }, [pe, le, i, j, fe, ne]), X(() => { if (!G || !E) return; const { id: r } = G, f = E.getState().focusCell; f && f.row !== r && T.current && T.current.contains(document.activeElement) && E.exec("focus-cell", { row: r, column: f.column }); }, [G, E]); const he = y( ({ id: r }) => { if (t) return !1; a.getTask(r).open && a.exec("open-task", { id: r, mode: !1 }); const f = a.getState()._tasks.find((g) => g.id === r); if (D(f || null), !f) return !1; }, [a, t] ), we = y( ({ id: r, top: f }) => { ee.current ? oe({ ...ee.current, onMove: !1 }) : a.exec("drag-task", { id: r, top: f + (ue ?? 0), inProgress: !1 }), D(null); }, [a, oe, ue] ), ke = y( ({ id: r, top: f, detail: g }) => { g && oe({ ...g, onMove: !0 }), a.exec("drag-task", { id: r, top: f + (ue ?? 0), inProgress: !0 }); }, [a, oe, ue] ); X(() => { const r = T.current; return r ? St(r, { start: he, touchStart: o, end: we, move: ke, getTask: a.getTask }).destroy : void 0; }, [a, he, o, we, ke]); const be = y( (r) => { const { key: f, isInput: g } = r; if (!g && (f === "arrowup" || f === "arrowdown")) return r.eventSource = "grid", a.exec("hotkey", r), !1; if (f === "enter") { const _ = E?.getState().focusCell; if (_) { const { row: re, column: se } = _; se === "add-task" ? z(re, "add-task") : se === "text" && z(re, "open-task"); } } }, [a, z, E] ), de = Y(null), Le = () => { de.current = { setTableAPI: x, handleHotkey: be, sortVal: h, api: a, adjustColumns: Ce, setColumnWidth: ye, tasks: b, durationUnitVal: V, onTableAPIChange: p }; }; Le(), X(() => { Le(); }, [x, be, h, a, Ce, ye, b, V, p]); const Me = y( (r) => { x(r), r.intercept("hotkey", (f) => de.current.handleHotkey(f)), r.intercept("scroll", () => !1), r.intercept("select-row", () => !1), r.intercept("sort-rows", (f) => { const g = de.current.sortVal, { key: _, add: re } = f, se = g ? g.find((Te) => Te.key === _) : null; let me = "asc"; return se && (me = !se || se.order === "asc" ? "desc" : "asc"), a.exec("sort-tasks", { key: _, order: me, add: re }), !1; }), r.on("resize-column", () => { de.current.setColumnWidth(!0); }), r.on("hide-column", (f) => { f.mode || de.current.adjustColumns(), de.current.setColumnWidth(); }), r.intercept("update-cell", (f) => { const { id: g, column: _, value: re } = f, se = de.current.tasks.find((me) => me.id === g); if (se) { const me = { ...se }; let Te = re; Te && !isNaN(Te) && !(Te instanceof Date) && (Te *= 1), me[_] = Te, et(me, de.current.durationUnitVal, !0, _), a.exec("update-task", { id: g, task: me }); } return !1; }), p && p(r); }, [] ); return /* @__PURE__ */ c( "div", { className: "wx-rHj6070p wx-table-container", style: { flex: `0 0 ${j}` }, ref: B, children: /* @__PURE__ */ c( "div", { ref: T, style: le, className: "wx-rHj6070p wx-table", onTouchStart: R, onTouchMove: U, onClick: k, onDoubleClick: Ne, children: /* @__PURE__ */ c( $t, { init: Me, sizes: { rowHeight: v, headerHeight: (ge ?? 0) - 1 }, rowStyle: (r) => r.$reorder ? "wx-rHj6070p wx-reorder-task" : "wx-rHj6070p", columnStyle: (r) => `wx-rHj6070p wx-text-${r.align}${r.id === "add-task" ? " wx-action" : ""}`, data: fe, columns: pe, selectedRows: [...P], sortMarks: ie } ) } ) } ); } function Dt({ borders: e = "" }) { const t = ve(Re), n = F(t, "cellWidth"), s = F(t, "cellHeight"), i = Y(null), [N, p] = ce("#e4e4e4"); X(() => { if (typeof getComputedStyle < "u" && i.current) { const m = getComputedStyle(i.current).getPropertyValue( "--wx-gantt-border" ); p(m ? m.substring(m.indexOf("#")) : "#1d1e261a"); } }, []); const l = { width: "100%", height: "100%", background: n != null && s != null ? `url(${wt(n, s, N, e)})` : void 0, position: "absolute" }; return /* @__PURE__ */ c("div", { ref: i, style: l }); } function Ht(e) { const { readonly: t, taskTemplate: n } = e, s = ve(Re), [i, N] = _e(s, "_tasks"), [p, l] = _e(s, "_links"), m = F(s, "area"), E = F(s, "_scales"), x = F(s, "taskTypes"), I = F(s, "baselines"), w = F(s, "_selected"), a = F(s, "_scrollTask"), $ = M(() => { if (!m || !Array.isArray(i)) return []; const o = m.start ?? 0, R = m.end ?? 0; return i.slice(o, R).map((U) => ({ ...U })); }, [N, m]), v = M( () => E.lengthUnitWidth, [E] ), G = Y(!1), [A, O] = ce(void 0), [W, d] = ce(null), L = Y(null), [h, V] = ce(void 0), K = Y(null), [q, J] = ce(0), D = Y(null), b = M(() => { const o = D.current; return !!(w.length && o && o.contains(document.activeElement)); }, [w, D.current]), z = M(() => b && w[w.length - 1]?.id, [b, w]); X(() => { if (a && b && a) { const { id: o } = a, R = D.current?.querySelector( `.wx-bar[data-id='${o}']` ); R && R.focus({ preventScroll: !0 }); } }, [a]), X(() => { const o = D.current; if (o && (J(o.offsetWidth || 0), typeof ResizeObserver < "u")) { const R = new ResizeObserver((U) => { U[0] && J(U[0].contentRect.width); }); return R.observe(o), () => R.disconnect(); } }, [D.current]); const k = y(() => { document.body.style.userSelect = "none"; }, []), T = y(() => { document.body.style.userSelect = ""; }, []), B = y( (o, R, U) => { if (U || (U = s.getTask(He(o))), U.type === "milestone" || U.type == "summary") return ""; const P = o.getBoundingClientRect(), ne = (R.clientX - P.left) / P.width; let he = 0.2 / (P.width > 200 ? P.width / 200 : 1); return ne < he ? "start" : ne > 1 - he ? "end" : ""; }, [s] ), u = y( (o, R) => { const { clientX: U } = R, P = He(o), ne = s.getTask(P), he = R.target.classList; if (!t) { if (he.contains("wx-progress-marker")) { const { progress: we } = s.getTask(P); L.current = { id: P, x: U, progress: we, dx: 0, node: o, marker: R.target }, R.target.classList.add("wx-progress-in-drag"); } else { const we = B(o, R, ne) || "move"; d({ id: P, mode: we, x: U, dx: 0, l: ne.$x, w: ne.$w }); } k(); } }, [s, t, B, k] ), S = y( (o) => { if (o.button !== 0) return; const R = Ee(o); R && u(R, o); }, [t, v, q, W, A] ), te = y( (o) => { const R = Ee(o); R && (K.current = setTimeout(() => { V(!0), u(R, o.touches[0]); }, 300)); }, [t] ), Z = y(() => { if (L.current) { const { dx: o, id: R, marker: U, value: P } = L.current; L.current = null, typeof P < "u" && o && s.exec("update-task", { id: R, task: { progress: P } }), U.classList.remove("wx-progress-in-drag"), G.current = !0, T(); } else if (W) { const { id: o, mode: R, dx: U, l: P, w: ne, start: he } = W; if (d(null), he) { const we = Math.round(U / v); if (!we) s.exec("drag-task", { id: o, width: ne, left: P, inProgress: !1 }); else { let ke = {}, be = s.getTask(o); R == "move" ? (ke.start = be.start, ke.end = be.end) : ke[R] = be[R], s.exec("update-task", { id: o, task: ke, diff: we }); } G.current = !0; } T(); } }, [s, T, W, v]), ee = y( (o, R) => { const { clientX: U } = R; if (!t) if (L.current) { const { node: P, x: ne, id: he } = L.current, we = L.current.dx = U - ne, ke = Math.round(we / P.offsetWidth * 100); let be = L.current.progress + ke; L.current.value = be = Math.min( Math.max(0, be), 100 ), s.exec("update-task", { id: he, task: { progress: be }, inProgress: !0 }); } else if (W) { const { mode: P, l: ne, w: he, x: we, id: ke, start: be } = W, de = U - we; if (!be && Math.abs(de) < 20 || P === "start" && he - de < v || P === "end" && he + de < v || P == "move" && (de < 0 && ne + de < 0 || de > 0 && ne + he + de > q)) return; const Le = { ...W, dx: de }; let Me, r; P === "start" ? (Me = ne + de, r = he - de) : P === "end" ? (Me = ne, r = he + de) : P === "move" && (Me = ne + de, r = he); let f = { id: ke, width: r, left: Me, inProgress: !0 }; s.exec("drag-task", f); const g = s.getTask(ke); if (!Le.start && (P == "move" && g.$x == ne || P != "move" && g.$w == he)) { G.current = !0, Z(); return; } Le.start = !0, d(Le); } else { const P = Ee(o); if (P) { const ne = B(P, R); P.style.cursor = ne && !t ? "col-resize" : "pointer"; } } }, [s, t, W, v, q, B] ), oe = y( (o) => { ee(o, o); }, [ee] ), ue = y( (o) => { h ? (o.preventDefault(), ee(o, o.touches[0])) : K.current && (clearTimeout(K.current), K.current = null); }, [h, ee] ), ge = y(() => { Z(); }, [Z]), H = y(() => { V(null), K.current && (clearTimeout(K.current), K.current = null), Z(); }, [Z]); X(() => (window.addEventListener("mouseup", ge), () => { window.removeEventListener("mouseup", ge); }), [ge]); const le = y( (o) => { if (!t) { const R = Ie(o.target); R && !o.target.classList.contains("wx-link") && s.exec("show-editor", { id: R }); } }, [s, t] ), fe = ["e2s", "s2s", "e2e", "s2e"], C = y( (o, R) => fe[(o ? 1 : 0) + (R ? 0 : 2)], [] ), j = y( (o, R) => { const U = A.id, P = A.start; return o === U ? !0 : !!p.find((ne) => ne.target == o && ne.source == U && ne.type === C(P, R)); }, [A, l, C] ), ie = y(() => { A && O(null); }, [A]), ae = y( (o) => { if (G.current) { G.current = !1; return; } const R = Ie(o.target); if (R) { const U = o.target.classList; if (U.contains("wx-link")) { const P = U.contains("wx-left"); if (!A) { O({ id: R, start: P }); return; } A.id !== R && !j(R, P) && s.exec("add-link", { link: { source: A.id, target: R, type: C(A.start, P) } }); } else s.exec("select-task", { id: R, toggle: o.ctrlKey || o.metaKey, range: o.shiftKey }); } ie(); }, [s, A, l] ), Q = y((o) => ({ left: `${o.$x}px`, top: `${o.$y}px`, width: `${o.$w}px`, height: `${o.$h}px` }), []), pe = y((o) => ({ left: `${o.$x_base}px`, top: `${o.$y_base}px`, width: `${o.$w_base}px`, height: `${o.$h_base}px` }), []), ye = y( (o) => { if (h || K.current) return o.preventDefault(), !1; }, [h] ), Ce = y( (o) => { let R = x.some((U) => o === U.id) ? o : "task"; return R !== "task" && R !== "milestone" && R !== "summary" && (R = `task ${R}`), R; }, [x] ), Ne = y( (o) => { s.exec(o.action, o.data); }, [s] ); return /* @__PURE__ */ c( "div", { className: "wx-GKbcLEGA wx-bars", style: { lineHeight: `${$.length ? $[0].$h : 0}px` }, ref: D, onContextMenu: ye, onMouseDown: S, onMouseMove: oe, onTouchStart: te, onTouchMove: ue, onTouchEnd: H, onClick: ae, onDoubleClick: le, onDragStart: (o) => (o.preventDefault(), !1), children: $.map((o) => { if (o.$skip && o.$skip_baseline) return null; const R = `wx-bar wx-${Ce(o.type)}` + (h && W && o.id === W.id ? " wx-touch" : "") + (A && A.id === o.id ? " wx-selected" : "") + (o.$reorder ? " wx-reorder-task" : ""), U = "wx-link wx-left" + (A ? " wx-visible" : "") + (!A || !j(o.id, !0) ? " wx-target" : "") + (A && A.id === o.id && A.start ? " wx-selected" : ""), P = "wx-link wx-right" + (A ? " wx-visible" : "") + (!A || !j(o.id, !1) ? " wx-target" : "") + (A && A.id === o.id && !A.start ? " wx-selected" : ""); return /* @__PURE__ */ xe(ct, { children: [ !o.$skip && /* @__PURE__ */ xe( "div", { className: "wx-GKbcLEGA " + R, style: Q(o), "data-tooltip-id": o.id, "data-id": o.id, tabIndex: z === o.id ? 0 : -1, children: [ t ? null : /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA " + U, children: /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-inner" }) }), o.type !== "milestone" ? /* @__PURE__ */ xe(Ge, { children: [ o.progress ? /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-progress-wrapper", children: /* @__PURE__ */ c( "div", { className: "wx-GKbcLEGA wx-progress-percent", style: { width: `${o.progress}%` } } ) }) : null, t ? null : /* @__PURE__ */ c( "div", { className: "wx-GKbcLEGA wx-progress-marker", style: { left: `calc(${o.progress}% - 10px)` }, children: o.progress } ), n ? /* @__PURE__ */ c(n, { data: o, api: s, onAction: Ne }) : /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-content", children: o.text || "" }) ] }) : /* @__PURE__ */ xe(Ge, { children: [ /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-content" }), n ? /* @__PURE__ */ c(n, { data: o, api: s, onAction: Ne }) : /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-text-out", children: o.text }) ] }), t ? null : /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA " + P, children: /* @__PURE__ */ c("div", { className: "wx-GKbcLEGA wx-inner" }) }) ] } ), I && !o.$skip_baseline ? /* @__PURE__ */ c( "div", { className: "wx-GKbcLEGA wx-baseline" + (o.type === "milestone" ? " wx-milestone" : ""), style: pe(o) } ) : null ] }, o.id); }) } ); } function Gt() { const e = ve(Re), t = F(e, "_links"); return /* @__PURE__ */ c("svg", { className: "wx-dkx3NwEn wx-links", children: (t || []).map((n) => /* @__PURE__ */ c( "polyline", { className: "wx-dkx3NwEn wx-line", points: n.$p }, n.id )) }); } function zt(e) { const { highlightTime: t } = e, n = ve(Re), s = F(n, "_scales"), i = { width: `${(s && s.width) != null ? s.width : 0}px` }; return /* @__PURE__ */ c("div", { className: "wx-ZkvhDKir wx-scale", style: i, children: (s?.rows || []).map((N, p) => /* @__PURE__ */ c( "div", { className: "wx-ZkvhDKir wx-row", style: { height: `${N.height}px` }, children: (N.cells || []).map((l, m) => { const E = t ? t(l.date, l.unit) : "", x = ["wx-cell", l.css, E].filter(Boolean).join(" "); return /* @__PURE__ */ c( "div", { className: "wx-ZkvhDKir " + x, style: { width: `${l.width}px` }, children: l.value }, m ); }) }, p )) }); } function It(e) { const { readonly: t, fullWidth: n, fullHeight: s, taskTemplate: i, cellBorders: N, highlightTime: p } = e, l = ve(Re), [m, E] = _e(l, "_selected"), x = F(l, "scrollLeft"), I = F(l, "scrollTop"), w = F(l, "cellHeight"), a = F(l, "cellWidth"), $ = F(l, "_scales"), v = F(l, "_markers"), G = F(l, "_scrollTask"), A = F(l, "zoom"), [O, W] = ce(), d = Y(null), L = 1 + ($?.rows?.length || 0), h = M(() => { const u = []; return m && m.length && w && m.forEach((S) => { u.push({ height: `${w}px`, top: `${S.$y - 3}px` }); }), u; }, [E, w]), V = M( () => Math.max(O || 0, s), [O, s] ); X(() => { const u = d.current; u && typeof I == "number" && (u.scrollTop = I); }, [I]); const K = () => { q(); }; function q(u) { const S = d.current; if (!S) return; const te = {}; te.left = S.scrollLeft, l.exec("scroll-chart", te); } function J() { const u = d.current, te = Math.ceil((O || 0) / (w || 1)) + 1, Z = Math.floor((u && u.scrollTop || 0) / (w || 1)), ee = Math.max(0, Z - L), oe = Z + te + L, ue = ee * (w || 0); l.exec("render-data", { start: ee, end: oe, from: ue }); } X(() => { J(); }, [O, I, x]); const D = y( (u) => { if (!u) return; const { id: S, mode: te } = u; if (te.toString().indexOf("x") < 0) return; const Z = d.current; if (!Z) return; const { clientWidth: ee } = Z, oe = l.getTask(S); if (oe.$x + oe.$w < Z.scrollLeft) l.exec("scroll-chart", { left: oe.$x - (a || 0) }), Z.scrollLeft = oe.$x - (a || 0); else if (oe.$x >= ee + Z.scrollLeft) { const ue = ee < oe.$w ? a || 0 : oe.$w; l.exec("scroll-chart", { left: oe.$x - ee + ue }), Z.scrollLeft = oe.$x - ee + ue; } }, [l, a, x] ); X(() => { D(G); }, [G]); function b(u) { if (A && (u.ctrlKey || u.metaKey)) { u.preventDefault(); const S = d.current, te = -Math.sign(u.deltaY), Z = u.clientX - (S ? S.getBoundingClientRect().left : 0); l.exec("zoom-scale", { dir: te, offset: Z }); } } function z(u) { const S = p(u.date, u.unit); return S ? { css: S, width: u.width } : null; } const k = M(() => $ && ($.minUnit === "hour" || $.minUnit === "day") && p ? $.rows[$.rows.length - 1].cells.map(z) : null, [$, p]), T = y((u) => { u.eventSource = "chart", l.exec("hotkey", u); }, [l]); X(() => { const u = d.current; if (!u) return; const S = () => W(u.clientHeight); S(); const te = new ResizeObserver(() => S()); return te.observe(u), () => { te.disconnect(); }; }, [d.current]); const B = Y(null); return X(() => { const u = d.current; if (u && !B.current) return B.current = st(u, { keys: { arrowup: !0, arrowdown: !0 }, exec: (S) => T(S) }), () => { B.current?.destroy(), B.current = null; }; }, []), X(() => { const u = d.current; if (!u) return; const S = b; return u.addEventListener("wheel", S), () => { u.removeEventListener("wheel", S); }; }, [b]), /* @__PURE__ */ xe( "div", { className: "wx-mR7v2Xag wx-chart", tabIndex: -1, ref: d, onScroll: K, children: [ /* @__PURE__ */ c(zt, { highlightTime: p, scales: $ }), v && v.length ? /* @__PURE__ */ c( "div", { className: "wx-mR7v2Xag wx-markers", style: { height: `${V}px` }, children: v.map((u, S) => /* @__PURE__ */ c( "div", { className: `wx-mR7v2Xag wx-marker ${u.css || "wx-default"}`, style: { left: `${u.left}px` }, children: /* @__PURE__ */ c("div", { className: "wx-mR7v2Xag wx-content", children: u.text }) }, S )) } ) : null, /* @__PURE__ */ xe( "div", { className: "wx-mR7v2Xag wx-area", style: { width: `${n}px`, height: `${V}px` }, children: [ k ? /* @__PURE__ */ c( "div", { className: "wx-mR7v2Xag wx-gantt-holidays", style: { height: "100%" }, children: k.map( (u, S) => u ? /* @__PURE__ */ c( "div", { className: "wx-mR7v2Xag " + u.css, style: { width: `${u.width}px`, left: `${S * u.width}px` } }, S ) : null ) } ) : null, /* @__PURE__ */ c(Dt, { borders: N }), m && m.length ? m.map( (u, S) => u.$y ? /* @__PURE__ */ c( "div", { className: "wx-mR7v2Xag wx-selected", "data-id": u.id, style: h[S] }, u.id ) : null ) : null, /* @__PURE__ */ c(Gt, {}), /* @__PURE__ */ c(Ht, { readonly: t, taskTemplate: i }) ] } ) ] } ); } function Wt(e) { const { position: t = "after", size: n = 4, dir: s = "x", minValue: i = 0, maxValue: N = 0, onMove: p, onDisplayChange: l, compactMode: m } = e, [E, x] = ze(e.value ?? 0), [I, w] = ze(e.display ?? "all"); function a(D) { let b = 0; t == "center" ? b = n / 2 : t == "before" && (b = n); const z = { size: [n + "px", "auto"], p: [D - b + "px", "0px"], p2: ["auto", "0px"] }; if (s != "x") for (let k in z) z[k] = z[k].reverse(); return z; } const [$, v] = ce(!1), G = Y(0), A = Y(); function O(D) { return s == "x" ? D.clientX : D.clientY; } const W = y((D) => { const b = A.current + O(D) - G.current; (!i || i <= b) && (!N || N >= b) && (x(b), p(b)); }, []), d = y(() => { document.body.style.cursor = "", document.body.style.userSelect = "", v(!1), window.removeEventListener("mousemove", W), window.removeEventListener("mouseup", d); }, [W]), L = M( () => I !== "all" ? "auto" : s == "x" ? "ew-resize" : "ns-resize", [I, s] ), h = y( (D) => { G.current = O(D), A.current = E, v(!0), document.body.style.cursor = L, document.body.style.userSelect = "none", window.addEventListener("mousemove", W), window.addEventListener("mouseup", d); }, [L, W, d, E] ); function V() { let D; m ? D = I === "chart" ? "grid" : "chart" : D = I === "all" ? "chart" : "all", w(D), l(D); } function K() { let D; m ? D = I === "grid" ? "chart" : "grid" : D = I === "all" ? "grid" : "all", w(D), l(D); } const q = M(() => a(E), [E, t, n, s]), J = [ "wx-resizer", `wx-resizer-${s}`, `wx-resizer-display-${I}`, $ ? "wx-resizer-active" : "" ].filter(Boolean).join(" "); return /* @__PURE__ */ xe( "div", { className: "wx-pFykzMlT " + J, onMouseDown: h, style: { width: q.size[0], height: q.size[1], cursor: L }, children: [ /* @__PURE__ */ xe("div", { className: "wx-pFykzMlT wx-button-expand-box", children: [ /* @__PURE__ */ c( "div", { className: "wx-pFykzMlT wx-button-expand-content wx-button-expand-left", children: /* @__PURE__ */ c( "i", { className: "wx-pFykzMlT wxi-menu-left", onClick: V } ) } ), /* @__PURE__ */ c( "div", { className: "wx-pFykzMlT wx-button-expand-content wx-button-expand-right", children: /* @__PURE__ */ c( "i", { className: "wx-pFykzMlT wxi-menu-right", onClick: K } ) } ) ] }), /* @__PURE__ */ c("div", { className: "wx-pFykzMlT wx-resizer-line" }) ] } ); } const _t = 650; function ot(e) { let t; function n() { t = new ResizeObserver((i) => { for (let N of i) if (N.target === document.body) { let p = N.contentRect.width <= _t; e(p); } }), t.observe(document.body); } function s() { t && (t.disconnect(), t = null); } return { observe: n, disconnect: s }; } function Kt(e) { const { taskTemplate: t, readonly: n, cellBorders: s, highlightTime: i, onTableAPIChange: N } = e, p = ve(Re), l = F(p, "_tasks"), m = F(p, "_scales"), E = F(p, "cellHeight"), x = F(p, "columns"), I = F(p, "_scrollTask"), [w, a] = ce(!1); let [$, v] = ce(0); const [G, A] = ce(void 0), [O, W] = ce(void 0), [d, L] = ce(void 0), [h, V] = ce("all"), K = Y(null), q = y( (H) => { a((le) => (H !== le && (H ? (K.current = h, h === "all" && V("grid")) : (!K.current || K.current === "all") && V("all")), H)); }, [h] ); X(() => { const H = ot(q); return H.observe(), () => { H.disconnect(); }; }, [q]); const J = M(() => { let H; return x.every((le) => le.width && !le.flexgrow) ? H = x.reduce((le, fe) => le + parseInt(fe.width), 0) : w && h === "chart" ? H = parseInt(x.find((le) => le.id === "action")?.width) || 50 : H = 440, $ = H, H; }, [x, w, h]); X(() => { v(J); }, [J]); const D = M( () => (G ?? 0) - (d ?? 0), [G, d] ), b = M(() => m.width, [m]), z = M( () => l.length * E, [l, E] ), k = M( () => m.height + z + D, [m, z, D] ), T = M( () => $ + b, [$, b] ), B = Y(null), u = y(() => { Promise.resolve().then(() => { if ((G ?? 0) > (T ?? 0)) { const H = (G ?? 0) - $; p.exec("expand-scale", { minWidth: H }); } }); }, [G, T, $, p]); X(() => { let H; return B.current && (H = new ResizeObserver(u), H.observe(B.current)), () => { H && H.disconnect(); }; }, [B.current, u]); const S = Y(null), te = Y(null), Z = y(() => { const H = S.current; H && p.exec("scroll-chart", { top: H.scrollTop }); }, [p]), ee = Y({ rTasks: [], rScales: { height: 0 }, rCellHeight: 0, scrollSize: 0, ganttDiv: null, ganttHeight: 0 }); X(() => { ee.current = { rTasks: l, rScales: m, rCellHeight: E, scrollSize: D, ganttDiv: S.current, ganttHeight: O ?? 0 }; }, [l, m, E, D, O]); const oe = y( (H) => { if (!H) return; const { rTasks: le, rScales: fe, rCellHeight: C, scrollSize: j, ganttDiv: ie, ganttHeight: ae } = ee.current; if (!ie) return; const { id: Q } = H, pe = le.findIndex((ye) => ye.id === Q); if (pe > -1) { const ye = ae - fe.height, Ce = pe * C, Ne = ie.scrollTop; let o = null; Ce < Ne ? o = Ce : Ce + C > Ne + ye && (o = Ce - ye + C + j), o !== null && (p.exec("scroll-chart", { top: Math.max(o, 0) }), S.current.scrollTop = Math.max(o, 0)); } }, [p] ); X(() => { oe(I); }, [I]), X(() => { const H = S.current; if (!H) return; const le = () => { W(H.offsetHeight), A(H.offsetWidth); }; le(); const fe = new ResizeObserver(le); return fe.observe(H), () => fe.disconnect(); }, [S.current]), X(() => { const H = te.current; if (!H) return; const le = () => { L(H.offsetWidth); }; le(); const fe = new ResizeObserver(le); return fe.observe(H), () => fe.disconnect(); }, [te.current]); const ue = Y(null), ge = Y(null); return X(() => { if (ge.current) return; const H = ue.current; if (H) return ge.current = st(H, { keys: { "ctrl+c": !0, "ctrl+v": !0, "ctrl+x": !0, "ctrl+d": !0, backspace: !0 }, exec: (le) => { le.isInput || p.exec("hotkey", le); } }), () => { ge.current?.destroy(), ge.current = null; }; }, []), /* @__PURE__ */ c("div", { className: "wx-jlbQoHOz wx-gantt", ref: S, onScroll: Z, children: /* @__PURE__ */ c( "div", { className: "wx-jlbQoHOz wx-pseudo-rows", style: { height: k, width: "100%" }, ref: te, children: /* @__PURE__ */ c( "div", { className: "wx-jlbQoHOz wx-stuck", style: { height: O, width: d }, children: /* @__PURE__ */ xe("div", { tabIndex: 0, className: "wx-jlbQoHOz wx-layout", ref: ue, children: [ x.length ? /* @__PURE__ */ xe(Ge, { children: [ /* @__PURE__ */ c( At, { display: h, compactMode: w, columnWidth: J, width: $, readonly: n, fullHeight: z, onTableAPIChange: N } ), /* @__PURE__ */ c( Wt, { value: $, display: h, compactMode: w, minValue: "50", maxValue: "800", onMove: (H) => v(H), onDisplayChange: (H) => V(H) } ) ] }) : null, /* @__PURE__ */ c("div", { className: "wx-jlbQoHOz wx-content", ref: B, children: /* @__PURE__ */ c( It, { readonly: n, fullWidth: b, fullHeight: z, taskTemplate: t, cellBorders: s, highlightTime: i } ) }) ] }) } ) } ) }); } const Pt = (e) => e.split("-").map((t) => t ? t.charAt(0).toUpperCase() + t.slice(1) : "").join(""), Ft = [ { unit: "month", step: 1, format: "MMMM yyy" }, { unit: "day", step: 1, format: "d" } ], un = Ue(function({ taskTemplate: t = null, markers: n = [], taskTypes: s = yt, tasks: i = [], selected: N = [], activeTask: p = null, links: l = [], scales: m = Ft, columns: E = kt, start: x = null, end: I = null, lengthUnit: w = "day", durationUnit: a = "day", cellWidth: $ = 100, cellHeight: v = 38, scaleHeight: G = 36, readonly: A = !1, cellBorders: O = "full", zoom: W = !1, baselines: d = !1, highlightTime: L = null, init: h = null, autoScale: V = !0, unscheduledTasks: K = !1, ...q }, J) { const D = Y(); D.current = q; const b = M(() => new gt(vt), []), z = M(() => b.in, [b]), k = Y(null); k.current === null && (k.current = new pt((Z, ee) => { const oe = "on" + Pt(Z); D.current && D.current[oe] && D.current[oe](ee); }), z.setNext(k.current)); const [T, B] = ce(null), u = Y(null); u.current = T; const S = M( () => ({ getState: b.getState.bind(b), getReactiveState: b.getReactive.bind(b), getStores: () => ({ data: b }), exec: z.exec, setNext: (Z) => (k.current = k.current.setNext(Z), k.current), intercept: z.intercept.bind(z), on: z.on.bind(z), detach: z.detach.bind(z), getTask: b.getTask.bind(b), serialize: b.serialize.bind(b), getTable: (Z) => Z ? new Promise((ee) => setTimeout(() => ee(u.current), 1)) : u.current }), [b, z] ); Ze( J, () => ({ ...S }), [S] ); const te = Y(0); return X(() => { te.current ? b.init({ tasks: i, links: l, start: x, columns: E, end: I, lengthUnit: w, cellWidth: $, cellHeight: v, scaleHeight: G, scales: m, taskTypes: s, zoom: W, selected: N, activeTask: p, baselines: d, autoScale: V, unscheduledTasks: K, markers: n, durationUnit: a }) : h && h(S), te.current++; }, [ i, l, x, E, I, w, $, v, G, m, s, W, N, p, d, V, K, n, a ]), te.current === 0 && b.init({ tasks: i, links: l, start: x, columns: E, end: I, lengthUnit: w, cellWidth: $, cellHeight: v, scaleHeight: G, scales: m, taskTypes: s, zoom: W, selected: N, activeTask: p, baselines: d, autoScale: V, unscheduledTasks: K, markers: n, durationUnit: a }), /* @__PURE__ */ c(Je, { words: We, optional: !0, children: /* @__PURE__ */ c(Re.Provider, { value: S, children: /* @__PURE__ */ c( Kt, { taskTemplate: t, readonly: A, cellBorders: O, highlightTime: L, onTableAPIChange: B } ) }) }); }); function Ot({ appearance: e = "primary", icon: t = "", onClick: n }) { return /* @__PURE__ */ c("button", { className: `wx-TyZ1fHBj wx-button ${e}`, onClick: n, children: t ? /* @__PURE__ */ c("i", { className: `wx-TyZ1fHBj wx-button-icon ${t}` }) : null }); } class Vt { constructor() { this.store = /* @__PURE__ */ new Map(); } limit(t) { this._scope = t; } isActive() { return !this._scope || this._scope(); } add(t, n) { this.store.set(t.toLowerCase().replace(/[ ]/g, ""), n); } } const Ae = [], jt = { subscribe: (e) => { Bt(); const t = new Vt(); return Ae.push(t), e(t), () => { const n = Ae.findIndex((s) => s === t); n >= 0 && Ae.splice(n, 1); }; } }; var Qe = !1; function Bt() { Qe || (Qe = !0, document.addEventListener("keydown", (e) => { if (Ae.length && (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey || e.key.length > 1 || e.key === " ")) { const t = []; e.ctrlKey && t.push("ctrl"), e.altKey && t.push("alt"), e.metaKey && t.push("meta"), e.shiftKey && t.push("shift"); let n = e.key.toLocaleLowerCase(); e.key === " " && (n = "space"), t.push(n); const s = t.join("+"); for (let i = Ae.length - 1; i >= 0; i--) { const N = Ae[i], p = N.store.get(s) || N.store.get(n), l = e.target.tagName; if (p && l !== "INPUT" && l !== "TEXTAREA" && N.isActive()) { p(e), e.preventDefault(); return; } } } })); } function dn({ hotkey: e = null, children: t }) { const n = Y(null), [s, i] = ce(!1), N = Y(s); X(() => { N.current = s; }, [s]); const p = Y(() => { const l = n.current, m = !N.current; m && l ? l.requestFullscreen() : N.current && document.exitFullscreen(), i(m); }); return X(() => { e && jt.subscribe((l) => l.add(e, p.current)); }, []), X(() => { const l = () => { i(document.fullscreenElement === n.current); }; return document.addEventListener("fullscreenchange", l), () => { document.removeEventListener("fullscreenchange", l); }; }, []), /* @__PURE__ */ xe("div", { tabIndex: 0, className: "wx-KG2RkQhB wx-fullscreen", ref: n, children: [ t, /* @__PURE__ */ c("div", { className: "wx-KG2RkQhB wx-fullscreen-icon", children: /* @__PURE__ */ c( Ot, { appearance: "transparent", icon: `wxi-${s ? "collapse" : "expand"}`, onClick: () => p.current() } ) }) ] }); } function fn({ api: e = null, items: t = [...Ve] }) { const n = ve($e.i18n), s = M(() => n || Ke(We), [n]), i = M(() => s.getGroup("gantt"), [s]), N = Se(e, "_selected"), p = Se(e, "_tasks"), l = M(() => t.map((E) => { let x = { ...E, disabled: !1 }; return x.handler = nt(Ve, x.id) ? (I) => tt(e, I.id, null, i) : x.handler, x.text && (x.text = i(x.text)), x.menuText && (x.menuText = i(x.menuText)), x; }), [t, e, i]), m = M(() => e && N?.length ? l.map((E) => { if (!E.check) return E; const x = N.some( (I) => !E.check(I, p) ); return { ...E, disabled: x }; }) : [{ ...l[0], disabled: !1 }], [e, N, p, l]); return n ? /* @__PURE__ */ c(Be, { items: m }) : /* @__PURE__ */ c($e.i18n.Provider, { value: s, children: /* @__PURE__ */ c(Be, { items: m }) }); } const hn = Ue(function({ options: t, api: n = null, resolver: s = null, filter: i = null, at: N = "point", children: p, onClick: l, css: m }, E) { const x = M(() => t ?? [...je], [t]), [I] = ze(x), w = Y(null), a = Y(null), $ = ve($e.i18n), v = M(() => $ || Ke({ ...We, ...rt }), [$]), G = M(() => v.getGroup("gantt"), [v]), A = Se(n, "taskTypes"), O = Se(n, "_tasks"), W = Se(n, "selected"), d = Se(n, "_selected"); X(() => { n && (n.on("scroll-chart", () => { w.current && w.current.show && w.current.show(); }), n.on("drag-task", () => { w.current && w.current.show && w.current.show(); })); }, [n]); function L(k) { return k.map((T) => (T = { ...T }, T.text && (T.text = G(T.text)), T.subtext && (T.subtext = G(T.subtext)), T.data