@object-ui/plugin-gantt 5.0.1 → 5.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @object-ui/plugin-gantt
2
2
 
3
+ ## 5.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - cab6a93: **plugin-grid:** column summary footer now formats values using the
8
+ column's type metadata. Currency columns render `Sum: $1,760,000.00`
9
+ instead of bare `Sum: 1,760,000`; percent columns honor `0–1` vs
10
+ `0–100` value ranges; avg uses two fraction digits. `useColumnSummary`
11
+ accepts an optional `fieldMetadata` map (typically `objectSchema.fields`)
12
+ so per-field `type`, `currency`, `defaultCurrency`, `precision` are
13
+ respected.
14
+
15
+ **plugin-gantt:** added safe-fallback `useGanttTranslation` hook. All
16
+ hardcoded toolbar `aria-label`s and the `Task Name` / `Start` / `End` /
17
+ `Today` column-header strings now flow through `t('gantt.*')`. A new
18
+ `gantt.*` section is exported from the en/zh/ja/ko/de/fr/es/pt/ru/ar
19
+ locales.
20
+
21
+ **app-shell:** `ReportView` no longer hardcodes the `Edit` button label
22
+ or the `Loading report…` fallback — they now use `common.edit` and
23
+ `common.loading`.
24
+
25
+ **i18n:** added top-level `gantt` section (with English fallbacks in
26
+ non-en/zh locales) and the `common.addToFavorites` /
27
+ `common.removeFromFavorites` keys across all ten built-in locales so
28
+ the `builtInLocales` parity tests pass.
29
+ - @object-ui/components@5.0.2
30
+ - @object-ui/fields@5.0.2
31
+ - @object-ui/react@5.0.2
32
+ - @object-ui/plugin-detail@5.0.2
33
+ - @object-ui/types@5.0.2
34
+ - @object-ui/core@5.0.2
35
+
3
36
  ## 5.0.1
4
37
 
5
38
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,32 +1,60 @@
1
1
  import * as e from "react";
2
2
  import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
3
3
  import { ComponentRegistry as a, buildExpandFields as o, extractRecords as s } from "@object-ui/core";
4
- import { useNavigationOverlay as c, useSchemaContext as l } from "@object-ui/react";
5
- import { GanttConfigSchema as u } from "@objectstack/spec/ui";
6
- import { RecordDetailDrawer as d, deriveRecordPageHref as f } from "@object-ui/plugin-detail";
7
- import { AlertDialog as p, AlertDialogAction as m, AlertDialogCancel as h, AlertDialogContent as ee, AlertDialogDescription as g, AlertDialogFooter as _, AlertDialogHeader as v, AlertDialogTitle as y, Button as b, cn as x, useResizeObserver as S } from "@object-ui/components";
8
- import { getSemanticColorName as C, getSemanticHex as w } from "@object-ui/fields";
9
- import { CalendarDays as T, ChevronLeft as E, ChevronRight as D, PanelLeft as O, PanelLeftClose as te, ZoomIn as k, ZoomOut as ne } from "lucide-react";
10
- import { Fragment as A, jsx as j, jsxs as M } from "react/jsx-runtime";
4
+ import { useNavigationOverlay as c, useObjectTranslation as l, useSchemaContext as u } from "@object-ui/react";
5
+ import { GanttConfigSchema as d } from "@objectstack/spec/ui";
6
+ import { RecordDetailDrawer as f, deriveRecordPageHref as p } from "@object-ui/plugin-detail";
7
+ import { AlertDialog as m, AlertDialogAction as h, AlertDialogCancel as g, AlertDialogContent as _, AlertDialogDescription as v, AlertDialogFooter as y, AlertDialogHeader as b, AlertDialogTitle as x, Button as S, cn as C, useResizeObserver as w } from "@object-ui/components";
8
+ import { getSemanticColorName as T, getSemanticHex as E } from "@object-ui/fields";
9
+ import { CalendarDays as ee, ChevronLeft as D, ChevronRight as O, PanelLeft as te, PanelLeftClose as k, ZoomIn as ne, ZoomOut as A } from "lucide-react";
10
+ import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
11
+ //#region src/useGanttTranslation.ts
12
+ var P = {
13
+ "gantt.column.taskName": "Task Name",
14
+ "gantt.column.start": "Start",
15
+ "gantt.column.end": "End",
16
+ "gantt.toolbar.prevPeriod": "Previous period",
17
+ "gantt.toolbar.nextPeriod": "Next period",
18
+ "gantt.toolbar.zoomIn": "Zoom in",
19
+ "gantt.toolbar.zoomOut": "Zoom out",
20
+ "gantt.toolbar.jumpToToday": "Jump to today",
21
+ "gantt.toolbar.today": "Today",
22
+ "gantt.toolbar.showTaskList": "Show task list",
23
+ "gantt.toolbar.hideTaskList": "Hide task list"
24
+ }, F = "gantt.column.taskName";
25
+ function I(e, t) {
26
+ let n = P[e] || e;
27
+ if (t) for (let [e, r] of Object.entries(t)) n = n.replace(`{{${e}}}`, String(r));
28
+ return n;
29
+ }
30
+ function re() {
31
+ try {
32
+ let e = l();
33
+ return e.t(F) === F ? { t: I } : { t: e.t };
34
+ } catch {
35
+ return { t: I };
36
+ }
37
+ }
38
+ //#endregion
11
39
  //#region src/GanttView.tsx
12
- function N(e) {
40
+ function L(e) {
13
41
  return e < 640 ? 35 : e < 1024 ? 50 : 60;
14
42
  }
15
- function P(e) {
43
+ function ie(e) {
16
44
  return e < 640 ? 140 : e < 1024 ? 220 : 320;
17
45
  }
18
- function F(e) {
46
+ function R(e) {
19
47
  return e >= 280;
20
48
  }
21
- function I(e) {
49
+ function ae(e) {
22
50
  return e < 640 ? 32 : 40;
23
51
  }
24
- function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a, className: o, inlineEdit: s = !1 }) {
25
- let [c, l] = e.useState(/* @__PURE__ */ new Date()), u = e.useRef(null), { width: d } = S(u), f = d || (typeof window < "u" ? window.innerWidth : 1024), p = f < 640, m = I(f), h = N(f), [ee, g] = e.useState(null), _ = ee ?? h, [v, y] = e.useState(!1), C = e.useRef(!1);
52
+ function z({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a, className: o, inlineEdit: s = !1 }) {
53
+ let { t: c } = re(), [l, u] = e.useState(/* @__PURE__ */ new Date()), d = e.useRef(null), { width: f } = w(d), p = f || (typeof window < "u" ? window.innerWidth : 1024), m = p < 640, h = ae(p), g = L(p), [_, v] = e.useState(null), y = _ ?? g, [b, x] = e.useState(!1), T = e.useRef(!1);
26
54
  e.useEffect(() => {
27
- !C.current && p && (y(!0), C.current = !0);
28
- }, [p]);
29
- let w = v ? 0 : P(f), L = F(w), [re, R] = e.useState(null), [z, B] = e.useState({}), [V, H] = e.useState(null), U = e.useRef(null);
55
+ !T.current && m && (x(!0), T.current = !0);
56
+ }, [m]);
57
+ let E = b ? 0 : ie(p), P = R(E), [F, I] = e.useState(null), [z, B] = e.useState({}), [V, H] = e.useState(null), U = e.useRef(null);
30
58
  e.useEffect(() => {
31
59
  U.current = V;
32
60
  }, [V]);
@@ -42,7 +70,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
42
70
  let e = (e) => {
43
71
  let t = U.current;
44
72
  if (!t) return;
45
- let n = Math.round((e.clientX - t.originClientX) / Math.max(_, 1));
73
+ let n = Math.round((e.clientX - t.originClientX) / Math.max(y, 1));
46
74
  n !== t.dayDelta && H({
47
75
  ...t,
48
76
  dayDelta: n
@@ -71,7 +99,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
71
99
  };
72
100
  }, [
73
101
  V,
74
- _,
102
+ y,
75
103
  t,
76
104
  a,
77
105
  G
@@ -103,65 +131,65 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
103
131
  isWeekend: t.getDay() === 0 || t.getDay() === 6
104
132
  }), t.setDate(t.getDate() + 1);
105
133
  return e;
106
- }, [q]), Y = e.useRef(null), X = e.useRef(null), ie = e.useRef(null), Z = e.useRef(null), Q = e.useRef(null), ae = e.useCallback((e) => {
134
+ }, [q]), Y = e.useRef(null), X = e.useRef(null), oe = e.useRef(null), Z = e.useRef(null), Q = e.useRef(null), se = e.useCallback((e) => {
107
135
  if (e.touches.length === 2) {
108
136
  let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY;
109
137
  Q.current = {
110
138
  baseDistance: Math.max(1, Math.sqrt(t * t + n * n)),
111
- baseColumn: _
139
+ baseColumn: y
112
140
  };
113
141
  }
114
- }, [_]), oe = e.useCallback((e) => {
142
+ }, [y]), ce = e.useCallback((e) => {
115
143
  if (e.touches.length !== 2 || !Q.current) return;
116
144
  let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY, r = Math.max(1, Math.sqrt(t * t + n * n)) / Q.current.baseDistance;
117
- g(Math.max(15, Math.min(120, Math.round(Q.current.baseColumn * r))));
118
- }, []), se = e.useCallback(() => {
145
+ v(Math.max(15, Math.min(120, Math.round(Q.current.baseColumn * r))));
146
+ }, []), le = e.useCallback(() => {
119
147
  Q.current = null;
120
148
  }, []), $ = e.useMemo(() => {
121
149
  let e = /* @__PURE__ */ new Date();
122
150
  if (e < q.start || e > q.end) return null;
123
151
  let t = (e.getTime() - q.start.getTime()) / (1440 * 60 * 1e3);
124
- return Math.round(t * _);
125
- }, [q, _]), ce = e.useCallback(() => {
152
+ return Math.round(t * y);
153
+ }, [q, y]), ue = e.useCallback(() => {
126
154
  if ($ == null || !Z.current) return;
127
155
  let e = Math.max(0, $ - Z.current.clientWidth / 2);
128
156
  Z.current.scrollTo({
129
157
  left: e,
130
158
  behavior: "smooth"
131
159
  });
132
- }, [$]), le = (e) => {
160
+ }, [$]), de = (e) => {
133
161
  Y.current && (Y.current.scrollLeft = e.currentTarget.scrollLeft), X.current && (X.current.scrollTop = e.currentTarget.scrollTop);
134
- }, ue = (e) => {
162
+ }, fe = (e) => {
135
163
  q.end.getTime() - q.start.getTime();
136
- let t = _, n = 1e3 * 60 * 60 * 24, r = e.start.getTime() - q.start.getTime(), i = e.end.getTime() - e.start.getTime();
164
+ let t = y, n = 1e3 * 60 * 60 * 24, r = e.start.getTime() - q.start.getTime(), i = e.end.getTime() - e.start.getTime();
137
165
  return {
138
166
  left: r / n * t,
139
167
  width: Math.max(i / n * t, t)
140
168
  };
141
169
  };
142
- return /* @__PURE__ */ M("div", {
143
- ref: u,
144
- className: x("flex flex-col h-full bg-background overflow-hidden min-w-0", o),
145
- children: [/* @__PURE__ */ M("div", {
170
+ return /* @__PURE__ */ N("div", {
171
+ ref: d,
172
+ className: C("flex flex-col h-full bg-background overflow-hidden min-w-0", o),
173
+ children: [/* @__PURE__ */ N("div", {
146
174
  className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card",
147
- children: [/* @__PURE__ */ M("div", {
175
+ children: [/* @__PURE__ */ N("div", {
148
176
  className: "flex items-center gap-2",
149
177
  children: [
150
- /* @__PURE__ */ j(b, {
178
+ /* @__PURE__ */ M(S, {
151
179
  variant: "ghost",
152
180
  size: "icon",
153
181
  className: "h-8 w-8",
154
- "aria-label": "Previous period",
155
- children: /* @__PURE__ */ j(E, { className: "h-4 w-4" })
182
+ "aria-label": c("gantt.toolbar.prevPeriod"),
183
+ children: /* @__PURE__ */ M(D, { className: "h-4 w-4" })
156
184
  }),
157
- /* @__PURE__ */ j(b, {
185
+ /* @__PURE__ */ M(S, {
158
186
  variant: "ghost",
159
187
  size: "icon",
160
188
  className: "h-8 w-8",
161
- "aria-label": "Next period",
162
- children: /* @__PURE__ */ j(D, { className: "h-4 w-4" })
189
+ "aria-label": c("gantt.toolbar.nextPeriod"),
190
+ children: /* @__PURE__ */ M(O, { className: "h-4 w-4" })
163
191
  }),
164
- /* @__PURE__ */ j("span", {
192
+ /* @__PURE__ */ M("span", {
165
193
  className: "font-semibold text-xs sm:text-sm",
166
194
  children: q.start.toLocaleDateString(void 0, {
167
195
  month: "long",
@@ -169,108 +197,108 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
169
197
  })
170
198
  })
171
199
  ]
172
- }), /* @__PURE__ */ M("div", {
200
+ }), /* @__PURE__ */ N("div", {
173
201
  className: "flex items-center gap-2",
174
202
  children: [
175
- /* @__PURE__ */ M("div", {
203
+ /* @__PURE__ */ N("div", {
176
204
  className: "flex bg-muted rounded-md p-1",
177
- children: [/* @__PURE__ */ j(b, {
205
+ children: [/* @__PURE__ */ M(S, {
178
206
  variant: "ghost",
179
207
  size: "icon",
180
208
  className: "h-6 w-6",
181
- onClick: () => g(Math.max(15, _ - 10)),
182
- "aria-label": "Zoom out",
183
- children: /* @__PURE__ */ j(ne, { className: "h-3 w-3" })
184
- }), /* @__PURE__ */ j(b, {
209
+ onClick: () => v(Math.max(15, y - 10)),
210
+ "aria-label": c("gantt.toolbar.zoomOut"),
211
+ children: /* @__PURE__ */ M(A, { className: "h-3 w-3" })
212
+ }), /* @__PURE__ */ M(S, {
185
213
  variant: "ghost",
186
214
  size: "icon",
187
215
  className: "h-6 w-6",
188
- onClick: () => g(Math.min(120, _ + 10)),
189
- "aria-label": "Zoom in",
190
- children: /* @__PURE__ */ j(k, { className: "h-3 w-3" })
216
+ onClick: () => v(Math.min(120, y + 10)),
217
+ "aria-label": c("gantt.toolbar.zoomIn"),
218
+ children: /* @__PURE__ */ M(ne, { className: "h-3 w-3" })
191
219
  })]
192
220
  }),
193
- /* @__PURE__ */ j(b, {
221
+ /* @__PURE__ */ M(S, {
194
222
  variant: "ghost",
195
223
  size: "icon",
196
224
  className: "h-8 w-8",
197
- onClick: () => y((e) => !e),
198
- "aria-label": v ? "Show task list" : "Hide task list",
199
- "aria-pressed": v,
225
+ onClick: () => x((e) => !e),
226
+ "aria-label": c(b ? "gantt.toolbar.showTaskList" : "gantt.toolbar.hideTaskList"),
227
+ "aria-pressed": b,
200
228
  "data-testid": "gantt-toggle-task-list",
201
- children: j(v ? O : te, { className: "h-4 w-4" })
229
+ children: M(b ? te : k, { className: "h-4 w-4" })
202
230
  }),
203
- /* @__PURE__ */ j(b, {
231
+ /* @__PURE__ */ M(S, {
204
232
  variant: "ghost",
205
233
  size: "icon",
206
234
  className: "h-8 w-8",
207
- onClick: ce,
235
+ onClick: ue,
208
236
  disabled: $ == null,
209
- "aria-label": "Jump to today",
237
+ "aria-label": c("gantt.toolbar.jumpToToday"),
210
238
  "data-testid": "gantt-jump-today",
211
- children: /* @__PURE__ */ j(T, { className: "h-4 w-4" })
239
+ children: /* @__PURE__ */ M(ee, { className: "h-4 w-4" })
212
240
  })
213
241
  ]
214
242
  })]
215
- }), /* @__PURE__ */ M("div", {
243
+ }), /* @__PURE__ */ N("div", {
216
244
  className: "flex flex-col flex-1 overflow-hidden",
217
- children: [/* @__PURE__ */ M("div", {
245
+ children: [/* @__PURE__ */ N("div", {
218
246
  className: "flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]",
219
- children: [/* @__PURE__ */ M("div", {
247
+ children: [/* @__PURE__ */ N("div", {
220
248
  className: "flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm",
221
249
  style: {
222
- width: w,
223
- minWidth: w
250
+ width: E,
251
+ minWidth: E
224
252
  },
225
- children: [/* @__PURE__ */ j("div", {
253
+ children: [/* @__PURE__ */ M("div", {
226
254
  className: "flex-1 truncate",
227
- children: "Task Name"
228
- }), L && /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j("div", {
255
+ children: c("gantt.column.taskName")
256
+ }), P && /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M("div", {
229
257
  className: "w-16 sm:w-20 text-right",
230
- children: "Start"
231
- }), /* @__PURE__ */ j("div", {
258
+ children: c("gantt.column.start")
259
+ }), /* @__PURE__ */ M("div", {
232
260
  className: "w-16 sm:w-20 text-right",
233
- children: "End"
261
+ children: c("gantt.column.end")
234
262
  })] })]
235
- }), /* @__PURE__ */ j("div", {
263
+ }), /* @__PURE__ */ M("div", {
236
264
  className: "flex-1 overflow-hidden",
237
265
  ref: Y,
238
- children: /* @__PURE__ */ j("div", {
266
+ children: /* @__PURE__ */ M("div", {
239
267
  className: "flex h-full",
240
- style: { width: J.length * _ },
241
- children: J.map((e, t) => /* @__PURE__ */ M("div", {
242
- className: x("flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full", e.isWeekend && "bg-muted/50"),
268
+ style: { width: J.length * y },
269
+ children: J.map((e, t) => /* @__PURE__ */ N("div", {
270
+ className: C("flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full", e.isWeekend && "bg-muted/50"),
243
271
  style: {
244
- width: _,
245
- minWidth: _
272
+ width: y,
273
+ minWidth: y
246
274
  },
247
- children: [/* @__PURE__ */ j("span", {
275
+ children: [/* @__PURE__ */ M("span", {
248
276
  className: "font-medium text-foreground",
249
277
  children: e.label
250
- }), /* @__PURE__ */ j("span", {
278
+ }), /* @__PURE__ */ M("span", {
251
279
  className: "text-[10px] opacity-70",
252
280
  children: e.date.toLocaleDateString(void 0, { weekday: "narrow" })
253
281
  })]
254
282
  }, t))
255
283
  })
256
284
  })]
257
- }), /* @__PURE__ */ M("div", {
285
+ }), /* @__PURE__ */ N("div", {
258
286
  className: "flex flex-1 overflow-hidden",
259
- children: [/* @__PURE__ */ j("div", {
287
+ children: [/* @__PURE__ */ M("div", {
260
288
  className: "overflow-hidden border-r bg-card z-10 shadow-sm",
261
289
  ref: X,
262
290
  style: {
263
- width: w,
264
- minWidth: w
291
+ width: E,
292
+ minWidth: E
265
293
  },
266
294
  children: t.map((e) => {
267
- let t = s && re === e.id;
268
- return /* @__PURE__ */ M("div", {
295
+ let t = s && F === e.id;
296
+ return /* @__PURE__ */ N("div", {
269
297
  className: "group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",
270
- style: { height: m },
298
+ style: { height: h },
271
299
  onClick: () => !t && i?.(e),
272
300
  onDoubleClick: () => {
273
- s && a && (R(e.id), B({
301
+ s && a && (I(e.id), B({
274
302
  title: e.title,
275
303
  start: e.start.toLocaleDateString("en-CA"),
276
304
  end: e.end.toLocaleDateString("en-CA"),
@@ -278,12 +306,12 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
278
306
  }));
279
307
  },
280
308
  children: [
281
- /* @__PURE__ */ M("div", {
309
+ /* @__PURE__ */ N("div", {
282
310
  className: "flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2",
283
- children: [/* @__PURE__ */ j("div", {
311
+ children: [/* @__PURE__ */ M("div", {
284
312
  className: "w-2 h-2 rounded-full shrink-0",
285
313
  style: { backgroundColor: e.color || "#3b82f6" }
286
- }), t ? /* @__PURE__ */ j("input", {
314
+ }), t ? /* @__PURE__ */ M("input", {
287
315
  className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
288
316
  value: z.title || "",
289
317
  onChange: (e) => B((t) => ({
@@ -296,16 +324,16 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
296
324
  start: new Date(z.start),
297
325
  end: new Date(z.end),
298
326
  progress: Number(z.progress) || 0
299
- }), R(null)) : t.key === "Escape" && R(null);
327
+ }), I(null)) : t.key === "Escape" && I(null);
300
328
  },
301
329
  onClick: (e) => e.stopPropagation(),
302
330
  autoFocus: !0
303
- }) : /* @__PURE__ */ M("span", {
331
+ }) : /* @__PURE__ */ N("span", {
304
332
  className: "flex flex-col min-w-0",
305
- children: [/* @__PURE__ */ j("span", {
333
+ children: [/* @__PURE__ */ M("span", {
306
334
  className: "truncate",
307
335
  children: e.title
308
- }), /* @__PURE__ */ M("span", {
336
+ }), /* @__PURE__ */ N("span", {
309
337
  className: "text-[10px] text-muted-foreground sm:hidden",
310
338
  children: [
311
339
  e.start.toLocaleDateString(void 0, {
@@ -321,11 +349,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
321
349
  })]
322
350
  })]
323
351
  }),
324
- /* @__PURE__ */ j("div", {
352
+ /* @__PURE__ */ M("div", {
325
353
  className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
326
- hidden: !L,
327
- style: L ? void 0 : { display: "none" },
328
- children: t ? /* @__PURE__ */ j("input", {
354
+ hidden: !P,
355
+ style: P ? void 0 : { display: "none" },
356
+ children: t ? /* @__PURE__ */ M("input", {
329
357
  type: "date",
330
358
  className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
331
359
  value: z.start || "",
@@ -339,11 +367,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
339
367
  day: "numeric"
340
368
  })
341
369
  }),
342
- /* @__PURE__ */ j("div", {
370
+ /* @__PURE__ */ M("div", {
343
371
  className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
344
- hidden: !L,
345
- style: L ? void 0 : { display: "none" },
346
- children: t ? /* @__PURE__ */ j("input", {
372
+ hidden: !P,
373
+ style: P ? void 0 : { display: "none" },
374
+ children: t ? /* @__PURE__ */ M("input", {
347
375
  type: "date",
348
376
  className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
349
377
  value: z.end || "",
@@ -360,56 +388,56 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
360
388
  ]
361
389
  }, e.id);
362
390
  })
363
- }), /* @__PURE__ */ j("div", {
391
+ }), /* @__PURE__ */ M("div", {
364
392
  className: "flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]",
365
393
  ref: (e) => {
366
- ie.current = e, Z.current = e;
394
+ oe.current = e, Z.current = e;
367
395
  },
368
- onScroll: le,
369
- onTouchStart: ae,
370
- onTouchMove: oe,
371
- onTouchEnd: se,
396
+ onScroll: de,
397
+ onTouchStart: se,
398
+ onTouchMove: ce,
399
+ onTouchEnd: le,
372
400
  "data-testid": "gantt-timeline",
373
- children: /* @__PURE__ */ M("div", {
401
+ children: /* @__PURE__ */ N("div", {
374
402
  className: "relative",
375
- style: { width: J.length * _ },
376
- children: [$ != null && /* @__PURE__ */ j("div", {
403
+ style: { width: J.length * y },
404
+ children: [$ != null && /* @__PURE__ */ M("div", {
377
405
  className: "absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none",
378
406
  style: { left: $ },
379
407
  "data-testid": "gantt-today-marker",
380
- "aria-label": "Today",
381
- children: /* @__PURE__ */ j("div", {
408
+ "aria-label": c("gantt.toolbar.today"),
409
+ children: /* @__PURE__ */ M("div", {
382
410
  className: "absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap",
383
- children: "Today"
411
+ children: c("gantt.toolbar.today")
384
412
  })
385
- }), /* @__PURE__ */ M("div", {
413
+ }), /* @__PURE__ */ N("div", {
386
414
  className: "relative",
387
415
  children: [
388
- /* @__PURE__ */ j("div", {
416
+ /* @__PURE__ */ M("div", {
389
417
  className: "absolute inset-0 flex pointer-events-none z-0",
390
- children: J.map((e, t) => /* @__PURE__ */ j("div", {
391
- className: x("border-r h-full", e.isWeekend && "bg-muted/20"),
418
+ children: J.map((e, t) => /* @__PURE__ */ M("div", {
419
+ className: C("border-r h-full", e.isWeekend && "bg-muted/20"),
392
420
  style: {
393
- width: _,
394
- minWidth: _
421
+ width: y,
422
+ minWidth: y
395
423
  }
396
424
  }, t))
397
425
  }),
398
426
  t.map((e) => {
399
- let t = ue(e), n = V?.taskId === e.id, r = t;
427
+ let t = fe(e), n = V?.taskId === e.id, r = t;
400
428
  if (n && V) {
401
429
  let t = G(V);
402
- r = ue({
430
+ r = fe({
403
431
  ...e,
404
432
  start: t.start,
405
433
  end: t.end
406
434
  });
407
435
  }
408
436
  let o = !!a;
409
- return /* @__PURE__ */ M("div", {
437
+ return /* @__PURE__ */ N("div", {
410
438
  className: "relative border-b hover:bg-black/5",
411
- style: { height: m },
412
- children: [n && /* @__PURE__ */ j("div", {
439
+ style: { height: h },
440
+ children: [n && /* @__PURE__ */ M("div", {
413
441
  className: "absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none",
414
442
  style: {
415
443
  left: t.left,
@@ -417,8 +445,8 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
417
445
  opacity: .35
418
446
  },
419
447
  "aria-hidden": "true"
420
- }), /* @__PURE__ */ M("div", {
421
- className: x("absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none", o ? "cursor-grab active:cursor-grabbing" : "cursor-pointer", n && "ring-2 ring-primary/60 brightness-110 z-10"),
448
+ }), /* @__PURE__ */ N("div", {
449
+ className: C("absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none", o ? "cursor-grab active:cursor-grabbing" : "cursor-pointer", n && "ring-2 ring-primary/60 brightness-110 z-10"),
422
450
  style: {
423
451
  left: r.left,
424
452
  width: r.width,
@@ -432,14 +460,14 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
432
460
  t.button === 0 && K(e, "move", t);
433
461
  } : void 0,
434
462
  children: [
435
- o && r.width >= 14 && /* @__PURE__ */ M(A, { children: [/* @__PURE__ */ j("div", {
463
+ o && r.width >= 14 && /* @__PURE__ */ N(j, { children: [/* @__PURE__ */ M("div", {
436
464
  className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
437
465
  "data-testid": `gantt-task-resize-left-${e.id}`,
438
466
  onPointerDown: (t) => {
439
467
  t.button === 0 && K(e, "resize-left", t);
440
468
  },
441
469
  onClick: (e) => e.stopPropagation()
442
- }), /* @__PURE__ */ j("div", {
470
+ }), /* @__PURE__ */ M("div", {
443
471
  className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
444
472
  "data-testid": `gantt-task-resize-right-${e.id}`,
445
473
  onPointerDown: (t) => {
@@ -447,11 +475,11 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
447
475
  },
448
476
  onClick: (e) => e.stopPropagation()
449
477
  })] }),
450
- e.progress > 0 && /* @__PURE__ */ j("div", {
478
+ e.progress > 0 && /* @__PURE__ */ M("div", {
451
479
  className: "absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none",
452
480
  style: { width: `${e.progress}%` }
453
481
  }),
454
- /* @__PURE__ */ j("span", {
482
+ /* @__PURE__ */ M("span", {
455
483
  className: "text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none",
456
484
  children: n ? `${G(V).start.toLocaleDateString(void 0, {
457
485
  month: "numeric",
@@ -465,10 +493,10 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
465
493
  })]
466
494
  }, e.id);
467
495
  }),
468
- /* @__PURE__ */ j("div", {
496
+ /* @__PURE__ */ M("div", {
469
497
  className: "absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none",
470
- style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) * _ },
471
- children: /* @__PURE__ */ j("div", { className: "w-2 h-2 rounded-full bg-red-500 -ml-[3px]" })
498
+ style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) * y },
499
+ children: /* @__PURE__ */ M("div", { className: "w-2 h-2 rounded-full bg-red-500 -ml-[3px]" })
472
500
  })
473
501
  ]
474
502
  })]
@@ -480,7 +508,7 @@ function L({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a
480
508
  }
481
509
  //#endregion
482
510
  //#region src/ObjectGantt.tsx
483
- function re(e) {
511
+ function B(e) {
484
512
  return e.data ? e.data : e.staticData ? {
485
513
  provider: "value",
486
514
  items: e.staticData
@@ -489,7 +517,7 @@ function re(e) {
489
517
  object: e.objectName
490
518
  } : null;
491
519
  }
492
- function R(e) {
520
+ function V(e) {
493
521
  if (e) {
494
522
  if (typeof e == "string") {
495
523
  let t = e.split(" "), n = t[0], r = t[1]?.toLowerCase() === "desc" ? "desc" : "asc";
@@ -498,7 +526,7 @@ function R(e) {
498
526
  if (Array.isArray(e)) return e.reduce((e, t) => (t.field && t.order && (e[t.field] = t.order), e), {});
499
527
  }
500
528
  }
501
- function z(e) {
529
+ function H(e) {
502
530
  let t = null;
503
531
  if (e.startDateField && e.endDateField) return t = {
504
532
  startDateField: e.startDateField,
@@ -509,33 +537,33 @@ function z(e) {
509
537
  colorField: e.colorField
510
538
  }, t;
511
539
  if (e.gantt && (t = e.gantt), t) {
512
- let e = u.safeParse(t);
540
+ let e = d.safeParse(t);
513
541
  return e.success || console.warn("[ObjectGantt] Invalid gantt configuration:", e.error.format()), t;
514
542
  }
515
543
  return null;
516
544
  }
517
- var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b, ...x }) => {
518
- let [S, T] = i([]), [E, D] = i(!0), [O, te] = i(null), [k, ne] = i(null), N = re(e), P = r(() => N, [JSON.stringify(N)]), F = z(e), I = P?.provider === "value";
545
+ var U = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: d, ...S }) => {
546
+ let [C, w] = i([]), [ee, D] = i(!0), [O, te] = i(null), [k, ne] = i(null), A = B(e), P = r(() => A, [JSON.stringify(A)]), F = H(e), I = P?.provider === "value";
519
547
  n(() => {
520
548
  (async () => {
521
549
  try {
522
- if (D(!0), x.data && Array.isArray(x.data)) {
523
- T(x.data), D(!1);
550
+ if (D(!0), S.data && Array.isArray(S.data)) {
551
+ w(S.data), D(!1);
524
552
  return;
525
553
  }
526
554
  if (I && P?.provider === "value") {
527
- T(P.items), D(!1);
555
+ w(P.items), D(!1);
528
556
  return;
529
557
  }
530
558
  if (!a || typeof a.find != "function") throw Error("DataSource required for object/api providers");
531
559
  if (P?.provider === "object") {
532
560
  let t = P.object, n = o(k?.fields);
533
- T(s(await a.find(t, {
561
+ w(s(await a.find(t, {
534
562
  $filter: e.filter,
535
- $orderby: R(e.sort),
563
+ $orderby: V(e.sort),
536
564
  ...n.length > 0 ? { $expand: n } : {}
537
565
  })));
538
- } else P?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"), T([]));
566
+ } else P?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"), w([]));
539
567
  D(!1);
540
568
  } catch (e) {
541
569
  te(e), D(!1);
@@ -565,8 +593,8 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
565
593
  I,
566
594
  P
567
595
  ]);
568
- let B = r(() => {
569
- if (!F || !S.length) return [];
596
+ let re = r(() => {
597
+ if (!F || !C.length) return [];
570
598
  let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } = F, o = (e, t) => {
571
599
  if (!t) return;
572
600
  let n = t.split("."), r = e;
@@ -591,13 +619,13 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
591
619
  for (let e of t) if (e != null && String(e).trim() !== "") return String(e);
592
620
  return "Untitled";
593
621
  };
594
- return S.map((n, o) => {
622
+ return C.map((n, o) => {
595
623
  let c = n[e], l = n[t], u = s(n), d = r ? n[r] : 0, f = i ? n[i] : [], p = a ? n[a] : void 0;
596
624
  if (!p) {
597
625
  let e = n.status ?? n.state ?? n.priority ?? n.severity;
598
626
  if (e != null && e !== "") {
599
- let t = C(void 0, e);
600
- t && (p = w(t));
627
+ let t = T(void 0, e);
628
+ t && (p = E(t));
601
629
  }
602
630
  }
603
631
  return {
@@ -611,14 +639,14 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
611
639
  data: n
612
640
  };
613
641
  }).filter((e) => !isNaN(e.start.getTime()) && !isNaN(e.end.getTime()));
614
- }, [S, F]), V = e.navigation ?? {
642
+ }, [C, F]), L = e.navigation ?? {
615
643
  mode: "drawer",
616
644
  width: "min(960px, 60vw)"
617
- }, H = V.mode === "drawer" || V.mode === "modal" || V.mode === "split" || V.mode === "popover", U = c({
618
- navigation: V,
645
+ }, ie = L.mode === "drawer" || L.mode === "modal" || L.mode === "split" || L.mode === "popover", R = c({
646
+ navigation: L,
619
647
  objectName: e.objectName,
620
- onRowClick: H ? void 0 : b
621
- }), W = t(async (t, n) => {
648
+ onRowClick: ie ? void 0 : d
649
+ }), ae = t(async (t, n) => {
622
650
  if (!F) return;
623
651
  let r = P?.provider === "object" ? P.object : e.objectName;
624
652
  if (!r || !a || typeof a.update != "function") return;
@@ -626,153 +654,153 @@ var B = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: b
626
654
  if (n.start instanceof Date && (l[i] = n.start.toISOString()), n.end instanceof Date && (l[o] = n.end.toISOString()), typeof n.title == "string" && s && (l[s] = n.title), typeof n.progress == "number" && c && (l[c] = n.progress), Object.keys(l).length === 0) return;
627
655
  let u = t.data?.id ?? t.data?._id ?? t.id;
628
656
  if (u == null) return;
629
- let d = S;
630
- T((e) => e.map((e) => String(e.id ?? e._id) === String(u) ? {
657
+ let d = C;
658
+ w((e) => e.map((e) => String(e.id ?? e._id) === String(u) ? {
631
659
  ...e,
632
660
  ...l
633
661
  } : e));
634
662
  try {
635
663
  await a.update(r, String(u), l);
636
664
  } catch (e) {
637
- console.error("[ObjectGantt] Failed to persist task update:", e), T(d);
665
+ console.error("[ObjectGantt] Failed to persist task update:", e), w(d);
638
666
  }
639
667
  }, [
640
668
  F,
641
669
  P,
642
670
  a,
643
671
  e.objectName,
644
- S
645
- ]), [G, K] = i(null), [q, J] = i(!1), Y = t((e) => {
646
- K(e);
647
- }, []), X = t(async () => {
648
- if (!G) return;
672
+ C
673
+ ]), [U, W] = i(null), [G, K] = i(!1), q = t((e) => {
674
+ W(e);
675
+ }, []), J = t(async () => {
676
+ if (!U) return;
649
677
  let t = P?.provider === "object" ? P.object : e.objectName;
650
678
  if (!t || !a?.delete) {
651
- K(null);
679
+ W(null);
652
680
  return;
653
681
  }
654
- let n = G.data?.id ?? G.data?._id ?? G.id;
682
+ let n = U.data?.id ?? U.data?._id ?? U.id;
655
683
  if (n == null) {
656
- K(null);
684
+ W(null);
657
685
  return;
658
686
  }
659
- J(!0);
660
- let r = S;
661
- T((e) => e.filter((e) => String(e.id ?? e._id) !== String(n)));
687
+ K(!0);
688
+ let r = C;
689
+ w((e) => e.filter((e) => String(e.id ?? e._id) !== String(n)));
662
690
  try {
663
- await a.delete(t, String(n)), K(null);
691
+ await a.delete(t, String(n)), W(null);
664
692
  } catch (e) {
665
- console.error("[ObjectGantt] Failed to delete:", e), T(r), K(null);
693
+ console.error("[ObjectGantt] Failed to delete:", e), w(r), W(null);
666
694
  } finally {
667
- J(!1);
695
+ K(!1);
668
696
  }
669
697
  }, [
670
- G,
698
+ U,
671
699
  P,
672
700
  a,
673
701
  e.objectName,
674
- S
702
+ C
675
703
  ]);
676
- return E ? /* @__PURE__ */ j("div", {
704
+ return ee ? /* @__PURE__ */ M("div", {
677
705
  className: l,
678
- children: /* @__PURE__ */ j("div", {
706
+ children: /* @__PURE__ */ M("div", {
679
707
  className: "flex items-center justify-center h-96",
680
- children: /* @__PURE__ */ j("div", {
708
+ children: /* @__PURE__ */ M("div", {
681
709
  className: "text-muted-foreground",
682
710
  children: "Loading Gantt chart..."
683
711
  })
684
712
  })
685
- }) : O ? /* @__PURE__ */ j("div", {
713
+ }) : O ? /* @__PURE__ */ M("div", {
686
714
  className: l,
687
- children: /* @__PURE__ */ j("div", {
715
+ children: /* @__PURE__ */ M("div", {
688
716
  className: "flex items-center justify-center h-96",
689
- children: /* @__PURE__ */ M("div", {
717
+ children: /* @__PURE__ */ N("div", {
690
718
  className: "text-destructive",
691
719
  children: ["Error: ", O.message]
692
720
  })
693
721
  })
694
- }) : F ? /* @__PURE__ */ M("div", {
722
+ }) : F ? /* @__PURE__ */ N("div", {
695
723
  className: l,
696
724
  children: [
697
- /* @__PURE__ */ j("div", {
725
+ /* @__PURE__ */ M("div", {
698
726
  className: "h-[calc(100vh-200px)] min-h-[600px]",
699
- children: /* @__PURE__ */ j(L, {
700
- tasks: B,
727
+ children: /* @__PURE__ */ M(z, {
728
+ tasks: re,
701
729
  onTaskClick: (e) => {
702
- U.handleClick(e.data), u?.(e.data);
730
+ R.handleClick(e.data), u?.(e.data);
703
731
  },
704
- onTaskUpdate: W,
705
- onTaskDelete: Y,
732
+ onTaskUpdate: ae,
733
+ onTaskDelete: q,
706
734
  inlineEdit: !0
707
735
  })
708
736
  }),
709
- U.isOverlay && U.isOpen && U.selectedRecord && (() => {
710
- let t = P?.provider === "object" ? P.object : e.objectName, n = U.selectedRecord, r = n.id ?? n._id;
737
+ R.isOverlay && R.isOpen && R.selectedRecord && (() => {
738
+ let t = P?.provider === "object" ? P.object : e.objectName, n = R.selectedRecord, r = n.id ?? n._id;
711
739
  if (!t || r == null) return null;
712
740
  let i = F?.titleField ? String(n[F.titleField] ?? "Task Details") : "Task Details";
713
- return /* @__PURE__ */ j(d, {
741
+ return /* @__PURE__ */ M(f, {
714
742
  open: !0,
715
- onClose: U.close,
743
+ onClose: R.close,
716
744
  title: i,
717
745
  record: n,
718
746
  objectName: t,
719
747
  recordId: r,
720
748
  dataSource: a,
721
749
  objectSchema: k,
722
- width: U.width,
723
- fullPageHref: f(t, r) ?? void 0,
750
+ width: R.width,
751
+ fullPageHref: p(t, r) ?? void 0,
724
752
  onFieldSave: async (e, n) => {
725
- a?.update && (await a.update(t, String(r), { [e]: n }), T((t) => t.map((t) => String(t.id ?? t._id) === String(r) ? {
753
+ a?.update && (await a.update(t, String(r), { [e]: n }), w((t) => t.map((t) => String(t.id ?? t._id) === String(r) ? {
726
754
  ...t,
727
755
  [e]: n
728
756
  } : t)));
729
757
  },
730
758
  onDelete: async () => {
731
- a?.delete && (await a.delete(t, String(r)), T((e) => e.filter((e) => String(e.id ?? e._id) !== String(r))));
759
+ a?.delete && (await a.delete(t, String(r)), w((e) => e.filter((e) => String(e.id ?? e._id) !== String(r))));
732
760
  }
733
761
  });
734
762
  })(),
735
- /* @__PURE__ */ j(p, {
736
- open: !!G,
763
+ /* @__PURE__ */ M(m, {
764
+ open: !!U,
737
765
  onOpenChange: (e) => {
738
- !e && !q && K(null);
766
+ !e && !G && W(null);
739
767
  },
740
- children: /* @__PURE__ */ M(ee, { children: [/* @__PURE__ */ M(v, { children: [/* @__PURE__ */ j(y, { children: "Delete this task?" }), /* @__PURE__ */ j(g, { children: G ? /* @__PURE__ */ M(A, { children: [
768
+ children: /* @__PURE__ */ N(_, { children: [/* @__PURE__ */ N(b, { children: [/* @__PURE__ */ M(x, { children: "Delete this task?" }), /* @__PURE__ */ M(v, { children: U ? /* @__PURE__ */ N(j, { children: [
741
769
  "\"",
742
- G.title,
770
+ U.title,
743
771
  "\" will be permanently removed. This action cannot be undone."
744
- ] }) : null })] }), /* @__PURE__ */ M(_, { children: [/* @__PURE__ */ j(h, {
745
- disabled: q,
772
+ ] }) : null })] }), /* @__PURE__ */ N(y, { children: [/* @__PURE__ */ M(g, {
773
+ disabled: G,
746
774
  children: "Cancel"
747
- }), /* @__PURE__ */ j(m, {
775
+ }), /* @__PURE__ */ M(h, {
748
776
  onClick: (e) => {
749
- e.preventDefault(), X();
777
+ e.preventDefault(), J();
750
778
  },
751
- disabled: q,
779
+ disabled: G,
752
780
  "data-testid": "gantt-delete-confirm",
753
781
  className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
754
- children: q ? "Deleting…" : "Delete"
782
+ children: G ? "Deleting…" : "Delete"
755
783
  })] })] })
756
784
  })
757
785
  ]
758
- }) : /* @__PURE__ */ j("div", {
786
+ }) : /* @__PURE__ */ M("div", {
759
787
  className: l,
760
- children: /* @__PURE__ */ j("div", {
788
+ children: /* @__PURE__ */ M("div", {
761
789
  className: "flex items-center justify-center h-96",
762
- children: /* @__PURE__ */ j("div", {
790
+ children: /* @__PURE__ */ M("div", {
763
791
  className: "text-muted-foreground",
764
792
  children: "Gantt configuration required. Please specify startDateField, endDateField, and titleField."
765
793
  })
766
794
  })
767
795
  });
768
- }, V = ({ schema: e }) => {
769
- let { dataSource: t } = l() || {};
770
- return /* @__PURE__ */ j(B, {
796
+ }, W = ({ schema: e }) => {
797
+ let { dataSource: t } = u() || {};
798
+ return /* @__PURE__ */ M(U, {
771
799
  schema: e,
772
800
  dataSource: t
773
801
  });
774
802
  };
775
- a.register("object-gantt", V, {
803
+ a.register("object-gantt", W, {
776
804
  namespace: "plugin-gantt",
777
805
  label: "Object Gantt",
778
806
  category: "view",
@@ -787,7 +815,7 @@ a.register("object-gantt", V, {
787
815
  label: "Gantt Config",
788
816
  description: "startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField"
789
817
  }]
790
- }), a.register("gantt", V, {
818
+ }), a.register("gantt", W, {
791
819
  namespace: "view",
792
820
  label: "Gantt View",
793
821
  category: "view",
@@ -804,4 +832,4 @@ a.register("object-gantt", V, {
804
832
  }]
805
833
  });
806
834
  //#endregion
807
- export { L as GanttView, B as ObjectGantt, V as ObjectGanttRenderer };
835
+ export { z as GanttView, U as ObjectGantt, W as ObjectGanttRenderer };
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`@object-ui/core`),require(`@object-ui/react`),require(`@objectstack/spec/ui`),require(`@object-ui/plugin-detail`),require(`@object-ui/components`),require(`@object-ui/fields`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/plugin-detail`,`@object-ui/components`,`@object-ui/fields`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_plugin_detail,e.ObjectUIComponents,e._object_ui_fields,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function _(e){return e<640?35:e<1024?50:60}function v(e){return e<640?140:e<1024?220:320}function y(e){return e>=280}function b(e){return e<640?32:40}function x({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:s,inlineEdit:u=!1}){let[d,f]=t.useState(new Date),p=t.useRef(null),{width:m}=(0,o.useResizeObserver)(p),h=m||(typeof window<`u`?window.innerWidth:1024),g=h<640,x=b(h),S=_(h),[C,w]=t.useState(null),T=C??S,[E,D]=t.useState(!1),O=t.useRef(!1);t.useEffect(()=>{!O.current&&g&&(D(!0),O.current=!0)},[g]);let k=E?0:v(h),A=y(k),[j,M]=t.useState(null),[N,P]=t.useState({}),[F,I]=t.useState(null),L=t.useRef(null);t.useEffect(()=>{L.current=F},[F]);let R=t.useRef(!1),z=t.useCallback(e=>{let t=1e3*60*60*24,n=t,r=e.dayDelta*t,i=new Date(e.originStart),a=new Date(e.originEnd);return e.mode===`move`?(i=new Date(e.originStart.getTime()+r),a=new Date(e.originEnd.getTime()+r)):e.mode===`resize-left`?(i=new Date(e.originStart.getTime()+r),a.getTime()-i.getTime()<n&&(i=new Date(a.getTime()-n))):e.mode===`resize-right`&&(a=new Date(e.originEnd.getTime()+r),a.getTime()-i.getTime()<n&&(a=new Date(i.getTime()+n))),{start:i,end:a}},[]);t.useEffect(()=>{if(!F)return;let t=e=>{let t=L.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(T,1));n!==t.dayDelta&&I({...t,dayDelta:n})},n=()=>{let t=L.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=z(t);a(n,{start:e,end:r})}R.current=!0,window.setTimeout(()=>{R.current=!1},0)}I(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[F,T,e,a,z]);let B=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),I({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),V=t.useMemo(()=>{let t=n?new Date(n):new Date,i=r?new Date(r):new Date;return!n&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!r&&e.length>0&&(i=new Date(Math.max(...e.map(e=>e.end.getTime()))),i.setDate(i.getDate()+14)),t.setHours(0,0,0,0),i.setHours(23,59,59,999),{start:t,end:i}},[n,r,e]),H=t.useMemo(()=>{let e=[],t=new Date(V.start);for(;t<=V.end;)e.push({date:new Date(t),label:t.getDate().toString(),isWeekend:t.getDay()===0||t.getDay()===6}),t.setDate(t.getDate()+1);return e},[V]),U=t.useRef(null),W=t.useRef(null),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;q.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:T}}},[T]),Y=t.useCallback(e=>{if(e.touches.length!==2||!q.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/q.current.baseDistance;w(Math.max(15,Math.min(120,Math.round(q.current.baseColumn*r))))},[]),X=t.useCallback(()=>{q.current=null},[]),Z=t.useMemo(()=>{let e=new Date;if(e<V.start||e>V.end)return null;let t=(e.getTime()-V.start.getTime())/(1440*60*1e3);return Math.round(t*T)},[V,T]),Q=t.useCallback(()=>{if(Z==null||!K.current)return;let e=Math.max(0,Z-K.current.clientWidth/2);K.current.scrollTo({left:e,behavior:`smooth`})},[Z]),ee=e=>{U.current&&(U.current.scrollLeft=e.currentTarget.scrollLeft),W.current&&(W.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{V.end.getTime()-V.start.getTime();let t=T,n=1e3*60*60*24,r=e.start.getTime()-V.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,l.jsxs)(`div`,{ref:p,className:(0,o.cn)(`flex flex-col h-full bg-background overflow-hidden min-w-0`,s),children:[(0,l.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Previous period`,children:(0,l.jsx)(c.ChevronLeft,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Next period`,children:(0,l.jsx)(c.ChevronRight,{className:`h-4 w-4`})}),(0,l.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:V.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.max(15,T-10)),"aria-label":`Zoom out`,children:(0,l.jsx)(c.ZoomOut,{className:`h-3 w-3`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>w(Math.min(120,T+10)),"aria-label":`Zoom in`,children:(0,l.jsx)(c.ZoomIn,{className:`h-3 w-3`})})]}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>D(e=>!e),"aria-label":E?`Show task list`:`Hide task list`,"aria-pressed":E,"data-testid":`gantt-toggle-task-list`,children:E?(0,l.jsx)(c.PanelLeft,{className:`h-4 w-4`}):(0,l.jsx)(c.PanelLeftClose,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:Q,disabled:Z==null,"aria-label":`Jump to today`,"data-testid":`gantt-jump-today`,children:(0,l.jsx)(c.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,l.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:k,minWidth:k},children:[(0,l.jsx)(`div`,{className:`flex-1 truncate`,children:`Task Name`}),A&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`Start`}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`End`})]})]}),(0,l.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:U,children:(0,l.jsx)(`div`,{className:`flex h-full`,style:{width:H.length*T},children:H.map((e,t)=>(0,l.jsxs)(`div`,{className:(0,o.cn)(`flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full`,e.isWeekend&&`bg-muted/50`),style:{width:T,minWidth:T},children:[(0,l.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,l.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,l.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,l.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:W,style:{width:k,minWidth:k},children:e.map(e=>{let t=u&&j===e.id;return(0,l.jsxs)(`div`,{className:`group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:x},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(M(e.id),P({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,l.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,l.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.title||``,onChange:e=>P(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:N.title,start:new Date(N.start),end:new Date(N.end),progress:Number(N.progress)||0}),M(null)):t.key===`Escape`&&M(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,l.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,l.jsx)(`span`,{className:`truncate`,children:e.title}),(0,l.jsxs)(`span`,{className:`text-[10px] text-muted-foreground sm:hidden`,children:[e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})]})]})]}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.start||``,onChange:e=>P(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!A,style:A?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:N.end||``,onChange:e=>P(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,l.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{G.current=e,K.current=e},onScroll:ee,onTouchStart:J,onTouchMove:Y,onTouchEnd:X,"data-testid":`gantt-timeline`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:H.length*T},children:[Z!=null&&(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Z},"data-testid":`gantt-today-marker`,"aria-label":`Today`,children:(0,l.jsx)(`div`,{className:`absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap`,children:`Today`})}),(0,l.jsxs)(`div`,{className:`relative`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:H.map((e,t)=>(0,l.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:T,minWidth:T}},t))}),e.map(e=>{let t=$(e),n=F?.taskId===e.id,r=t;if(n&&F){let t=z(F);r=$({...e,start:t.start,end:t.end})}let s=!!a;return(0,l.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:x},children:[n&&(0,l.jsx)(`div`,{className:`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none`,style:{left:t.left,width:t.width,opacity:.35},"aria-hidden":`true`}),(0,l.jsxs)(`div`,{className:(0,o.cn)(`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none`,s?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,n&&`ring-2 ring-primary/60 brightness-110 z-10`),style:{left:r.left,width:r.width,backgroundColor:e.color||`#3b82f6`},"data-testid":`gantt-task-bar-${e.id}`,onClick:()=>{R.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&B(e,`move`,t)}:void 0,children:[s&&r.width>=14&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-left-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-left`,t)},onClick:e=>e.stopPropagation()}),(0,l.jsx)(`div`,{className:`absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-right-${e.id}`,onPointerDown:t=>{t.button===0&&B(e,`resize-right`,t)},onClick:e=>e.stopPropagation()})]}),e.progress>0&&(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,l.jsx)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:n?`${z(F).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${z(F).end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}`:`${Math.round(e.progress)}%`})]})]},e.id)}),(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-V.start.getTime())/(1e3*60*60*24)*T},children:(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function S(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function C(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function w(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var T=({schema:e,dataSource:i,className:c,onTaskClick:u,onRowClick:d,...f})=>{let[p,m]=(0,t.useState)([]),[h,g]=(0,t.useState)(!0),[_,v]=(0,t.useState)(null),[y,b]=(0,t.useState)(null),T=S(e),E=(0,t.useMemo)(()=>T,[JSON.stringify(T)]),D=w(e),O=E?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(g(!0),f.data&&Array.isArray(f.data)){m(f.data),g(!1);return}if(O&&E?.provider===`value`){m(E.items),g(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(E?.provider===`object`){let t=E.object,r=(0,n.buildExpandFields)(y?.fields);m((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:C(e.sort),...r.length>0?{$expand:r}:{}})))}else E?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),m([]));g(!1)}catch(e){v(e),g(!1)}})()},[E,i,O,e.filter,e.sort,y]),(0,t.useEffect)(()=>{!O&&i&&(async()=>{try{if(!i)return;let t=E?.provider===`object`?E.object:e.objectName;if(!t)return;b(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,O,E]);let k=(0,t.useMemo)(()=>{if(!D||!p.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=D,o=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},c=e=>{let t=[o(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`};return p.map((n,o)=>{let l=n[e],u=n[t],d=c(n),f=r?n[r]:0,p=i?n[i]:[],m=a?n[a]:void 0;if(!m){let e=n.status??n.state??n.priority??n.severity;if(e!=null&&e!==``){let t=(0,s.getSemanticColorName)(void 0,e);t&&(m=(0,s.getSemanticHex)(t))}}return{id:n.id||n._id||`task-${o}`,title:d,start:l?new Date(l):new Date,end:u?new Date(u):new Date,progress:Math.min(100,Math.max(0,f||0)),dependencies:Array.isArray(p)?p:[],color:m,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[p,D]),A=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},j=A.mode===`drawer`||A.mode===`modal`||A.mode===`split`||A.mode===`popover`,M=(0,r.useNavigationOverlay)({navigation:A,objectName:e.objectName,onRowClick:j?void 0:d}),N=(0,t.useCallback)(async(t,n)=>{if(!D)return;let r=E?.provider===`object`?E.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=D,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=p;m(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),m(d)}},[D,E,i,e.objectName,p]),[P,F]=(0,t.useState)(null),[I,L]=(0,t.useState)(!1),R=(0,t.useCallback)(e=>{F(e)},[]),z=(0,t.useCallback)(async()=>{if(!P)return;let t=E?.provider===`object`?E.object:e.objectName;if(!t||!i?.delete){F(null);return}let n=P.data?.id??P.data?._id??P.id;if(n==null){F(null);return}L(!0);let r=p;m(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),F(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),m(r),F(null)}finally{L(!1)}},[P,E,i,e.objectName,p]);return h?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):_?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,_.message]})})}):D?(0,l.jsxs)(`div`,{className:c,children:[(0,l.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,l.jsx)(x,{tasks:k,onTaskClick:e=>{M.handleClick(e.data),u?.(e.data)},onTaskUpdate:N,onTaskDelete:R,inlineEdit:!0})}),M.isOverlay&&M.isOpen&&M.selectedRecord&&(()=>{let t=E?.provider===`object`?E.object:e.objectName,n=M.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=D?.titleField?String(n[D.titleField]??`Task Details`):`Task Details`;return(0,l.jsx)(a.RecordDetailDrawer,{open:!0,onClose:M.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:y,width:M.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),m(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),m(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,l.jsx)(o.AlertDialog,{open:!!P,onOpenChange:e=>{!e&&!I&&F(null)},children:(0,l.jsxs)(o.AlertDialogContent,{children:[(0,l.jsxs)(o.AlertDialogHeader,{children:[(0,l.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,l.jsx)(o.AlertDialogDescription,{children:P?(0,l.jsxs)(l.Fragment,{children:[`"`,P.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,l.jsxs)(o.AlertDialogFooter,{children:[(0,l.jsx)(o.AlertDialogCancel,{disabled:I,children:`Cancel`}),(0,l.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),z()},disabled:I,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:I?`Deleting…`:`Delete`})]})]})})]}):(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},E=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,l.jsx)(T,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,E,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,E,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=x,e.ObjectGantt=T,e.ObjectGanttRenderer=E});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`@object-ui/core`),require(`@object-ui/react`),require(`@objectstack/spec/ui`),require(`@object-ui/plugin-detail`),require(`@object-ui/components`),require(`@object-ui/fields`),require(`lucide-react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/plugin-detail`,`@object-ui/components`,`@object-ui/fields`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_plugin_detail,e.ObjectUIComponents,e._object_ui_fields,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var _={"gantt.column.taskName":`Task Name`,"gantt.column.start":`Start`,"gantt.column.end":`End`,"gantt.toolbar.prevPeriod":`Previous period`,"gantt.toolbar.nextPeriod":`Next period`,"gantt.toolbar.zoomIn":`Zoom in`,"gantt.toolbar.zoomOut":`Zoom out`,"gantt.toolbar.jumpToToday":`Jump to today`,"gantt.toolbar.today":`Today`,"gantt.toolbar.showTaskList":`Show task list`,"gantt.toolbar.hideTaskList":`Hide task list`},v=`gantt.column.taskName`;function y(e,t){let n=_[e]||e;if(t)for(let[e,r]of Object.entries(t))n=n.replace(`{{${e}}}`,String(r));return n}function b(){try{let e=(0,r.useObjectTranslation)();return e.t(v)===v?{t:y}:{t:e.t}}catch{return{t:y}}}function x(e){return e<640?35:e<1024?50:60}function S(e){return e<640?140:e<1024?220:320}function C(e){return e>=280}function w(e){return e<640?32:40}function T({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:s,inlineEdit:u=!1}){let{t:d}=b(),[f,p]=t.useState(new Date),m=t.useRef(null),{width:h}=(0,o.useResizeObserver)(m),g=h||(typeof window<`u`?window.innerWidth:1024),_=g<640,v=w(g),y=x(g),[T,E]=t.useState(null),D=T??y,[O,k]=t.useState(!1),A=t.useRef(!1);t.useEffect(()=>{!A.current&&_&&(k(!0),A.current=!0)},[_]);let j=O?0:S(g),M=C(j),[N,P]=t.useState(null),[F,I]=t.useState({}),[L,R]=t.useState(null),z=t.useRef(null);t.useEffect(()=>{z.current=L},[L]);let B=t.useRef(!1),V=t.useCallback(e=>{let t=1e3*60*60*24,n=t,r=e.dayDelta*t,i=new Date(e.originStart),a=new Date(e.originEnd);return e.mode===`move`?(i=new Date(e.originStart.getTime()+r),a=new Date(e.originEnd.getTime()+r)):e.mode===`resize-left`?(i=new Date(e.originStart.getTime()+r),a.getTime()-i.getTime()<n&&(i=new Date(a.getTime()-n))):e.mode===`resize-right`&&(a=new Date(e.originEnd.getTime()+r),a.getTime()-i.getTime()<n&&(a=new Date(i.getTime()+n))),{start:i,end:a}},[]);t.useEffect(()=>{if(!L)return;let t=e=>{let t=z.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(D,1));n!==t.dayDelta&&R({...t,dayDelta:n})},n=()=>{let t=z.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=V(t);a(n,{start:e,end:r})}B.current=!0,window.setTimeout(()=>{B.current=!1},0)}R(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[L,D,e,a,V]);let H=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),R({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),U=t.useMemo(()=>{let t=n?new Date(n):new Date,i=r?new Date(r):new Date;return!n&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!r&&e.length>0&&(i=new Date(Math.max(...e.map(e=>e.end.getTime()))),i.setDate(i.getDate()+14)),t.setHours(0,0,0,0),i.setHours(23,59,59,999),{start:t,end:i}},[n,r,e]),W=t.useMemo(()=>{let e=[],t=new Date(U.start);for(;t<=U.end;)e.push({date:new Date(t),label:t.getDate().toString(),isWeekend:t.getDay()===0||t.getDay()===6}),t.setDate(t.getDate()+1);return e},[U]),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useRef(null),Y=t.useRef(null),X=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;Y.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:D}}},[D]),Z=t.useCallback(e=>{if(e.touches.length!==2||!Y.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/Y.current.baseDistance;E(Math.max(15,Math.min(120,Math.round(Y.current.baseColumn*r))))},[]),ee=t.useCallback(()=>{Y.current=null},[]),Q=t.useMemo(()=>{let e=new Date;if(e<U.start||e>U.end)return null;let t=(e.getTime()-U.start.getTime())/(1440*60*1e3);return Math.round(t*D)},[U,D]),te=t.useCallback(()=>{if(Q==null||!J.current)return;let e=Math.max(0,Q-J.current.clientWidth/2);J.current.scrollTo({left:e,behavior:`smooth`})},[Q]),ne=e=>{G.current&&(G.current.scrollLeft=e.currentTarget.scrollLeft),K.current&&(K.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{U.end.getTime()-U.start.getTime();let t=D,n=1e3*60*60*24,r=e.start.getTime()-U.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,l.jsxs)(`div`,{ref:m,className:(0,o.cn)(`flex flex-col h-full bg-background overflow-hidden min-w-0`,s),children:[(0,l.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":d(`gantt.toolbar.prevPeriod`),children:(0,l.jsx)(c.ChevronLeft,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":d(`gantt.toolbar.nextPeriod`),children:(0,l.jsx)(c.ChevronRight,{className:`h-4 w-4`})}),(0,l.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:U.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.max(15,D-10)),"aria-label":d(`gantt.toolbar.zoomOut`),children:(0,l.jsx)(c.ZoomOut,{className:`h-3 w-3`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.min(120,D+10)),"aria-label":d(`gantt.toolbar.zoomIn`),children:(0,l.jsx)(c.ZoomIn,{className:`h-3 w-3`})})]}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>k(e=>!e),"aria-label":d(O?`gantt.toolbar.showTaskList`:`gantt.toolbar.hideTaskList`),"aria-pressed":O,"data-testid":`gantt-toggle-task-list`,children:O?(0,l.jsx)(c.PanelLeft,{className:`h-4 w-4`}):(0,l.jsx)(c.PanelLeftClose,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:te,disabled:Q==null,"aria-label":d(`gantt.toolbar.jumpToToday`),"data-testid":`gantt-jump-today`,children:(0,l.jsx)(c.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,l.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:j,minWidth:j},children:[(0,l.jsx)(`div`,{className:`flex-1 truncate`,children:d(`gantt.column.taskName`)}),M&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.start`)}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.end`)})]})]}),(0,l.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:G,children:(0,l.jsx)(`div`,{className:`flex h-full`,style:{width:W.length*D},children:W.map((e,t)=>(0,l.jsxs)(`div`,{className:(0,o.cn)(`flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full`,e.isWeekend&&`bg-muted/50`),style:{width:D,minWidth:D},children:[(0,l.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,l.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,l.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,l.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:K,style:{width:j,minWidth:j},children:e.map(e=>{let t=u&&N===e.id;return(0,l.jsxs)(`div`,{className:`group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:v},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(P(e.id),I({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,l.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,l.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.title||``,onChange:e=>I(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:F.title,start:new Date(F.start),end:new Date(F.end),progress:Number(F.progress)||0}),P(null)):t.key===`Escape`&&P(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,l.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,l.jsx)(`span`,{className:`truncate`,children:e.title}),(0,l.jsxs)(`span`,{className:`text-[10px] text-muted-foreground sm:hidden`,children:[e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})]})]})]}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!M,style:M?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.start||``,onChange:e=>I(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!M,style:M?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.end||``,onChange:e=>I(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,l.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{q.current=e,J.current=e},onScroll:ne,onTouchStart:X,onTouchMove:Z,onTouchEnd:ee,"data-testid":`gantt-timeline`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:W.length*D},children:[Q!=null&&(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Q},"data-testid":`gantt-today-marker`,"aria-label":d(`gantt.toolbar.today`),children:(0,l.jsx)(`div`,{className:`absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap`,children:d(`gantt.toolbar.today`)})}),(0,l.jsxs)(`div`,{className:`relative`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:W.map((e,t)=>(0,l.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:D,minWidth:D}},t))}),e.map(e=>{let t=$(e),n=L?.taskId===e.id,r=t;if(n&&L){let t=V(L);r=$({...e,start:t.start,end:t.end})}let s=!!a;return(0,l.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:v},children:[n&&(0,l.jsx)(`div`,{className:`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none`,style:{left:t.left,width:t.width,opacity:.35},"aria-hidden":`true`}),(0,l.jsxs)(`div`,{className:(0,o.cn)(`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none`,s?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,n&&`ring-2 ring-primary/60 brightness-110 z-10`),style:{left:r.left,width:r.width,backgroundColor:e.color||`#3b82f6`},"data-testid":`gantt-task-bar-${e.id}`,onClick:()=>{B.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&H(e,`move`,t)}:void 0,children:[s&&r.width>=14&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-left-${e.id}`,onPointerDown:t=>{t.button===0&&H(e,`resize-left`,t)},onClick:e=>e.stopPropagation()}),(0,l.jsx)(`div`,{className:`absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-right-${e.id}`,onPointerDown:t=>{t.button===0&&H(e,`resize-right`,t)},onClick:e=>e.stopPropagation()})]}),e.progress>0&&(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,l.jsx)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:n?`${V(L).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${V(L).end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}`:`${Math.round(e.progress)}%`})]})]},e.id)}),(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-U.start.getTime())/(1e3*60*60*24)*D},children:(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function E(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function D(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function O(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var k=({schema:e,dataSource:i,className:c,onTaskClick:u,onRowClick:d,...f})=>{let[p,m]=(0,t.useState)([]),[h,g]=(0,t.useState)(!0),[_,v]=(0,t.useState)(null),[y,b]=(0,t.useState)(null),x=E(e),S=(0,t.useMemo)(()=>x,[JSON.stringify(x)]),C=O(e),w=S?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(g(!0),f.data&&Array.isArray(f.data)){m(f.data),g(!1);return}if(w&&S?.provider===`value`){m(S.items),g(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(S?.provider===`object`){let t=S.object,r=(0,n.buildExpandFields)(y?.fields);m((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:D(e.sort),...r.length>0?{$expand:r}:{}})))}else S?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),m([]));g(!1)}catch(e){v(e),g(!1)}})()},[S,i,w,e.filter,e.sort,y]),(0,t.useEffect)(()=>{!w&&i&&(async()=>{try{if(!i)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t)return;b(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,w,S]);let k=(0,t.useMemo)(()=>{if(!C||!p.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=C,o=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},c=e=>{let t=[o(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`};return p.map((n,o)=>{let l=n[e],u=n[t],d=c(n),f=r?n[r]:0,p=i?n[i]:[],m=a?n[a]:void 0;if(!m){let e=n.status??n.state??n.priority??n.severity;if(e!=null&&e!==``){let t=(0,s.getSemanticColorName)(void 0,e);t&&(m=(0,s.getSemanticHex)(t))}}return{id:n.id||n._id||`task-${o}`,title:d,start:l?new Date(l):new Date,end:u?new Date(u):new Date,progress:Math.min(100,Math.max(0,f||0)),dependencies:Array.isArray(p)?p:[],color:m,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[p,C]),A=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},j=A.mode===`drawer`||A.mode===`modal`||A.mode===`split`||A.mode===`popover`,M=(0,r.useNavigationOverlay)({navigation:A,objectName:e.objectName,onRowClick:j?void 0:d}),N=(0,t.useCallback)(async(t,n)=>{if(!C)return;let r=S?.provider===`object`?S.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=C,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=p;m(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),m(d)}},[C,S,i,e.objectName,p]),[P,F]=(0,t.useState)(null),[I,L]=(0,t.useState)(!1),R=(0,t.useCallback)(e=>{F(e)},[]),z=(0,t.useCallback)(async()=>{if(!P)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t||!i?.delete){F(null);return}let n=P.data?.id??P.data?._id??P.id;if(n==null){F(null);return}L(!0);let r=p;m(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),F(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),m(r),F(null)}finally{L(!1)}},[P,S,i,e.objectName,p]);return h?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):_?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,_.message]})})}):C?(0,l.jsxs)(`div`,{className:c,children:[(0,l.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,l.jsx)(T,{tasks:k,onTaskClick:e=>{M.handleClick(e.data),u?.(e.data)},onTaskUpdate:N,onTaskDelete:R,inlineEdit:!0})}),M.isOverlay&&M.isOpen&&M.selectedRecord&&(()=>{let t=S?.provider===`object`?S.object:e.objectName,n=M.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=C?.titleField?String(n[C.titleField]??`Task Details`):`Task Details`;return(0,l.jsx)(a.RecordDetailDrawer,{open:!0,onClose:M.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:y,width:M.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),m(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),m(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,l.jsx)(o.AlertDialog,{open:!!P,onOpenChange:e=>{!e&&!I&&F(null)},children:(0,l.jsxs)(o.AlertDialogContent,{children:[(0,l.jsxs)(o.AlertDialogHeader,{children:[(0,l.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,l.jsx)(o.AlertDialogDescription,{children:P?(0,l.jsxs)(l.Fragment,{children:[`"`,P.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,l.jsxs)(o.AlertDialogFooter,{children:[(0,l.jsx)(o.AlertDialogCancel,{disabled:I,children:`Cancel`}),(0,l.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),z()},disabled:I,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:I?`Deleting…`:`Delete`})]})]})})]}):(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},A=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,l.jsx)(k,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,A,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,A,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=T,e.ObjectGantt=k,e.ObjectGanttRenderer=A});
@@ -1 +1 @@
1
- {"version":3,"file":"GanttView.d.ts","sourceRoot":"","sources":["../../../../src/GanttView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoDH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,IAAI,CAAA;IACX,GAAG,EAAE,IAAI,CAAA;IACT,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC,CAAC,KAAK,IAAI,CAAA;IACnH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACxC,oDAAoD;IACpD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,SAAS,EACT,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAkB,GACnB,EAAE,cAAc,2CA6kBhB"}
1
+ {"version":3,"file":"GanttView.d.ts","sourceRoot":"","sources":["../../../../src/GanttView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqDH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,IAAI,CAAA;IACX,GAAG,EAAE,IAAI,CAAA;IACT,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,YAAY,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,aAAa,CAAA;IACxB,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC,CAAC,KAAK,IAAI,CAAA;IACnH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACxC,oDAAoD;IACpD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,SAAS,EACT,OAAO,EACP,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAkB,GACnB,EAAE,cAAc,2CA8kBhB"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Default English translations for ObjectGantt. Mirrors the
10
+ * createSafeTranslationHook pattern used by plugin-detail / plugin-timeline so
11
+ * the Gantt keeps working when rendered standalone (Storybook, tests, embed)
12
+ * without an I18nProvider on the React tree.
13
+ */
14
+ export declare const GANTT_DEFAULT_TRANSLATIONS: Record<string, string>;
15
+ declare function fallback(key: string, options?: Record<string, unknown>): string;
16
+ export declare function useGanttTranslation(): {
17
+ t: typeof fallback;
18
+ } | {
19
+ t: import('i18next').TFunction<string, undefined>;
20
+ };
21
+ export {};
22
+ //# sourceMappingURL=useGanttTranslation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGanttTranslation.d.ts","sourceRoot":"","sources":["../../../../src/useGanttTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY7D,CAAC;AAIF,iBAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQxE;AAED,wBAAgB,mBAAmB;;;;EAWlC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-gantt",
3
- "version": "5.0.1",
3
+ "version": "5.0.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Gantt chart plugin for Object UI",
@@ -26,12 +26,12 @@
26
26
  "dependencies": {
27
27
  "@objectstack/spec": "^4.0.5",
28
28
  "lucide-react": "^1.16.0",
29
- "@object-ui/components": "5.0.1",
30
- "@object-ui/core": "5.0.1",
31
- "@object-ui/fields": "5.0.1",
32
- "@object-ui/plugin-detail": "5.0.1",
33
- "@object-ui/react": "5.0.1",
34
- "@object-ui/types": "5.0.1"
29
+ "@object-ui/components": "5.0.2",
30
+ "@object-ui/core": "5.0.2",
31
+ "@object-ui/fields": "5.0.2",
32
+ "@object-ui/plugin-detail": "5.0.2",
33
+ "@object-ui/react": "5.0.2",
34
+ "@object-ui/types": "5.0.2"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": "^18.0.0 || ^19.0.0",