@object-ui/plugin-gantt 4.0.7 → 4.0.8
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 +11 -0
- package/README.md +62 -0
- package/dist/index.js +452 -269
- package/dist/index.umd.cjs +1 -1
- package/dist/packages/plugin-gantt/src/GanttView.d.ts +12 -2
- package/dist/packages/plugin-gantt/src/GanttView.d.ts.map +1 -1
- package/dist/packages/plugin-gantt/src/ObjectGantt.d.ts.map +1 -1
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @object-ui/plugin-gantt
|
|
2
2
|
|
|
3
|
+
## 4.0.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @object-ui/components@4.0.8
|
|
8
|
+
- @object-ui/fields@4.0.8
|
|
9
|
+
- @object-ui/react@4.0.8
|
|
10
|
+
- @object-ui/plugin-detail@4.0.8
|
|
11
|
+
- @object-ui/types@4.0.8
|
|
12
|
+
- @object-ui/core@4.0.8
|
|
13
|
+
|
|
3
14
|
## 4.0.7
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -5,12 +5,74 @@ Gantt chart plugin for Object UI - Visualize project timelines and task dependen
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Gantt Charts** - Interactive Gantt chart visualization
|
|
8
|
+
- **Full CRUD on the timeline** - Create via toolbar quick-create dialog, edit
|
|
9
|
+
inline or via drag, delete via row kebab → confirmation dialog, view detail
|
|
10
|
+
via click → navigation overlay
|
|
11
|
+
- **Drag-and-drop rescheduling** - Drag a bar to move it; drag either edge to resize
|
|
12
|
+
start/end (snaps to whole days, persists via `dataSource.update`)
|
|
8
13
|
- **Task Dependencies** - Link tasks with dependencies
|
|
9
14
|
- **Timeline View** - Visualize project schedules
|
|
10
15
|
- **Task Management** - Create, edit, and track tasks
|
|
11
16
|
- **Responsive** - Scrollable timeline for large projects
|
|
12
17
|
- **Customizable** - Tailwind CSS styling support
|
|
13
18
|
|
|
19
|
+
### Create / Edit / Delete / View
|
|
20
|
+
|
|
21
|
+
When used through `ObjectGantt` (the wiring the framework uses for the
|
|
22
|
+
`gantt` view type) the full CRUD lifecycle is wired automatically:
|
|
23
|
+
|
|
24
|
+
- **Create** — click the toolbar "+ New Task" button. A small dialog opens
|
|
25
|
+
pre-filled with start/end (today → +7 days). On submit the component calls
|
|
26
|
+
`dataSource.create(objectName, { [titleField], [startDateField],
|
|
27
|
+
[endDateField], …required fields })` and optimistically inserts the new
|
|
28
|
+
record into the chart.
|
|
29
|
+
- **Edit** — drag the bar (move), drag an edge (resize), or hover the row
|
|
30
|
+
and pick **Edit inline** from the kebab menu to rename / change dates
|
|
31
|
+
inline. All paths funnel through `dataSource.update`.
|
|
32
|
+
- **Delete** — hover a row, open the kebab menu, choose **Delete**. A
|
|
33
|
+
shadcn `<AlertDialog>` asks for confirmation; on confirm `dataSource.delete`
|
|
34
|
+
removes the record (optimistic local removal, reverts on failure).
|
|
35
|
+
- **View / Edit / Delete in a side drawer** — click anywhere on a row
|
|
36
|
+
(or pick **View details** in the kebab) to open a right-side drawer
|
|
37
|
+
containing the standard `<DetailView>` from `@object-ui/plugin-detail`.
|
|
38
|
+
The drawer ships the same record-header chrome used everywhere else
|
|
39
|
+
(badges, summary chips, **Edit** + **Inline edit** buttons, and a
|
|
40
|
+
**…** more-actions menu with **Delete**). Edits via inline-edit save
|
|
41
|
+
through `dataSource.update` and merge into the local timeline state;
|
|
42
|
+
delete confirms via the platform standard dialog and removes the row
|
|
43
|
+
on success. Fields are auto-derived from the record (object schema is
|
|
44
|
+
fetched by `DetailView` itself when `dataSource.getObjectSchema` is
|
|
45
|
+
available).
|
|
46
|
+
|
|
47
|
+
Override by setting `navigation` on the schema, e.g.
|
|
48
|
+
`{ mode: 'page', basePath: '/console/apps/.../campaign' }` to route
|
|
49
|
+
to the standalone detail page instead.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
### Drag-and-drop rescheduling
|
|
53
|
+
|
|
54
|
+
When the renderer is used through `ObjectGantt` (the standard wiring used by
|
|
55
|
+
the framework's `gantt` view type) drag is enabled automatically: each bar
|
|
56
|
+
shows a grab cursor; the body drags the entire task, and the two thin edge
|
|
57
|
+
zones (≈6px) resize start or end. Pointer motion snaps to whole days using
|
|
58
|
+
the current column width. On release `ObjectGantt` issues an optimistic local
|
|
59
|
+
patch and a `dataSource.update(objectName, recordId, { [startDateField]: …,
|
|
60
|
+
[endDateField]: … })`. If the request fails the local state is reverted.
|
|
61
|
+
|
|
62
|
+
When you embed the lower-level `<GanttView>` directly, pass `onTaskUpdate`
|
|
63
|
+
to opt in:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
<GanttView
|
|
67
|
+
tasks={tasks}
|
|
68
|
+
onTaskUpdate={(task, { start, end }) => {
|
|
69
|
+
// start/end are JS Date objects already snapped to whole days,
|
|
70
|
+
// and the resize-left/right cases clamp so end - start >= 1 day.
|
|
71
|
+
save(task.id, { start, end });
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
14
76
|
## Installation
|
|
15
77
|
|
|
16
78
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,98 @@
|
|
|
1
1
|
import * as e from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { ComponentRegistry as
|
|
4
|
-
import { useNavigationOverlay as
|
|
5
|
-
import { GanttConfigSchema as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
|
|
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 ee, AlertDialogContent as te, AlertDialogDescription as h, AlertDialogFooter as g, AlertDialogHeader as _, AlertDialogTitle as v, Button as y, cn as b, useResizeObserver as x } from "@object-ui/components";
|
|
8
|
+
import { CalendarDays as S, ChevronLeft as C, ChevronRight as w, PanelLeft as T, PanelLeftClose as ne, ZoomIn as E, ZoomOut as re } from "lucide-react";
|
|
9
|
+
import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
9
10
|
//#region src/GanttView.tsx
|
|
10
|
-
function
|
|
11
|
+
function A(e) {
|
|
11
12
|
return e < 640 ? 35 : e < 1024 ? 50 : 60;
|
|
12
13
|
}
|
|
13
|
-
function
|
|
14
|
-
return e < 640 ?
|
|
14
|
+
function j(e) {
|
|
15
|
+
return e < 640 ? 140 : e < 1024 ? 220 : 320;
|
|
16
|
+
}
|
|
17
|
+
function M(e) {
|
|
18
|
+
return e >= 280;
|
|
15
19
|
}
|
|
16
|
-
function
|
|
20
|
+
function N(e) {
|
|
17
21
|
return e < 640 ? 32 : 40;
|
|
18
22
|
}
|
|
19
|
-
function
|
|
20
|
-
let [
|
|
23
|
+
function P({ tasks: t, startDate: n, endDate: r, onTaskClick: i, onTaskUpdate: a, className: o, inlineEdit: s = !1 }) {
|
|
24
|
+
let [c, l] = e.useState(/* @__PURE__ */ new Date()), u = e.useRef(null), { width: d } = x(u), f = d || (typeof window < "u" ? window.innerWidth : 1024), p = f < 640, m = N(f), ee = A(f), [te, h] = e.useState(null), g = te ?? ee, [_, v] = e.useState(!1), P = e.useRef(!1);
|
|
21
25
|
e.useEffect(() => {
|
|
22
|
-
!
|
|
23
|
-
}, [
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
!P.current && p && (v(!0), P.current = !0);
|
|
27
|
+
}, [p]);
|
|
28
|
+
let F = _ ? 0 : j(f), I = M(F), [L, R] = e.useState(null), [z, B] = e.useState({}), [V, H] = e.useState(null), U = e.useRef(null);
|
|
29
|
+
e.useEffect(() => {
|
|
30
|
+
U.current = V;
|
|
31
|
+
}, [V]);
|
|
32
|
+
let W = e.useRef(!1), G = e.useCallback((e) => {
|
|
33
|
+
let t = 1e3 * 60 * 60 * 24, n = t, r = e.dayDelta * t, i = new Date(e.originStart), a = new Date(e.originEnd);
|
|
34
|
+
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))), {
|
|
35
|
+
start: i,
|
|
36
|
+
end: a
|
|
37
|
+
};
|
|
38
|
+
}, []);
|
|
39
|
+
e.useEffect(() => {
|
|
40
|
+
if (!V) return;
|
|
41
|
+
let e = (e) => {
|
|
42
|
+
let t = U.current;
|
|
43
|
+
if (!t) return;
|
|
44
|
+
let n = Math.round((e.clientX - t.originClientX) / Math.max(g, 1));
|
|
45
|
+
n !== t.dayDelta && H({
|
|
46
|
+
...t,
|
|
47
|
+
dayDelta: n
|
|
48
|
+
});
|
|
49
|
+
}, n = () => {
|
|
50
|
+
let e = U.current;
|
|
51
|
+
if (e) {
|
|
52
|
+
if (e.dayDelta !== 0) {
|
|
53
|
+
let n = t.find((t) => t.id === e.taskId);
|
|
54
|
+
if (n && a) {
|
|
55
|
+
let { start: t, end: r } = G(e);
|
|
56
|
+
a(n, {
|
|
57
|
+
start: t,
|
|
58
|
+
end: r
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
W.current = !0, window.setTimeout(() => {
|
|
62
|
+
W.current = !1;
|
|
63
|
+
}, 0);
|
|
64
|
+
}
|
|
65
|
+
H(null);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return window.addEventListener("pointermove", e), window.addEventListener("pointerup", n), window.addEventListener("pointercancel", n), () => {
|
|
69
|
+
window.removeEventListener("pointermove", e), window.removeEventListener("pointerup", n), window.removeEventListener("pointercancel", n);
|
|
70
|
+
};
|
|
71
|
+
}, [
|
|
72
|
+
V,
|
|
73
|
+
g,
|
|
74
|
+
t,
|
|
75
|
+
a,
|
|
76
|
+
G
|
|
77
|
+
]);
|
|
78
|
+
let K = e.useCallback((e, t, n) => {
|
|
79
|
+
a && (n.stopPropagation(), n.preventDefault(), H({
|
|
80
|
+
taskId: e.id,
|
|
81
|
+
mode: t,
|
|
82
|
+
originStart: new Date(e.start),
|
|
83
|
+
originEnd: new Date(e.end),
|
|
84
|
+
originClientX: n.clientX,
|
|
85
|
+
dayDelta: 0
|
|
86
|
+
}));
|
|
87
|
+
}, [a]), q = e.useMemo(() => {
|
|
88
|
+
let e = n ? new Date(n) : /* @__PURE__ */ new Date(), i = r ? new Date(r) : /* @__PURE__ */ new Date();
|
|
89
|
+
return !n && t.length > 0 && (e = new Date(Math.min(...t.map((e) => e.start.getTime()))), e.setDate(e.getDate() - 7)), !r && t.length > 0 && (i = new Date(Math.max(...t.map((e) => e.end.getTime()))), i.setDate(i.getDate() + 14)), e.setHours(0, 0, 0, 0), i.setHours(23, 59, 59, 999), {
|
|
27
90
|
start: e,
|
|
28
|
-
end:
|
|
91
|
+
end: i
|
|
29
92
|
};
|
|
30
93
|
}, [
|
|
94
|
+
n,
|
|
31
95
|
r,
|
|
32
|
-
i,
|
|
33
96
|
t
|
|
34
97
|
]), J = e.useMemo(() => {
|
|
35
98
|
let e = [], t = new Date(q.start);
|
|
@@ -44,21 +107,21 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
44
107
|
let t = e.touches[0].clientX - e.touches[1].clientX, n = e.touches[0].clientY - e.touches[1].clientY;
|
|
45
108
|
Q.current = {
|
|
46
109
|
baseDistance: Math.max(1, Math.sqrt(t * t + n * n)),
|
|
47
|
-
baseColumn:
|
|
110
|
+
baseColumn: g
|
|
48
111
|
};
|
|
49
112
|
}
|
|
50
|
-
}, [
|
|
113
|
+
}, [g]), oe = e.useCallback((e) => {
|
|
51
114
|
if (e.touches.length !== 2 || !Q.current) return;
|
|
52
115
|
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;
|
|
53
|
-
|
|
116
|
+
h(Math.max(15, Math.min(120, Math.round(Q.current.baseColumn * r))));
|
|
54
117
|
}, []), se = e.useCallback(() => {
|
|
55
118
|
Q.current = null;
|
|
56
119
|
}, []), $ = e.useMemo(() => {
|
|
57
120
|
let e = /* @__PURE__ */ new Date();
|
|
58
121
|
if (e < q.start || e > q.end) return null;
|
|
59
122
|
let t = (e.getTime() - q.start.getTime()) / (1440 * 60 * 1e3);
|
|
60
|
-
return Math.round(t *
|
|
61
|
-
}, [q,
|
|
123
|
+
return Math.round(t * g);
|
|
124
|
+
}, [q, g]), ce = e.useCallback(() => {
|
|
62
125
|
if ($ == null || !Z.current) return;
|
|
63
126
|
let e = Math.max(0, $ - Z.current.clientWidth / 2);
|
|
64
127
|
Z.current.scrollTo({
|
|
@@ -69,53 +132,35 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
69
132
|
Y.current && (Y.current.scrollLeft = e.currentTarget.scrollLeft), X.current && (X.current.scrollTop = e.currentTarget.scrollTop);
|
|
70
133
|
}, ue = (e) => {
|
|
71
134
|
q.end.getTime() - q.start.getTime();
|
|
72
|
-
let t =
|
|
135
|
+
let t = g, n = 1e3 * 60 * 60 * 24, r = e.start.getTime() - q.start.getTime(), i = e.end.getTime() - e.start.getTime();
|
|
73
136
|
return {
|
|
74
137
|
left: r / n * t,
|
|
75
138
|
width: Math.max(i / n * t, t)
|
|
76
139
|
};
|
|
77
140
|
};
|
|
78
|
-
return /* @__PURE__ */
|
|
79
|
-
ref:
|
|
80
|
-
className:
|
|
81
|
-
children: [/* @__PURE__ */
|
|
141
|
+
return /* @__PURE__ */ k("div", {
|
|
142
|
+
ref: u,
|
|
143
|
+
className: b("flex flex-col h-full bg-background border rounded-lg overflow-hidden min-w-0", o),
|
|
144
|
+
children: [/* @__PURE__ */ k("div", {
|
|
82
145
|
className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card",
|
|
83
|
-
children: [/* @__PURE__ */
|
|
146
|
+
children: [/* @__PURE__ */ k("div", {
|
|
84
147
|
className: "flex items-center gap-2",
|
|
85
148
|
children: [
|
|
86
|
-
/* @__PURE__ */ O(
|
|
87
|
-
variant: "outline",
|
|
88
|
-
size: "sm",
|
|
89
|
-
onClick: () => c?.(),
|
|
90
|
-
"aria-label": "Create new task",
|
|
91
|
-
children: [
|
|
92
|
-
/* @__PURE__ */ D(w, { className: "h-4 w-4 mr-1 sm:mr-2" }),
|
|
93
|
-
/* @__PURE__ */ D("span", {
|
|
94
|
-
className: "hidden sm:inline",
|
|
95
|
-
children: "New Task"
|
|
96
|
-
}),
|
|
97
|
-
/* @__PURE__ */ D("span", {
|
|
98
|
-
className: "sm:hidden",
|
|
99
|
-
children: "New"
|
|
100
|
-
})
|
|
101
|
-
]
|
|
102
|
-
}),
|
|
103
|
-
/* @__PURE__ */ D("div", { className: "h-4 w-px bg-border mx-1 sm:mx-2" }),
|
|
104
|
-
/* @__PURE__ */ D(u, {
|
|
149
|
+
/* @__PURE__ */ O(y, {
|
|
105
150
|
variant: "ghost",
|
|
106
151
|
size: "icon",
|
|
107
152
|
className: "h-8 w-8",
|
|
108
153
|
"aria-label": "Previous period",
|
|
109
|
-
children: /* @__PURE__ */
|
|
154
|
+
children: /* @__PURE__ */ O(C, { className: "h-4 w-4" })
|
|
110
155
|
}),
|
|
111
|
-
/* @__PURE__ */
|
|
156
|
+
/* @__PURE__ */ O(y, {
|
|
112
157
|
variant: "ghost",
|
|
113
158
|
size: "icon",
|
|
114
159
|
className: "h-8 w-8",
|
|
115
160
|
"aria-label": "Next period",
|
|
116
|
-
children: /* @__PURE__ */
|
|
161
|
+
children: /* @__PURE__ */ O(w, { className: "h-4 w-4" })
|
|
117
162
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
163
|
+
/* @__PURE__ */ O("span", {
|
|
119
164
|
className: "font-semibold text-xs sm:text-sm",
|
|
120
165
|
children: q.start.toLocaleDateString(void 0, {
|
|
121
166
|
month: "long",
|
|
@@ -123,63 +168,38 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
123
168
|
})
|
|
124
169
|
})
|
|
125
170
|
]
|
|
126
|
-
}), /* @__PURE__ */
|
|
171
|
+
}), /* @__PURE__ */ k("div", {
|
|
127
172
|
className: "flex items-center gap-2",
|
|
128
173
|
children: [
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
value: n,
|
|
131
|
-
onValueChange: (e) => s?.(e),
|
|
132
|
-
children: [/* @__PURE__ */ D(h, {
|
|
133
|
-
className: "w-[100px] sm:w-[120px] h-8",
|
|
134
|
-
children: /* @__PURE__ */ D(g, {})
|
|
135
|
-
}), /* @__PURE__ */ O(p, { children: [
|
|
136
|
-
/* @__PURE__ */ D(m, {
|
|
137
|
-
value: "day",
|
|
138
|
-
children: "Day View"
|
|
139
|
-
}),
|
|
140
|
-
/* @__PURE__ */ D(m, {
|
|
141
|
-
value: "week",
|
|
142
|
-
children: "Week View"
|
|
143
|
-
}),
|
|
144
|
-
/* @__PURE__ */ D(m, {
|
|
145
|
-
value: "month",
|
|
146
|
-
children: "Month View"
|
|
147
|
-
}),
|
|
148
|
-
/* @__PURE__ */ D(m, {
|
|
149
|
-
value: "quarter",
|
|
150
|
-
children: "Quarter View"
|
|
151
|
-
})
|
|
152
|
-
] })]
|
|
153
|
-
}),
|
|
154
|
-
/* @__PURE__ */ O("div", {
|
|
174
|
+
/* @__PURE__ */ k("div", {
|
|
155
175
|
className: "flex bg-muted rounded-md p-1",
|
|
156
|
-
children: [/* @__PURE__ */
|
|
176
|
+
children: [/* @__PURE__ */ O(y, {
|
|
157
177
|
variant: "ghost",
|
|
158
178
|
size: "icon",
|
|
159
179
|
className: "h-6 w-6",
|
|
160
|
-
onClick: () =>
|
|
180
|
+
onClick: () => h(Math.max(15, g - 10)),
|
|
161
181
|
"aria-label": "Zoom out",
|
|
162
|
-
children: /* @__PURE__ */
|
|
163
|
-
}), /* @__PURE__ */
|
|
182
|
+
children: /* @__PURE__ */ O(re, { className: "h-3 w-3" })
|
|
183
|
+
}), /* @__PURE__ */ O(y, {
|
|
164
184
|
variant: "ghost",
|
|
165
185
|
size: "icon",
|
|
166
186
|
className: "h-6 w-6",
|
|
167
|
-
onClick: () =>
|
|
187
|
+
onClick: () => h(Math.min(120, g + 10)),
|
|
168
188
|
"aria-label": "Zoom in",
|
|
169
|
-
children: /* @__PURE__ */
|
|
189
|
+
children: /* @__PURE__ */ O(E, { className: "h-3 w-3" })
|
|
170
190
|
})]
|
|
171
191
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ O(y, {
|
|
173
193
|
variant: "ghost",
|
|
174
194
|
size: "icon",
|
|
175
195
|
className: "h-8 w-8",
|
|
176
|
-
onClick: () =>
|
|
177
|
-
"aria-label":
|
|
178
|
-
"aria-pressed":
|
|
196
|
+
onClick: () => v((e) => !e),
|
|
197
|
+
"aria-label": _ ? "Show task list" : "Hide task list",
|
|
198
|
+
"aria-pressed": _,
|
|
179
199
|
"data-testid": "gantt-toggle-task-list",
|
|
180
|
-
children:
|
|
200
|
+
children: O(_ ? T : ne, { className: "h-4 w-4" })
|
|
181
201
|
}),
|
|
182
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ O(y, {
|
|
183
203
|
variant: "ghost",
|
|
184
204
|
size: "icon",
|
|
185
205
|
className: "h-8 w-8",
|
|
@@ -187,73 +207,69 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
187
207
|
disabled: $ == null,
|
|
188
208
|
"aria-label": "Jump to today",
|
|
189
209
|
"data-testid": "gantt-jump-today",
|
|
190
|
-
children: /* @__PURE__ */
|
|
210
|
+
children: /* @__PURE__ */ O(S, { className: "h-4 w-4" })
|
|
191
211
|
})
|
|
192
212
|
]
|
|
193
213
|
})]
|
|
194
|
-
}), /* @__PURE__ */
|
|
214
|
+
}), /* @__PURE__ */ k("div", {
|
|
195
215
|
className: "flex flex-col flex-1 overflow-hidden",
|
|
196
|
-
children: [/* @__PURE__ */
|
|
216
|
+
children: [/* @__PURE__ */ k("div", {
|
|
197
217
|
className: "flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]",
|
|
198
|
-
children: [/* @__PURE__ */
|
|
218
|
+
children: [/* @__PURE__ */ k("div", {
|
|
199
219
|
className: "flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm",
|
|
200
220
|
style: {
|
|
201
|
-
width:
|
|
202
|
-
minWidth:
|
|
221
|
+
width: F,
|
|
222
|
+
minWidth: F
|
|
203
223
|
},
|
|
204
|
-
children: [
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
children: "End"
|
|
216
|
-
})
|
|
217
|
-
]
|
|
218
|
-
}), /* @__PURE__ */ D("div", {
|
|
224
|
+
children: [/* @__PURE__ */ O("div", {
|
|
225
|
+
className: "flex-1 truncate",
|
|
226
|
+
children: "Task Name"
|
|
227
|
+
}), I && /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O("div", {
|
|
228
|
+
className: "w-16 sm:w-20 text-right",
|
|
229
|
+
children: "Start"
|
|
230
|
+
}), /* @__PURE__ */ O("div", {
|
|
231
|
+
className: "w-16 sm:w-20 text-right",
|
|
232
|
+
children: "End"
|
|
233
|
+
})] })]
|
|
234
|
+
}), /* @__PURE__ */ O("div", {
|
|
219
235
|
className: "flex-1 overflow-hidden",
|
|
220
236
|
ref: Y,
|
|
221
|
-
children: /* @__PURE__ */
|
|
237
|
+
children: /* @__PURE__ */ O("div", {
|
|
222
238
|
className: "flex h-full",
|
|
223
|
-
style: { width: J.length *
|
|
224
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
225
|
-
className:
|
|
239
|
+
style: { width: J.length * g },
|
|
240
|
+
children: J.map((e, t) => /* @__PURE__ */ k("div", {
|
|
241
|
+
className: b("flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full", e.isWeekend && "bg-muted/50"),
|
|
226
242
|
style: {
|
|
227
|
-
width:
|
|
228
|
-
minWidth:
|
|
243
|
+
width: g,
|
|
244
|
+
minWidth: g
|
|
229
245
|
},
|
|
230
|
-
children: [/* @__PURE__ */
|
|
246
|
+
children: [/* @__PURE__ */ O("span", {
|
|
231
247
|
className: "font-medium text-foreground",
|
|
232
248
|
children: e.label
|
|
233
|
-
}), /* @__PURE__ */
|
|
249
|
+
}), /* @__PURE__ */ O("span", {
|
|
234
250
|
className: "text-[10px] opacity-70",
|
|
235
251
|
children: e.date.toLocaleDateString(void 0, { weekday: "narrow" })
|
|
236
252
|
})]
|
|
237
253
|
}, t))
|
|
238
254
|
})
|
|
239
255
|
})]
|
|
240
|
-
}), /* @__PURE__ */
|
|
256
|
+
}), /* @__PURE__ */ k("div", {
|
|
241
257
|
className: "flex flex-1 overflow-hidden",
|
|
242
|
-
children: [/* @__PURE__ */
|
|
258
|
+
children: [/* @__PURE__ */ O("div", {
|
|
243
259
|
className: "overflow-hidden border-r bg-card z-10 shadow-sm",
|
|
244
260
|
ref: X,
|
|
245
261
|
style: {
|
|
246
|
-
width:
|
|
247
|
-
minWidth:
|
|
262
|
+
width: F,
|
|
263
|
+
minWidth: F
|
|
248
264
|
},
|
|
249
265
|
children: t.map((e) => {
|
|
250
|
-
let t =
|
|
251
|
-
return /* @__PURE__ */
|
|
252
|
-
className: "flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",
|
|
253
|
-
style: { height:
|
|
254
|
-
onClick: () => !t &&
|
|
266
|
+
let t = s && L === e.id;
|
|
267
|
+
return /* @__PURE__ */ k("div", {
|
|
268
|
+
className: "group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation",
|
|
269
|
+
style: { height: m },
|
|
270
|
+
onClick: () => !t && i?.(e),
|
|
255
271
|
onDoubleClick: () => {
|
|
256
|
-
|
|
272
|
+
s && a && (R(e.id), B({
|
|
257
273
|
title: e.title,
|
|
258
274
|
start: e.start.toLocaleDateString("en-CA"),
|
|
259
275
|
end: e.end.toLocaleDateString("en-CA"),
|
|
@@ -261,34 +277,34 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
261
277
|
}));
|
|
262
278
|
},
|
|
263
279
|
children: [
|
|
264
|
-
/* @__PURE__ */
|
|
280
|
+
/* @__PURE__ */ k("div", {
|
|
265
281
|
className: "flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2",
|
|
266
|
-
children: [/* @__PURE__ */
|
|
282
|
+
children: [/* @__PURE__ */ O("div", {
|
|
267
283
|
className: "w-2 h-2 rounded-full shrink-0",
|
|
268
284
|
style: { backgroundColor: e.color || "#3b82f6" }
|
|
269
|
-
}), t ? /* @__PURE__ */
|
|
285
|
+
}), t ? /* @__PURE__ */ O("input", {
|
|
270
286
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
271
|
-
value:
|
|
272
|
-
onChange: (e) =>
|
|
287
|
+
value: z.title || "",
|
|
288
|
+
onChange: (e) => B((t) => ({
|
|
273
289
|
...t,
|
|
274
290
|
title: e.target.value
|
|
275
291
|
})),
|
|
276
292
|
onKeyDown: (t) => {
|
|
277
|
-
t.key === "Enter" ? (
|
|
278
|
-
title:
|
|
279
|
-
start: new Date(
|
|
280
|
-
end: new Date(
|
|
281
|
-
progress: Number(
|
|
282
|
-
}),
|
|
293
|
+
t.key === "Enter" ? (a?.(e, {
|
|
294
|
+
title: z.title,
|
|
295
|
+
start: new Date(z.start),
|
|
296
|
+
end: new Date(z.end),
|
|
297
|
+
progress: Number(z.progress) || 0
|
|
298
|
+
}), R(null)) : t.key === "Escape" && R(null);
|
|
283
299
|
},
|
|
284
300
|
onClick: (e) => e.stopPropagation(),
|
|
285
301
|
autoFocus: !0
|
|
286
|
-
}) : /* @__PURE__ */
|
|
302
|
+
}) : /* @__PURE__ */ k("span", {
|
|
287
303
|
className: "flex flex-col min-w-0",
|
|
288
|
-
children: [/* @__PURE__ */
|
|
304
|
+
children: [/* @__PURE__ */ O("span", {
|
|
289
305
|
className: "truncate",
|
|
290
306
|
children: e.title
|
|
291
|
-
}), /* @__PURE__ */
|
|
307
|
+
}), /* @__PURE__ */ k("span", {
|
|
292
308
|
className: "text-[10px] text-muted-foreground sm:hidden",
|
|
293
309
|
children: [
|
|
294
310
|
e.start.toLocaleDateString(void 0, {
|
|
@@ -304,13 +320,15 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
304
320
|
})]
|
|
305
321
|
})]
|
|
306
322
|
}),
|
|
307
|
-
/* @__PURE__ */
|
|
323
|
+
/* @__PURE__ */ O("div", {
|
|
308
324
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
309
|
-
|
|
325
|
+
hidden: !I,
|
|
326
|
+
style: I ? void 0 : { display: "none" },
|
|
327
|
+
children: t ? /* @__PURE__ */ O("input", {
|
|
310
328
|
type: "date",
|
|
311
329
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
312
|
-
value:
|
|
313
|
-
onChange: (e) =>
|
|
330
|
+
value: z.start || "",
|
|
331
|
+
onChange: (e) => B((t) => ({
|
|
314
332
|
...t,
|
|
315
333
|
start: e.target.value
|
|
316
334
|
})),
|
|
@@ -320,13 +338,15 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
320
338
|
day: "numeric"
|
|
321
339
|
})
|
|
322
340
|
}),
|
|
323
|
-
/* @__PURE__ */
|
|
341
|
+
/* @__PURE__ */ O("div", {
|
|
324
342
|
className: "w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block",
|
|
325
|
-
|
|
343
|
+
hidden: !I,
|
|
344
|
+
style: I ? void 0 : { display: "none" },
|
|
345
|
+
children: t ? /* @__PURE__ */ O("input", {
|
|
326
346
|
type: "date",
|
|
327
347
|
className: "border rounded px-1 py-0.5 text-xs w-full bg-background",
|
|
328
|
-
value:
|
|
329
|
-
onChange: (e) =>
|
|
348
|
+
value: z.end || "",
|
|
349
|
+
onChange: (e) => B((t) => ({
|
|
330
350
|
...t,
|
|
331
351
|
end: e.target.value
|
|
332
352
|
})),
|
|
@@ -339,7 +359,7 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
339
359
|
]
|
|
340
360
|
}, e.id);
|
|
341
361
|
})
|
|
342
|
-
}), /* @__PURE__ */
|
|
362
|
+
}), /* @__PURE__ */ O("div", {
|
|
343
363
|
className: "flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]",
|
|
344
364
|
ref: (e) => {
|
|
345
365
|
ie.current = e, Z.current = e;
|
|
@@ -349,58 +369,105 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
349
369
|
onTouchMove: oe,
|
|
350
370
|
onTouchEnd: se,
|
|
351
371
|
"data-testid": "gantt-timeline",
|
|
352
|
-
children: /* @__PURE__ */
|
|
372
|
+
children: /* @__PURE__ */ k("div", {
|
|
353
373
|
className: "relative",
|
|
354
|
-
style: { width: J.length *
|
|
355
|
-
children: [$ != null && /* @__PURE__ */
|
|
374
|
+
style: { width: J.length * g },
|
|
375
|
+
children: [$ != null && /* @__PURE__ */ O("div", {
|
|
356
376
|
className: "absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none",
|
|
357
377
|
style: { left: $ },
|
|
358
378
|
"data-testid": "gantt-today-marker",
|
|
359
379
|
"aria-label": "Today",
|
|
360
|
-
children: /* @__PURE__ */
|
|
380
|
+
children: /* @__PURE__ */ O("div", {
|
|
361
381
|
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",
|
|
362
382
|
children: "Today"
|
|
363
383
|
})
|
|
364
|
-
}), /* @__PURE__ */
|
|
384
|
+
}), /* @__PURE__ */ k("div", {
|
|
365
385
|
className: "relative",
|
|
366
386
|
children: [
|
|
367
|
-
/* @__PURE__ */
|
|
387
|
+
/* @__PURE__ */ O("div", {
|
|
368
388
|
className: "absolute inset-0 flex pointer-events-none z-0",
|
|
369
|
-
children: J.map((e, t) => /* @__PURE__ */
|
|
370
|
-
className:
|
|
389
|
+
children: J.map((e, t) => /* @__PURE__ */ O("div", {
|
|
390
|
+
className: b("border-r h-full", e.isWeekend && "bg-muted/20"),
|
|
371
391
|
style: {
|
|
372
|
-
width:
|
|
373
|
-
minWidth:
|
|
392
|
+
width: g,
|
|
393
|
+
minWidth: g
|
|
374
394
|
}
|
|
375
395
|
}, t))
|
|
376
396
|
}),
|
|
377
397
|
t.map((e) => {
|
|
378
|
-
let t = ue(e);
|
|
379
|
-
|
|
398
|
+
let t = ue(e), n = V?.taskId === e.id, r = t;
|
|
399
|
+
if (n && V) {
|
|
400
|
+
let t = G(V);
|
|
401
|
+
r = ue({
|
|
402
|
+
...e,
|
|
403
|
+
start: t.start,
|
|
404
|
+
end: t.end
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
let o = !!a;
|
|
408
|
+
return /* @__PURE__ */ k("div", {
|
|
380
409
|
className: "relative border-b hover:bg-black/5",
|
|
381
|
-
style: { height:
|
|
382
|
-
children: /* @__PURE__ */ O("div", {
|
|
383
|
-
className: "absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm
|
|
410
|
+
style: { height: m },
|
|
411
|
+
children: [n && /* @__PURE__ */ O("div", {
|
|
412
|
+
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",
|
|
384
413
|
style: {
|
|
385
414
|
left: t.left,
|
|
386
415
|
width: t.width,
|
|
416
|
+
opacity: .35
|
|
417
|
+
},
|
|
418
|
+
"aria-hidden": "true"
|
|
419
|
+
}), /* @__PURE__ */ k("div", {
|
|
420
|
+
className: b("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"),
|
|
421
|
+
style: {
|
|
422
|
+
left: r.left,
|
|
423
|
+
width: r.width,
|
|
387
424
|
backgroundColor: e.color || "#3b82f6"
|
|
388
425
|
},
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
426
|
+
"data-testid": `gantt-task-bar-${e.id}`,
|
|
427
|
+
onClick: () => {
|
|
428
|
+
W.current || i?.(e);
|
|
429
|
+
},
|
|
430
|
+
onPointerDown: o ? (t) => {
|
|
431
|
+
t.button === 0 && K(e, "move", t);
|
|
432
|
+
} : void 0,
|
|
433
|
+
children: [
|
|
434
|
+
o && r.width >= 14 && /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O("div", {
|
|
435
|
+
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
436
|
+
"data-testid": `gantt-task-resize-left-${e.id}`,
|
|
437
|
+
onPointerDown: (t) => {
|
|
438
|
+
t.button === 0 && K(e, "resize-left", t);
|
|
439
|
+
},
|
|
440
|
+
onClick: (e) => e.stopPropagation()
|
|
441
|
+
}), /* @__PURE__ */ O("div", {
|
|
442
|
+
className: "absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40",
|
|
443
|
+
"data-testid": `gantt-task-resize-right-${e.id}`,
|
|
444
|
+
onPointerDown: (t) => {
|
|
445
|
+
t.button === 0 && K(e, "resize-right", t);
|
|
446
|
+
},
|
|
447
|
+
onClick: (e) => e.stopPropagation()
|
|
448
|
+
})] }),
|
|
449
|
+
e.progress > 0 && /* @__PURE__ */ O("div", {
|
|
450
|
+
className: "absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none",
|
|
451
|
+
style: { width: `${e.progress}%` }
|
|
452
|
+
}),
|
|
453
|
+
/* @__PURE__ */ O("span", {
|
|
454
|
+
className: "text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none",
|
|
455
|
+
children: n ? `${G(V).start.toLocaleDateString(void 0, {
|
|
456
|
+
month: "numeric",
|
|
457
|
+
day: "numeric"
|
|
458
|
+
})} → ${G(V).end.toLocaleDateString(void 0, {
|
|
459
|
+
month: "numeric",
|
|
460
|
+
day: "numeric"
|
|
461
|
+
})}` : `${Math.round(e.progress)}%`
|
|
462
|
+
})
|
|
463
|
+
]
|
|
464
|
+
})]
|
|
398
465
|
}, e.id);
|
|
399
466
|
}),
|
|
400
|
-
/* @__PURE__ */
|
|
467
|
+
/* @__PURE__ */ O("div", {
|
|
401
468
|
className: "absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none",
|
|
402
|
-
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) *
|
|
403
|
-
children: /* @__PURE__ */
|
|
469
|
+
style: { left: ((/* @__PURE__ */ new Date()).getTime() - q.start.getTime()) / (1e3 * 60 * 60 * 24) * g },
|
|
470
|
+
children: /* @__PURE__ */ O("div", { className: "w-2 h-2 rounded-full bg-red-500 -ml-[3px]" })
|
|
404
471
|
})
|
|
405
472
|
]
|
|
406
473
|
})]
|
|
@@ -412,7 +479,7 @@ function A({ tasks: t, viewMode: n = "month", startDate: r, endDate: i, onTaskCl
|
|
|
412
479
|
}
|
|
413
480
|
//#endregion
|
|
414
481
|
//#region src/ObjectGantt.tsx
|
|
415
|
-
function
|
|
482
|
+
function F(e) {
|
|
416
483
|
return e.data ? e.data : e.staticData ? {
|
|
417
484
|
provider: "value",
|
|
418
485
|
items: e.staticData
|
|
@@ -421,7 +488,7 @@ function j(e) {
|
|
|
421
488
|
object: e.objectName
|
|
422
489
|
} : null;
|
|
423
490
|
}
|
|
424
|
-
function
|
|
491
|
+
function I(e) {
|
|
425
492
|
if (e) {
|
|
426
493
|
if (typeof e == "string") {
|
|
427
494
|
let t = e.split(" "), n = t[0], r = t[1]?.toLowerCase() === "desc" ? "desc" : "asc";
|
|
@@ -430,7 +497,7 @@ function M(e) {
|
|
|
430
497
|
if (Array.isArray(e)) return e.reduce((e, t) => (t.field && t.order && (e[t.field] = t.order), e), {});
|
|
431
498
|
}
|
|
432
499
|
}
|
|
433
|
-
function
|
|
500
|
+
function L(e) {
|
|
434
501
|
let t = null;
|
|
435
502
|
if (e.startDateField && e.endDateField) return t = {
|
|
436
503
|
startDateField: e.startDateField,
|
|
@@ -441,147 +508,263 @@ function N(e) {
|
|
|
441
508
|
colorField: e.colorField
|
|
442
509
|
}, t;
|
|
443
510
|
if (e.gantt && (t = e.gantt), t) {
|
|
444
|
-
let e =
|
|
511
|
+
let e = u.safeParse(t);
|
|
445
512
|
return e.success || console.warn("[ObjectGantt] Invalid gantt configuration:", e.error.format()), t;
|
|
446
513
|
}
|
|
447
514
|
return null;
|
|
448
515
|
}
|
|
449
|
-
var
|
|
450
|
-
let [
|
|
451
|
-
|
|
516
|
+
var R = ({ schema: e, dataSource: a, className: l, onTaskClick: u, onRowClick: y, ...b }) => {
|
|
517
|
+
let [x, S] = i([]), [C, w] = i(!0), [T, ne] = i(null), [E, re] = i(null), A = F(e), j = r(() => A, [JSON.stringify(A)]), M = L(e), N = j?.provider === "value";
|
|
518
|
+
n(() => {
|
|
452
519
|
(async () => {
|
|
453
520
|
try {
|
|
454
|
-
if (
|
|
455
|
-
|
|
521
|
+
if (w(!0), b.data && Array.isArray(b.data)) {
|
|
522
|
+
S(b.data), w(!1);
|
|
456
523
|
return;
|
|
457
524
|
}
|
|
458
|
-
if (
|
|
459
|
-
|
|
525
|
+
if (N && j?.provider === "value") {
|
|
526
|
+
S(j.items), w(!1);
|
|
460
527
|
return;
|
|
461
528
|
}
|
|
462
|
-
if (!
|
|
463
|
-
if (
|
|
464
|
-
let t =
|
|
465
|
-
|
|
529
|
+
if (!a || typeof a.find != "function") throw Error("DataSource required for object/api providers");
|
|
530
|
+
if (j?.provider === "object") {
|
|
531
|
+
let t = j.object, n = o(E?.fields);
|
|
532
|
+
S(s(await a.find(t, {
|
|
466
533
|
$filter: e.filter,
|
|
467
|
-
$orderby:
|
|
534
|
+
$orderby: I(e.sort),
|
|
468
535
|
...n.length > 0 ? { $expand: n } : {}
|
|
469
536
|
})));
|
|
470
|
-
} else
|
|
471
|
-
|
|
537
|
+
} else j?.provider === "api" && (console.warn("API provider not yet implemented for ObjectGantt"), S([]));
|
|
538
|
+
w(!1);
|
|
472
539
|
} catch (e) {
|
|
473
|
-
|
|
540
|
+
ne(e), w(!1);
|
|
474
541
|
}
|
|
475
542
|
})();
|
|
476
543
|
}, [
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
544
|
+
j,
|
|
545
|
+
a,
|
|
546
|
+
N,
|
|
480
547
|
e.filter,
|
|
481
548
|
e.sort,
|
|
482
|
-
|
|
483
|
-
]),
|
|
484
|
-
!
|
|
549
|
+
E
|
|
550
|
+
]), n(() => {
|
|
551
|
+
!N && a && (async () => {
|
|
485
552
|
try {
|
|
486
|
-
if (!
|
|
487
|
-
let t =
|
|
553
|
+
if (!a) return;
|
|
554
|
+
let t = j?.provider === "object" ? j.object : e.objectName;
|
|
488
555
|
if (!t) return;
|
|
489
|
-
|
|
556
|
+
re(await a.getObjectSchema(t));
|
|
490
557
|
} catch (e) {
|
|
491
558
|
console.error("Failed to fetch object schema:", e);
|
|
492
559
|
}
|
|
493
560
|
})();
|
|
494
561
|
}, [
|
|
495
562
|
e.objectName,
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
563
|
+
a,
|
|
564
|
+
N,
|
|
565
|
+
j
|
|
499
566
|
]);
|
|
500
|
-
let
|
|
501
|
-
if (!
|
|
502
|
-
let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } =
|
|
503
|
-
|
|
504
|
-
let
|
|
567
|
+
let R = r(() => {
|
|
568
|
+
if (!M || !x.length) return [];
|
|
569
|
+
let { startDateField: e, endDateField: t, titleField: n, progressField: r, dependenciesField: i, colorField: a } = M, o = (e, t) => {
|
|
570
|
+
if (!t) return;
|
|
571
|
+
let n = t.split("."), r = e;
|
|
572
|
+
for (let e of n) {
|
|
573
|
+
if (r == null) return;
|
|
574
|
+
r = r[e];
|
|
575
|
+
}
|
|
576
|
+
return r;
|
|
577
|
+
}, s = (e) => {
|
|
578
|
+
let t = [
|
|
579
|
+
o(e, n),
|
|
580
|
+
e?.name,
|
|
581
|
+
e?.title,
|
|
582
|
+
e?.subject,
|
|
583
|
+
e?.label,
|
|
584
|
+
e?.account?.name,
|
|
585
|
+
e?.opportunity?.name,
|
|
586
|
+
e?.contact && [e.contact.first_name, e.contact.last_name].filter(Boolean).join(" "),
|
|
587
|
+
e?.id,
|
|
588
|
+
e?._id
|
|
589
|
+
];
|
|
590
|
+
for (let e of t) if (e != null && String(e).trim() !== "") return String(e);
|
|
591
|
+
return "Untitled";
|
|
592
|
+
};
|
|
593
|
+
return x.map((n, o) => {
|
|
594
|
+
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;
|
|
505
595
|
return {
|
|
506
|
-
id:
|
|
596
|
+
id: n.id || n._id || `task-${o}`,
|
|
507
597
|
title: u,
|
|
508
598
|
start: c ? new Date(c) : /* @__PURE__ */ new Date(),
|
|
509
599
|
end: l ? new Date(l) : /* @__PURE__ */ new Date(),
|
|
510
600
|
progress: Math.min(100, Math.max(0, d || 0)),
|
|
511
601
|
dependencies: Array.isArray(f) ? f : [],
|
|
512
602
|
color: p,
|
|
513
|
-
data:
|
|
603
|
+
data: n
|
|
514
604
|
};
|
|
515
605
|
}).filter((e) => !isNaN(e.start.getTime()) && !isNaN(e.end.getTime()));
|
|
516
|
-
}, [
|
|
517
|
-
|
|
606
|
+
}, [x, M]), z = e.navigation ?? {
|
|
607
|
+
mode: "drawer",
|
|
608
|
+
width: "min(960px, 60vw)"
|
|
609
|
+
}, B = z.mode === "drawer" || z.mode === "modal" || z.mode === "split" || z.mode === "popover", V = c({
|
|
610
|
+
navigation: z,
|
|
518
611
|
objectName: e.objectName,
|
|
519
|
-
onRowClick:
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
612
|
+
onRowClick: B ? void 0 : y
|
|
613
|
+
}), H = t(async (t, n) => {
|
|
614
|
+
if (!M) return;
|
|
615
|
+
let r = j?.provider === "object" ? j.object : e.objectName;
|
|
616
|
+
if (!r || !a || typeof a.update != "function") return;
|
|
617
|
+
let { startDateField: i, endDateField: o, titleField: s, progressField: c } = M, l = {};
|
|
618
|
+
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;
|
|
619
|
+
let u = t.data?.id ?? t.data?._id ?? t.id;
|
|
620
|
+
if (u == null) return;
|
|
621
|
+
let d = x;
|
|
622
|
+
S((e) => e.map((e) => String(e.id ?? e._id) === String(u) ? {
|
|
623
|
+
...e,
|
|
624
|
+
...l
|
|
625
|
+
} : e));
|
|
626
|
+
try {
|
|
627
|
+
await a.update(r, String(u), l);
|
|
628
|
+
} catch (e) {
|
|
629
|
+
console.error("[ObjectGantt] Failed to persist task update:", e), S(d);
|
|
630
|
+
}
|
|
631
|
+
}, [
|
|
632
|
+
M,
|
|
633
|
+
j,
|
|
634
|
+
a,
|
|
635
|
+
e.objectName,
|
|
636
|
+
x
|
|
637
|
+
]), [U, W] = i(null), [G, K] = i(!1), q = t((e) => {
|
|
638
|
+
W(e);
|
|
639
|
+
}, []), J = t(async () => {
|
|
640
|
+
if (!U) return;
|
|
641
|
+
let t = j?.provider === "object" ? j.object : e.objectName;
|
|
642
|
+
if (!t || !a?.delete) {
|
|
643
|
+
W(null);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
let n = U.data?.id ?? U.data?._id ?? U.id;
|
|
647
|
+
if (n == null) {
|
|
648
|
+
W(null);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
K(!0);
|
|
652
|
+
let r = x;
|
|
653
|
+
S((e) => e.filter((e) => String(e.id ?? e._id) !== String(n)));
|
|
654
|
+
try {
|
|
655
|
+
await a.delete(t, String(n)), W(null);
|
|
656
|
+
} catch (e) {
|
|
657
|
+
console.error("[ObjectGantt] Failed to delete:", e), S(r), W(null);
|
|
658
|
+
} finally {
|
|
659
|
+
K(!1);
|
|
660
|
+
}
|
|
661
|
+
}, [
|
|
662
|
+
U,
|
|
663
|
+
j,
|
|
664
|
+
a,
|
|
665
|
+
e.objectName,
|
|
666
|
+
x
|
|
667
|
+
]);
|
|
668
|
+
return C ? /* @__PURE__ */ O("div", {
|
|
669
|
+
className: l,
|
|
670
|
+
children: /* @__PURE__ */ O("div", {
|
|
524
671
|
className: "flex items-center justify-center h-96",
|
|
525
|
-
children: /* @__PURE__ */
|
|
672
|
+
children: /* @__PURE__ */ O("div", {
|
|
526
673
|
className: "text-muted-foreground",
|
|
527
674
|
children: "Loading Gantt chart..."
|
|
528
675
|
})
|
|
529
676
|
})
|
|
530
|
-
}) :
|
|
531
|
-
className:
|
|
532
|
-
children: /* @__PURE__ */
|
|
677
|
+
}) : T ? /* @__PURE__ */ O("div", {
|
|
678
|
+
className: l,
|
|
679
|
+
children: /* @__PURE__ */ O("div", {
|
|
533
680
|
className: "flex items-center justify-center h-96",
|
|
534
|
-
children: /* @__PURE__ */
|
|
681
|
+
children: /* @__PURE__ */ k("div", {
|
|
535
682
|
className: "text-destructive",
|
|
536
|
-
children: ["Error: ",
|
|
683
|
+
children: ["Error: ", T.message]
|
|
537
684
|
})
|
|
538
685
|
})
|
|
539
|
-
}) :
|
|
540
|
-
className:
|
|
541
|
-
children: [
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
686
|
+
}) : M ? /* @__PURE__ */ k("div", {
|
|
687
|
+
className: l,
|
|
688
|
+
children: [
|
|
689
|
+
/* @__PURE__ */ O("div", {
|
|
690
|
+
className: "h-[calc(100vh-200px)] min-h-[600px]",
|
|
691
|
+
children: /* @__PURE__ */ O(P, {
|
|
692
|
+
tasks: R,
|
|
693
|
+
onTaskClick: (e) => {
|
|
694
|
+
V.handleClick(e.data), u?.(e.data);
|
|
695
|
+
},
|
|
696
|
+
onTaskUpdate: H,
|
|
697
|
+
onTaskDelete: q,
|
|
698
|
+
inlineEdit: !0
|
|
699
|
+
})
|
|
700
|
+
}),
|
|
701
|
+
V.isOverlay && V.isOpen && V.selectedRecord && (() => {
|
|
702
|
+
let t = j?.provider === "object" ? j.object : e.objectName, n = V.selectedRecord, r = n.id ?? n._id;
|
|
703
|
+
if (!t || r == null) return null;
|
|
704
|
+
let i = M?.titleField ? String(n[M.titleField] ?? "Task Details") : "Task Details";
|
|
705
|
+
return /* @__PURE__ */ O(d, {
|
|
706
|
+
open: !0,
|
|
707
|
+
onClose: V.close,
|
|
708
|
+
title: i,
|
|
709
|
+
record: n,
|
|
710
|
+
objectName: t,
|
|
711
|
+
recordId: r,
|
|
712
|
+
dataSource: a,
|
|
713
|
+
objectSchema: E,
|
|
714
|
+
width: V.width,
|
|
715
|
+
fullPageHref: f(t, r) ?? void 0,
|
|
716
|
+
onFieldSave: async (e, n) => {
|
|
717
|
+
a?.update && (await a.update(t, String(r), { [e]: n }), S((t) => t.map((t) => String(t.id ?? t._id) === String(r) ? {
|
|
718
|
+
...t,
|
|
719
|
+
[e]: n
|
|
720
|
+
} : t)));
|
|
721
|
+
},
|
|
722
|
+
onDelete: async () => {
|
|
723
|
+
a?.delete && (await a.delete(t, String(r)), S((e) => e.filter((e) => String(e.id ?? e._id) !== String(r))));
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
})(),
|
|
727
|
+
/* @__PURE__ */ O(p, {
|
|
728
|
+
open: !!U,
|
|
729
|
+
onOpenChange: (e) => {
|
|
730
|
+
!e && !G && W(null);
|
|
547
731
|
},
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
}, e))
|
|
732
|
+
children: /* @__PURE__ */ k(te, { children: [/* @__PURE__ */ k(_, { children: [/* @__PURE__ */ O(v, { children: "Delete this task?" }), /* @__PURE__ */ O(h, { children: U ? /* @__PURE__ */ k(D, { children: [
|
|
733
|
+
"\"",
|
|
734
|
+
U.title,
|
|
735
|
+
"\" will be permanently removed. This action cannot be undone."
|
|
736
|
+
] }) : null })] }), /* @__PURE__ */ k(g, { children: [/* @__PURE__ */ O(ee, {
|
|
737
|
+
disabled: G,
|
|
738
|
+
children: "Cancel"
|
|
739
|
+
}), /* @__PURE__ */ O(m, {
|
|
740
|
+
onClick: (e) => {
|
|
741
|
+
e.preventDefault(), J();
|
|
742
|
+
},
|
|
743
|
+
disabled: G,
|
|
744
|
+
"data-testid": "gantt-delete-confirm",
|
|
745
|
+
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
746
|
+
children: G ? "Deleting…" : "Delete"
|
|
747
|
+
})] })] })
|
|
565
748
|
})
|
|
566
|
-
|
|
567
|
-
}) : /* @__PURE__ */
|
|
568
|
-
className:
|
|
569
|
-
children: /* @__PURE__ */
|
|
749
|
+
]
|
|
750
|
+
}) : /* @__PURE__ */ O("div", {
|
|
751
|
+
className: l,
|
|
752
|
+
children: /* @__PURE__ */ O("div", {
|
|
570
753
|
className: "flex items-center justify-center h-96",
|
|
571
|
-
children: /* @__PURE__ */
|
|
754
|
+
children: /* @__PURE__ */ O("div", {
|
|
572
755
|
className: "text-muted-foreground",
|
|
573
756
|
children: "Gantt configuration required. Please specify startDateField, endDateField, and titleField."
|
|
574
757
|
})
|
|
575
758
|
})
|
|
576
759
|
});
|
|
577
|
-
},
|
|
578
|
-
let { dataSource: t } =
|
|
579
|
-
return /* @__PURE__ */
|
|
760
|
+
}, z = ({ schema: e }) => {
|
|
761
|
+
let { dataSource: t } = l() || {};
|
|
762
|
+
return /* @__PURE__ */ O(R, {
|
|
580
763
|
schema: e,
|
|
581
764
|
dataSource: t
|
|
582
765
|
});
|
|
583
766
|
};
|
|
584
|
-
|
|
767
|
+
a.register("object-gantt", z, {
|
|
585
768
|
namespace: "plugin-gantt",
|
|
586
769
|
label: "Object Gantt",
|
|
587
770
|
category: "view",
|
|
@@ -596,7 +779,7 @@ i.register("object-gantt", F, {
|
|
|
596
779
|
label: "Gantt Config",
|
|
597
780
|
description: "startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField"
|
|
598
781
|
}]
|
|
599
|
-
}),
|
|
782
|
+
}), a.register("gantt", z, {
|
|
600
783
|
namespace: "view",
|
|
601
784
|
label: "Gantt View",
|
|
602
785
|
category: "view",
|
|
@@ -613,4 +796,4 @@ i.register("object-gantt", F, {
|
|
|
613
796
|
}]
|
|
614
797
|
});
|
|
615
798
|
//#endregion
|
|
616
|
-
export {
|
|
799
|
+
export { P as GanttView, R as ObjectGantt, z as ObjectGanttRenderer };
|
package/dist/index.umd.cjs
CHANGED
|
@@ -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/components`),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/components`,`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.ObjectUIComponents,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var c=Object.create,l=Object.defineProperty,u=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,f=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty,m=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=d(t),a=0,o=i.length,s;a<o;a++)s=i[a],!p.call(e,s)&&s!==n&&l(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=u(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:c(f(e)),m(t||!e||!e.__esModule?l(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function h(e){return e<640?35:e<1024?50:60}function g(e){return e<640?120:e<1024?200:300}function _(e){return e<640?32:40}function v({tasks:e,viewMode:n=`month`,startDate:r,endDate:i,onTaskClick:c,onTaskUpdate:l,onViewChange:u,onAddClick:d,className:f,inlineEdit:p=!1}){let[m,v]=t.useState(new Date),y=t.useRef(null),{width:b}=(0,a.useResizeObserver)(y),x=b||(typeof window<`u`?window.innerWidth:1024),S=x<640,C=_(x),w=h(x),[T,E]=t.useState(null),D=T??w,[O,k]=t.useState(!1),A=t.useRef(!1);t.useEffect(()=>{!A.current&&S&&(k(!0),A.current=!0)},[S]);let j=O?0:g(x),[M,N]=t.useState(null),[P,F]=t.useState({}),I=t.useMemo(()=>{let t=r?new Date(r):new Date,n=i?new Date(i):new Date;return!r&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!i&&e.length>0&&(n=new Date(Math.max(...e.map(e=>e.end.getTime()))),n.setDate(n.getDate()+14)),t.setHours(0,0,0,0),n.setHours(23,59,59,999),{start:t,end:n}},[r,i,e]),L=t.useMemo(()=>{let e=[],t=new Date(I.start);for(;t<=I.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},[I]),R=t.useRef(null),z=t.useRef(null),B=t.useRef(null),V=t.useRef(null),H=t.useRef(null),U=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;H.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:D}}},[D]),W=t.useCallback(e=>{if(e.touches.length!==2||!H.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))/H.current.baseDistance;E(Math.max(15,Math.min(120,Math.round(H.current.baseColumn*r))))},[]),G=t.useCallback(()=>{H.current=null},[]),K=t.useMemo(()=>{let e=new Date;if(e<I.start||e>I.end)return null;let t=(e.getTime()-I.start.getTime())/(1440*60*1e3);return Math.round(t*D)},[I,D]),q=t.useCallback(()=>{if(K==null||!V.current)return;let e=Math.max(0,K-V.current.clientWidth/2);V.current.scrollTo({left:e,behavior:`smooth`})},[K]),J=e=>{R.current&&(R.current.scrollLeft=e.currentTarget.scrollLeft),z.current&&(z.current.scrollTop=e.currentTarget.scrollTop)},Y=e=>{I.end.getTime()-I.start.getTime();let t=D,n=1e3*60*60*24,r=e.start.getTime()-I.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,s.jsxs)(`div`,{ref:y,className:(0,a.cn)(`flex flex-col h-full bg-background border rounded-lg overflow-hidden min-w-0`,f),children:[(0,s.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,s.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,s.jsxs)(a.Button,{variant:`outline`,size:`sm`,onClick:()=>d?.(),"aria-label":`Create new task`,children:[(0,s.jsx)(o.Plus,{className:`h-4 w-4 mr-1 sm:mr-2`}),(0,s.jsx)(`span`,{className:`hidden sm:inline`,children:`New Task`}),(0,s.jsx)(`span`,{className:`sm:hidden`,children:`New`})]}),(0,s.jsx)(`div`,{className:`h-4 w-px bg-border mx-1 sm:mx-2`}),(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Previous period`,children:(0,s.jsx)(o.ChevronLeft,{className:`h-4 w-4`})}),(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Next period`,children:(0,s.jsx)(o.ChevronRight,{className:`h-4 w-4`})}),(0,s.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:I.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,s.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,s.jsxs)(a.Select,{value:n,onValueChange:e=>u?.(e),children:[(0,s.jsx)(a.SelectTrigger,{className:`w-[100px] sm:w-[120px] h-8`,children:(0,s.jsx)(a.SelectValue,{})}),(0,s.jsxs)(a.SelectContent,{children:[(0,s.jsx)(a.SelectItem,{value:`day`,children:`Day View`}),(0,s.jsx)(a.SelectItem,{value:`week`,children:`Week View`}),(0,s.jsx)(a.SelectItem,{value:`month`,children:`Month View`}),(0,s.jsx)(a.SelectItem,{value:`quarter`,children:`Quarter View`})]})]}),(0,s.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.max(15,D-10)),"aria-label":`Zoom out`,children:(0,s.jsx)(o.ZoomOut,{className:`h-3 w-3`})}),(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.min(120,D+10)),"aria-label":`Zoom in`,children:(0,s.jsx)(o.ZoomIn,{className:`h-3 w-3`})})]}),(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>k(e=>!e),"aria-label":O?`Show task list`:`Hide task list`,"aria-pressed":O,"data-testid":`gantt-toggle-task-list`,children:O?(0,s.jsx)(o.PanelLeft,{className:`h-4 w-4`}):(0,s.jsx)(o.PanelLeftClose,{className:`h-4 w-4`})}),(0,s.jsx)(a.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:q,disabled:K==null,"aria-label":`Jump to today`,"data-testid":`gantt-jump-today`,children:(0,s.jsx)(o.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,s.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,s.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,s.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,s.jsx)(`div`,{className:`flex-1`,children:`Task Name`}),(0,s.jsx)(`div`,{className:`w-16 sm:w-20 text-right hidden sm:block`,children:`Start`}),(0,s.jsx)(`div`,{className:`w-16 sm:w-20 text-right hidden sm:block`,children:`End`})]}),(0,s.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:R,children:(0,s.jsx)(`div`,{className:`flex h-full`,style:{width:L.length*D},children:L.map((e,t)=>(0,s.jsxs)(`div`,{className:(0,a.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,s.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,s.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,s.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,s.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:z,style:{width:j,minWidth:j},children:e.map(e=>{let t=p&&M===e.id;return(0,s.jsxs)(`div`,{className:`flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:C},onClick:()=>!t&&c?.(e),onDoubleClick:()=>{p&&l&&(N(e.id),F({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,s.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,s.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,s.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:P.title||``,onChange:e=>F(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(l?.(e,{title:P.title,start:new Date(P.start),end:new Date(P.end),progress:Number(P.progress)||0}),N(null)):t.key===`Escape`&&N(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,s.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,s.jsx)(`span`,{className:`truncate`,children:e.title}),(0,s.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,s.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,children:t?(0,s.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:P.start||``,onChange:e=>F(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,s.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,children:t?(0,s.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:P.end||``,onChange:e=>F(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,s.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{B.current=e,V.current=e},onScroll:J,onTouchStart:U,onTouchMove:W,onTouchEnd:G,"data-testid":`gantt-timeline`,children:(0,s.jsxs)(`div`,{className:`relative`,style:{width:L.length*D},children:[K!=null&&(0,s.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:K},"data-testid":`gantt-today-marker`,"aria-label":`Today`,children:(0,s.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,s.jsxs)(`div`,{className:`relative`,children:[(0,s.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:L.map((e,t)=>(0,s.jsx)(`div`,{className:(0,a.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:D,minWidth:D}},t))}),e.map(e=>{let t=Y(e);return(0,s.jsx)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:C},children:(0,s.jsxs)(`div`,{className:`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 cursor-pointer hover:brightness-110 flex items-center px-2 group`,style:{left:t.left,width:t.width,backgroundColor:e.color||`#3b82f6`},onClick:()=>c?.(e),children:[e.progress>0&&(0,s.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm`,style:{width:`${e.progress}%`}}),(0,s.jsxs)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity`,children:[Math.round(e.progress),`%`]})]})},e.id)}),(0,s.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-I.start.getTime())/(1e3*60*60*24)*D},children:(0,s.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function y(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function b(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 x(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 S=({schema:e,dataSource:i,className:o,onTaskClick:c,onRowClick:l,...u})=>{let[d,f]=(0,t.useState)([]),[p,m]=(0,t.useState)(!0),[h,g]=(0,t.useState)(null),[_,S]=(0,t.useState)(null),C=y(e),w=(0,t.useMemo)(()=>C,[JSON.stringify(C)]),T=x(e),E=w?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(m(!0),u.data&&Array.isArray(u.data)){f(u.data),m(!1);return}if(E&&w?.provider===`value`){f(w.items),m(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(w?.provider===`object`){let t=w.object,r=(0,n.buildExpandFields)(_?.fields);f((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:b(e.sort),...r.length>0?{$expand:r}:{}})))}else w?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),f([]));m(!1)}catch(e){g(e),m(!1)}})()},[w,i,E,e.filter,e.sort,_]),(0,t.useEffect)(()=>{!E&&i&&(async()=>{try{if(!i)return;let t=w?.provider===`object`?w.object:e.objectName;if(!t)return;S(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,E,w]);let D=(0,t.useMemo)(()=>{if(!T||!d.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=T;return d.map((o,s)=>{let c=o[e],l=o[t],u=o[n]||`Untitled Task`,d=r?o[r]:0,f=i?o[i]:[],p=a?o[a]:void 0;return{id:o.id||o._id||`task-${s}`,title:u,start:c?new Date(c):new Date,end:l?new Date(l):new Date,progress:Math.min(100,Math.max(0,d||0)),dependencies:Array.isArray(f)?f:[],color:p,data:o}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[d,T]),O=(0,r.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:l});return p?(0,s.jsx)(`div`,{className:o,children:(0,s.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,s.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):h?(0,s.jsx)(`div`,{className:o,children:(0,s.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,s.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,h.message]})})}):T?(0,s.jsxs)(`div`,{className:o,children:[(0,s.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,s.jsx)(v,{tasks:D,onTaskClick:e=>{O.handleClick(e.data),c?.(e.data)},onAddClick:()=>{}})}),O.isOverlay&&(0,s.jsx)(a.NavigationOverlay,{...O,title:`Task Details`,children:e=>(0,s.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,s.jsxs)(`div`,{className:`flex flex-col`,children:[(0,s.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,s.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]}):(0,s.jsx)(`div`,{className:o,children:(0,s.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,s.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},C=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,s.jsx)(S,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,C,{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`,C,{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=v,e.ObjectGantt=S,e.ObjectGanttRenderer=C});
|
|
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(`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`,`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.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule?u(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);function g(e){return e<640?35:e<1024?50:60}function _(e){return e<640?140:e<1024?220:320}function v(e){return e>=280}function y(e){return e<640?32:40}function b({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:l,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),b=h<640,x=y(h),S=g(h),[C,w]=t.useState(null),T=C??S,[E,D]=t.useState(!1),O=t.useRef(!1);t.useEffect(()=>{!O.current&&b&&(D(!0),O.current=!0)},[b]);let k=E?0:_(h),A=v(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,c.jsxs)(`div`,{ref:p,className:(0,o.cn)(`flex flex-col h-full bg-background border rounded-lg overflow-hidden min-w-0`,l),children:[(0,c.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,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Previous period`,children:(0,c.jsx)(s.ChevronLeft,{className:`h-4 w-4`})}),(0,c.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":`Next period`,children:(0,c.jsx)(s.ChevronRight,{className:`h-4 w-4`})}),(0,c.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:V.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,c.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,c.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,c.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,c.jsx)(s.ZoomOut,{className:`h-3 w-3`})}),(0,c.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,c.jsx)(s.ZoomIn,{className:`h-3 w-3`})})]}),(0,c.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,c.jsx)(s.PanelLeft,{className:`h-4 w-4`}):(0,c.jsx)(s.PanelLeftClose,{className:`h-4 w-4`})}),(0,c.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,c.jsx)(s.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,c.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,c.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,c.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,c.jsx)(`div`,{className:`flex-1 truncate`,children:`Task Name`}),A&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`Start`}),(0,c.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:`End`})]})]}),(0,c.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:U,children:(0,c.jsx)(`div`,{className:`flex h-full`,style:{width:H.length*T},children:H.map((e,t)=>(0,c.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,c.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,c.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,c.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,c.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,c.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,c.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,c.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,c.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,c.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,c.jsx)(`span`,{className:`truncate`,children:e.title}),(0,c.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,c.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,c.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,c.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,c.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,c.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,c.jsxs)(`div`,{className:`relative`,style:{width:H.length*T},children:[Z!=null&&(0,c.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,c.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,c.jsxs)(`div`,{className:`relative`,children:[(0,c.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:H.map((e,t)=>(0,c.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,c.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:x},children:[n&&(0,c.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,c.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,c.jsxs)(c.Fragment,{children:[(0,c.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,c.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,c.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,c.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,c.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,c.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function x(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function S(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 C(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 w=({schema:e,dataSource:i,className:s,onTaskClick:l,onRowClick:u,...d})=>{let[f,p]=(0,t.useState)([]),[m,h]=(0,t.useState)(!0),[g,_]=(0,t.useState)(null),[v,y]=(0,t.useState)(null),w=x(e),T=(0,t.useMemo)(()=>w,[JSON.stringify(w)]),E=C(e),D=T?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(h(!0),d.data&&Array.isArray(d.data)){p(d.data),h(!1);return}if(D&&T?.provider===`value`){p(T.items),h(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(T?.provider===`object`){let t=T.object,r=(0,n.buildExpandFields)(v?.fields);p((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:S(e.sort),...r.length>0?{$expand:r}:{}})))}else T?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),p([]));h(!1)}catch(e){_(e),h(!1)}})()},[T,i,D,e.filter,e.sort,v]),(0,t.useEffect)(()=>{!D&&i&&(async()=>{try{if(!i)return;let t=T?.provider===`object`?T.object:e.objectName;if(!t)return;y(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,D,T]);let O=(0,t.useMemo)(()=>{if(!E||!f.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=E,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},s=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 f.map((n,o)=>{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;return{id:n.id||n._id||`task-${o}`,title:u,start:c?new Date(c):new Date,end:l?new Date(l):new Date,progress:Math.min(100,Math.max(0,d||0)),dependencies:Array.isArray(f)?f:[],color:p,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[f,E]),k=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},A=k.mode===`drawer`||k.mode===`modal`||k.mode===`split`||k.mode===`popover`,j=(0,r.useNavigationOverlay)({navigation:k,objectName:e.objectName,onRowClick:A?void 0:u}),M=(0,t.useCallback)(async(t,n)=>{if(!E)return;let r=T?.provider===`object`?T.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=E,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=f;p(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),p(d)}},[E,T,i,e.objectName,f]),[N,P]=(0,t.useState)(null),[F,I]=(0,t.useState)(!1),L=(0,t.useCallback)(e=>{P(e)},[]),R=(0,t.useCallback)(async()=>{if(!N)return;let t=T?.provider===`object`?T.object:e.objectName;if(!t||!i?.delete){P(null);return}let n=N.data?.id??N.data?._id??N.id;if(n==null){P(null);return}I(!0);let r=f;p(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),P(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),p(r),P(null)}finally{I(!1)}},[N,T,i,e.objectName,f]);return m?(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):g?(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,g.message]})})}):E?(0,c.jsxs)(`div`,{className:s,children:[(0,c.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,c.jsx)(b,{tasks:O,onTaskClick:e=>{j.handleClick(e.data),l?.(e.data)},onTaskUpdate:M,onTaskDelete:L,inlineEdit:!0})}),j.isOverlay&&j.isOpen&&j.selectedRecord&&(()=>{let t=T?.provider===`object`?T.object:e.objectName,n=j.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=E?.titleField?String(n[E.titleField]??`Task Details`):`Task Details`;return(0,c.jsx)(a.RecordDetailDrawer,{open:!0,onClose:j.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:v,width:j.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),p(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)),p(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,c.jsx)(o.AlertDialog,{open:!!N,onOpenChange:e=>{!e&&!F&&P(null)},children:(0,c.jsxs)(o.AlertDialogContent,{children:[(0,c.jsxs)(o.AlertDialogHeader,{children:[(0,c.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,c.jsx)(o.AlertDialogDescription,{children:N?(0,c.jsxs)(c.Fragment,{children:[`"`,N.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,c.jsxs)(o.AlertDialogFooter,{children:[(0,c.jsx)(o.AlertDialogCancel,{disabled:F,children:`Cancel`}),(0,c.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),R()},disabled:F,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:F?`Deleting…`:`Delete`})]})]})})]}):(0,c.jsx)(`div`,{className:s,children:(0,c.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,c.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},T=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,c.jsx)(w,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,T,{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`,T,{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=b,e.ObjectGantt=w,e.ObjectGanttRenderer=T});
|
|
@@ -15,19 +15,29 @@ export interface GanttTask {
|
|
|
15
15
|
data?: any;
|
|
16
16
|
dependencies?: (string | number)[];
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated The day/week/month/quarter view-mode dropdown was removed
|
|
20
|
+
* because all four values rendered the same daily-column timeline.
|
|
21
|
+
* Kept exported only to avoid breaking downstream type imports; the
|
|
22
|
+
* `viewMode` / `onViewChange` props on `GanttViewProps` are no-ops.
|
|
23
|
+
* Re-introduce real semantics here when timeline granularity is
|
|
24
|
+
* implemented.
|
|
25
|
+
*/
|
|
18
26
|
export type GanttViewMode = 'day' | 'week' | 'month' | 'quarter';
|
|
19
27
|
export interface GanttViewProps {
|
|
20
28
|
tasks: GanttTask[];
|
|
29
|
+
/** @deprecated no-op — see {@link GanttViewMode} */
|
|
21
30
|
viewMode?: GanttViewMode;
|
|
22
31
|
startDate?: Date;
|
|
23
32
|
endDate?: Date;
|
|
24
33
|
onTaskClick?: (task: GanttTask) => void;
|
|
25
34
|
onTaskUpdate?: (task: GanttTask, changes: Partial<Pick<GanttTask, 'title' | 'start' | 'end' | 'progress'>>) => void;
|
|
35
|
+
onTaskDelete?: (task: GanttTask) => void;
|
|
36
|
+
/** @deprecated no-op — see {@link GanttViewMode} */
|
|
26
37
|
onViewChange?: (view: GanttViewMode) => void;
|
|
27
|
-
onAddClick?: () => void;
|
|
28
38
|
className?: string;
|
|
29
39
|
/** Enable inline editing of task fields */
|
|
30
40
|
inlineEdit?: boolean;
|
|
31
41
|
}
|
|
32
|
-
export declare function GanttView({ tasks,
|
|
42
|
+
export declare function GanttView({ tasks, startDate, endDate, onTaskClick, onTaskUpdate, className, inlineEdit, }: GanttViewProps): import("react/jsx-runtime").JSX.Element;
|
|
33
43
|
//# sourceMappingURL=GanttView.d.ts.map
|
|
@@ -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,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,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,
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectGantt.d.ts","sourceRoot":"","sources":["../../../../src/ObjectGantt.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"ObjectGantt.d.ts","sourceRoot":"","sources":["../../../../src/ObjectGantt.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAyB,MAAM,kBAAkB,CAAC;AAiB5F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAClC;AAyFD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA0XlD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/plugin-gantt",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Gantt chart plugin for Object UI",
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@objectstack/spec": "^4.0.
|
|
27
|
+
"@objectstack/spec": "^4.0.5",
|
|
28
28
|
"lucide-react": "^1.14.0",
|
|
29
|
-
"@object-ui/components": "4.0.
|
|
30
|
-
"@object-ui/core": "4.0.
|
|
31
|
-
"@object-ui/fields": "4.0.
|
|
32
|
-
"@object-ui/
|
|
33
|
-
"@object-ui/
|
|
29
|
+
"@object-ui/components": "4.0.8",
|
|
30
|
+
"@object-ui/core": "4.0.8",
|
|
31
|
+
"@object-ui/fields": "4.0.8",
|
|
32
|
+
"@object-ui/plugin-detail": "4.0.8",
|
|
33
|
+
"@object-ui/react": "4.0.8",
|
|
34
|
+
"@object-ui/types": "4.0.8"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
37
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"@types/react-dom": "19.2.3",
|
|
42
43
|
"@vitejs/plugin-react": "^6.0.1",
|
|
43
44
|
"typescript": "^6.0.3",
|
|
44
|
-
"vite": "^8.0.
|
|
45
|
+
"vite": "^8.0.12",
|
|
45
46
|
"vite-plugin-dts": "^5.0.0"
|
|
46
47
|
},
|
|
47
48
|
"keywords": [
|