@object-ui/plugin-timeline 17.5.0 → 17.7.0

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/dist/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as e from "react";
2
- import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
3
- import { NavigationOverlay as a, cn as o, cva as s, renderChildren as c } from "@object-ui/components";
4
- import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
- import { ComponentRegistry as d, buildExpandFields as f, convertSortToQueryParams as p, extractRecords as m } from "@object-ui/core";
6
- import { createSafeTranslation as h, useDisplayLocale as g } from "@object-ui/i18n";
7
- import { ElementDataSourceGate as ee, useDataScope as te, useNavigationOverlay as ne, useObjectLabel as re, useSchemaContext as _ } from "@object-ui/react";
8
- import { usePullToRefresh as ie } from "@object-ui/mobile";
9
- import { z as v } from "zod";
2
+ import { useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
3
+ import { NavigationOverlay as o, cn as s, cva as c, renderChildren as l } from "@object-ui/components";
4
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
5
+ import { ComponentRegistry as f, buildExpandFields as p, convertSortToQueryParams as m, createFieldColorResolver as h, elementDataSourceBlock as g, extractRecords as _, isRealCalendarDate as v, recordDisplayValueAt as ee, toDateInputValue as y, toDisplayDate as b, toDisplayEndDate as te, toDomProps as x } from "@object-ui/core";
6
+ import { createSafeTranslation as ne, useDisplayLocale as re } from "@object-ui/i18n";
7
+ import { ElementDataSourceGate as ie, useDataInvalidation as ae, useDataScope as oe, useFilterScope as se, useNavigationOverlay as ce, useResolvedFilter as le, useSafeFieldLabel as ue, useSchemaContext as de, useSettledSchema as fe } from "@object-ui/react";
8
+ import { usePermissions as pe } from "@object-ui/permissions";
9
+ import { usePullToRefresh as me } from "@object-ui/mobile";
10
+ import { z as S } from "zod";
10
11
  //#region src/useTimelineTranslation.ts
11
- var y = {
12
+ var C = {
12
13
  "timeline.bucket.overdue": "Overdue",
13
14
  "timeline.bucket.today": "Today",
14
15
  "timeline.bucket.tomorrow": "Tomorrow",
@@ -17,15 +18,15 @@ var y = {
17
18
  "timeline.bucket.later": "Later",
18
19
  "timeline.bucket.noDate": "No date",
19
20
  "timeline.bucket.unassigned": "Unassigned",
20
- "timeline.relative.today": "Today",
21
- "timeline.relative.tomorrow": "Tomorrow",
22
- "timeline.relative.yesterday": "Yesterday",
23
- "timeline.relative.inDays": "In {{n}} days",
24
- "timeline.relative.daysAgo": "{{n}} days ago",
25
21
  "timeline.scale.week": "Week {{n}}",
26
22
  "timeline.scale.quarter": "Q{{quarter}} {{year}}",
27
- "timeline.gantt.rowLabel": "Items"
28
- }, b = "timeline.bucket.today", x = (e, t) => Object.entries(t ?? {}).reduce((e, [t, n]) => e.split(`{{${t}}}`).join(String(n)), y[e] || e), S = h(y, b), C = /* @__PURE__ */ new Set([
23
+ "timeline.gantt.rowLabel": "Items",
24
+ "timeline.gantt.unusableRange.malformedDate": "Unusable gantt date range — {{path}} is {{value}}, which is not a valid date. Every gantt date has to parse: the startDate and endDate on every row item, plus any minDate / maxDate pinned on the schema.",
25
+ "timeline.gantt.unusableRange.inverted": "Unusable gantt date range — minDate {{minDate}} is after maxDate {{maxDate}}. A pinned minDate / maxDate overrides the range computed from the rows, so this axis has no columns and no bar can be placed on it; swap the two values.",
26
+ "timeline.gantt.unusableRange.malformedRow": "Unusable gantt rows — {{path}} is {{value}}, which is not a row shape. A gantt draws items as a list of rows, every row as an object with a label and its own items, and every row's items as a list of bars; a null, a number, a string or a plain object in any of those places cannot be drawn.",
27
+ "timeline.unsupported.objectBoundGantt": "Unsupported variant \"gantt\" — an object-bound timeline renders the feed variants ({{variants}}). Gantt needs literal rows, each with its own nested items, so the gantt axis (scale) has no effect here.",
28
+ "timeline.unconfigured.noDateAxis": "Timeline date axis required — this view declares no date field, and an object-bound timeline will not invent one. Declare one of: {{fields}}. The first is the spec spelling; the rest are legacy aliases."
29
+ }, w = "timeline.bucket.today", he = (e, t) => Object.entries(t ?? {}).reduce((e, [t, n]) => e.split(`{{${t}}}`).join(String(n)), C[e] || e), ge = ne(C, w), T = /* @__PURE__ */ new Set([
29
30
  "hour",
30
31
  "day",
31
32
  "week",
@@ -33,84 +34,224 @@ var y = {
33
34
  "quarter",
34
35
  "year"
35
36
  ]);
36
- function w(e) {
37
- let t = e.scale ?? e.timeScale;
38
- return typeof t == "string" && C.has(t) ? t : "month";
37
+ function E(e) {
38
+ let t = e.scale;
39
+ return typeof t == "string" && T.has(t) ? t : "month";
40
+ }
41
+ function D(e) {
42
+ return typeof e == "string" ? b(e) : new Date(e);
39
43
  }
40
- function T(e, t, n, r = "en", i = x) {
41
- let a = [], o = new Date(t), s = new Date(n);
42
- if (Number.isNaN(o.getTime()) || Number.isNaN(s.getTime()) || o > s) return a;
43
- let c = new Date(o);
44
+ function O(e) {
45
+ let t = new Date(e);
46
+ return t.setHours(0, 0, 0, 0), t;
47
+ }
48
+ var _e = 36e5, ve = {
49
+ floor: (e) => {
50
+ let t = new Date(e);
51
+ return t.setMinutes(0, 0, 0), t;
52
+ },
53
+ step: (e) => {
54
+ e.setTime(e.getTime() + _e);
55
+ },
56
+ label: (e, t, n) => e.toLocaleString(n, {
57
+ month: "short",
58
+ day: "numeric",
59
+ hour: "numeric"
60
+ })
61
+ }, k = {
62
+ floor: O,
63
+ step: (e) => {
64
+ e.setDate(e.getDate() + 1);
65
+ },
66
+ label: (e, t, n) => e.toLocaleDateString(n, {
67
+ month: "short",
68
+ day: "numeric"
69
+ })
70
+ }, ye = {
71
+ floor: O,
72
+ step: (e) => {
73
+ e.setDate(e.getDate() + 7);
74
+ },
75
+ label: (e, t, n, r) => r("timeline.scale.week", { n: t + 1 })
76
+ }, A = {
77
+ floor: (e) => {
78
+ let t = O(e);
79
+ return t.setDate(1), t;
80
+ },
81
+ step: (e) => {
82
+ e.setMonth(e.getMonth() + 1);
83
+ },
84
+ label: (e, t, n) => e.toLocaleDateString(n, {
85
+ month: "short",
86
+ year: "numeric"
87
+ })
88
+ }, j = {
89
+ floor: (e) => {
90
+ let t = O(e);
91
+ return t.setMonth(Math.floor(t.getMonth() / 3) * 3, 1), t;
92
+ },
93
+ step: (e) => {
94
+ e.setMonth(e.getMonth() + 3);
95
+ },
96
+ label: (e, t, n, r) => r("timeline.scale.quarter", {
97
+ quarter: Math.floor(e.getMonth() / 3) + 1,
98
+ year: e.getFullYear()
99
+ })
100
+ }, be = {
101
+ floor: (e) => {
102
+ let t = O(e);
103
+ return t.setMonth(0, 1), t;
104
+ },
105
+ step: (e) => {
106
+ e.setFullYear(e.getFullYear() + 1);
107
+ },
108
+ label: (e) => String(e.getFullYear())
109
+ };
110
+ function xe(e) {
44
111
  switch (e) {
45
- case "hour":
46
- for (; c <= s;) a.push(c.toLocaleString(r, {
47
- month: "short",
48
- day: "numeric",
49
- hour: "numeric"
50
- })), c.setHours(c.getHours() + 1);
51
- break;
52
- case "day":
53
- for (; c <= s;) a.push(c.toLocaleDateString(r, {
54
- month: "short",
55
- day: "numeric"
56
- })), c.setDate(c.getDate() + 1);
57
- break;
58
- case "week": {
59
- let e = 1;
60
- for (; c <= s;) a.push(i("timeline.scale.week", { n: e++ })), c.setDate(c.getDate() + 7);
61
- break;
62
- }
63
- case "quarter":
64
- for (c.setMonth(Math.floor(c.getMonth() / 3) * 3, 1); c <= s;) a.push(i("timeline.scale.quarter", {
65
- quarter: Math.floor(c.getMonth() / 3) + 1,
66
- year: c.getFullYear()
67
- })), c.setMonth(c.getMonth() + 3);
68
- break;
69
- case "year":
70
- for (c.setMonth(0, 1); c <= s;) a.push(String(c.getFullYear())), c.setFullYear(c.getFullYear() + 1);
71
- break;
72
- default: for (; c <= s;) a.push(c.toLocaleDateString(r, {
73
- month: "short",
74
- year: "numeric"
75
- })), c.setMonth(c.getMonth() + 1);
112
+ case "hour": return ve;
113
+ case "day": return k;
114
+ case "week": return ye;
115
+ case "quarter": return j;
116
+ case "year": return be;
117
+ default: return A;
76
118
  }
77
- return a;
78
119
  }
79
- function E(e) {
80
- let t = e.flatMap((e) => (e.items || []).flatMap((e) => [e.startDate, e.endDate])), n = Math.min(...t.map((e) => new Date(e).getTime())), r = Math.max(...t.map((e) => new Date(e).getTime()));
120
+ function M(e) {
121
+ return typeof e == "string" ? te(e) : D(e);
122
+ }
123
+ function N(e, t, n, r, i, a) {
124
+ let o = D(t).getTime(), s = D(n).getTime();
125
+ if (Number.isNaN(o) || Number.isNaN(s) || o > s) return;
126
+ let c = a === void 0 ? s : Math.max(s, a), l = xe(e), u = [], d = l.floor(new Date(o));
127
+ for (; d.getTime() <= c;) {
128
+ let e = d.getTime(), t = l.label(new Date(e), u.length, r, i);
129
+ l.step(d), u.push({
130
+ start: e,
131
+ end: d.getTime(),
132
+ label: t
133
+ });
134
+ }
135
+ return {
136
+ start: u[0].start,
137
+ end: u[u.length - 1].end,
138
+ units: u
139
+ };
140
+ }
141
+ function P(e, t, n) {
142
+ let r = e.end - e.start;
143
+ return {
144
+ start: (t - e.start) / r * 100,
145
+ width: (n - t) / r * 100
146
+ };
147
+ }
148
+ function Se(e, t, n, r = "en", i = he) {
149
+ let a = N(e, t, n, r, i);
150
+ return a ? a.units.map((e) => e.label) : [];
151
+ }
152
+ function F() {
153
+ let e = y(/* @__PURE__ */ new Date());
154
+ return {
155
+ minDate: e,
156
+ maxDate: e
157
+ };
158
+ }
159
+ function I(e) {
160
+ if (!Array.isArray(e)) return {
161
+ ok: !1,
162
+ path: "items",
163
+ value: e
164
+ };
165
+ let t = [];
166
+ for (let n = 0; n < e.length; n++) {
167
+ let r = e[n];
168
+ if (typeof r != "object" || !r || Array.isArray(r)) return {
169
+ ok: !1,
170
+ path: `items[${n}]`,
171
+ value: r
172
+ };
173
+ let i = r.items;
174
+ if (i && !Array.isArray(i)) return {
175
+ ok: !1,
176
+ path: `items[${n}].items`,
177
+ value: i
178
+ };
179
+ t.push({
180
+ authored: r,
181
+ label: r.label,
182
+ items: i || []
183
+ });
184
+ }
81
185
  return {
82
- minDate: new Date(n).toISOString().split("T")[0],
83
- maxDate: new Date(r).toISOString().split("T")[0]
186
+ ok: !0,
187
+ rows: t
84
188
  };
85
189
  }
86
- function ae(e, t, n, r) {
87
- let i = new Date(e).getTime(), a = new Date(t).getTime(), o = new Date(n).getTime(), s = new Date(r).getTime() - o, c = i - o, l = a - i;
190
+ function L(e) {
191
+ let t = e.flatMap((e) => e.items.flatMap((e) => [e.startDate, e.endDate]));
192
+ if (t.length === 0) return F();
193
+ let n = Math.min(...t.map((e) => D(e).getTime())), r = Math.max(...t.map((e) => D(e).getTime())), i = Math.max(...e.flatMap((e) => e.items.map((e) => {
194
+ let t = D(e.startDate).getTime(), n = M(e.endDate).getTime();
195
+ return n > t ? n - 1 : t;
196
+ })));
88
197
  return {
89
- start: c / s * 100,
90
- width: l / s * 100
198
+ minDate: y(new Date(n)),
199
+ maxDate: y(new Date(r)),
200
+ through: i
201
+ };
202
+ }
203
+ var R = (e) => {
204
+ try {
205
+ return Date.prototype.getTime.call(e), !0;
206
+ } catch {
207
+ return !1;
208
+ }
209
+ };
210
+ function z(e) {
211
+ return typeof e == "string" ? JSON.stringify(e) : e === void 0 ? "undefined" : e === null ? "null" : typeof e == "symbol" ? e.toString() : typeof e == "bigint" ? `${e}n` : typeof e == "number" || typeof e == "boolean" ? String(e) : R(e) ? Date.prototype.toString.call(e) : Array.isArray(e) ? "an array" : typeof e == "function" ? "a function" : "an object";
212
+ }
213
+ var Ce = (e) => typeof e == "string" || typeof e == "number" && Number.isFinite(e) || R(e);
214
+ function B(e, t, n) {
215
+ let r = (e) => !Ce(e) || Number.isNaN(D(e).getTime());
216
+ for (let t = 0; t < e.length; t++) {
217
+ let n = e[t].items;
218
+ for (let e = 0; e < n.length; e++) for (let i of ["startDate", "endDate"]) {
219
+ let a = n[e]?.[i];
220
+ if (r(a)) return {
221
+ path: `items[${t}].items[${e}].${i}`,
222
+ value: a
223
+ };
224
+ }
225
+ }
226
+ for (let [e, i] of [["minDate", t], ["maxDate", n]]) if (i && r(i)) return {
227
+ path: e,
228
+ value: i
91
229
  };
92
230
  }
93
- function D(e, t, n) {
94
- let r = new Date(e);
231
+ function V(e, t, n) {
232
+ return P(n, D(e).getTime(), M(t).getTime());
233
+ }
234
+ function H(e, t, n) {
235
+ let r = b(e);
95
236
  return t === "short" ? r.toLocaleDateString(n) : t === "long" ? r.toLocaleDateString(n, {
96
237
  year: "numeric",
97
238
  month: "long",
98
239
  day: "numeric"
99
- }) : r.toISOString().split("T")[0];
240
+ }) : Number.isNaN(r.getTime()) ? String(e) : v(e) ? y(r) : r.toISOString().split("T")[0];
100
241
  }
101
- function O({ label: e, color: t }) {
242
+ function U({ label: e, color: t }) {
102
243
  let n = t ? {
103
244
  backgroundColor: `${t}22`,
104
245
  color: t,
105
246
  borderColor: `${t}55`
106
247
  } : void 0;
107
- return /* @__PURE__ */ l("span", {
108
- className: o("inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium", !t && "bg-muted text-muted-foreground border-transparent"),
248
+ return /* @__PURE__ */ u("span", {
249
+ className: s("inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium", !t && "bg-muted text-muted-foreground border-transparent"),
109
250
  style: n,
110
251
  children: e
111
252
  });
112
253
  }
113
- function k(e) {
254
+ function we(e) {
114
255
  let t = [];
115
256
  for (let n of e) {
116
257
  let e = n.group == null ? "" : String(n.group), r = t[t.length - 1];
@@ -121,154 +262,188 @@ function k(e) {
121
262
  }
122
263
  return t;
123
264
  }
124
- var A = ({ schema: e, className: t, ...n }) => {
125
- let { variant: r = "vertical", items: i = [], dateFormat: a = "short", onItemClick: s } = e, d = g(), { t: f } = S();
126
- if (r === "vertical") {
127
- let e = k(i), r = e.some((e) => e.key !== ""), f = (e, t) => {
265
+ var W = ({ schema: e, className: t, style: n, ...r }) => {
266
+ let { variant: i = "vertical", items: a = [], dateFormat: o = "short", onItemClick: c } = e, f = re(), { t: p } = ge();
267
+ if (i === "vertical") {
268
+ let e = we(a), i = e.some((e) => e.key !== ""), p = (e, t) => {
128
269
  let n = e.color ? {
129
270
  backgroundColor: `${e.color}33`,
130
271
  borderColor: e.color
131
- } : void 0, r = e.time ? D(e.time, a, d) : e.startDate ? D(e.startDate, a, d) : "", i = e.endDate && e.endDate !== e.startDate ? D(e.endDate, a, d) : "", f = Array.isArray(e.meta) ? e.meta : [];
132
- return /* @__PURE__ */ u(I, {
272
+ } : void 0, r = e.time ? H(e.time, o, f) : e.startDate ? H(e.startDate, o, f) : "", i = e.endDate && e.endDate !== e.startDate ? H(e.endDate, o, f) : "", a = Array.isArray(e.meta) ? e.meta : [];
273
+ return /* @__PURE__ */ d(Pe, {
133
274
  density: "compact",
134
- className: o(e.className, s && "cursor-pointer"),
135
- onClick: () => s?.(e),
136
- children: [/* @__PURE__ */ l(R, {
275
+ className: s(e.className, c && "cursor-pointer"),
276
+ onClick: () => c?.(e),
277
+ children: [/* @__PURE__ */ u(K, {
137
278
  variant: e.color ? "default" : e.variant || "default",
138
279
  style: n,
139
- children: e.icon && /* @__PURE__ */ l("span", {
280
+ children: e.icon && /* @__PURE__ */ u("span", {
140
281
  className: "text-xs",
141
282
  children: e.icon
142
283
  })
143
- }), /* @__PURE__ */ u(z, { children: [
144
- (r || i) && /* @__PURE__ */ u(V, {
284
+ }), /* @__PURE__ */ d(Ie, { children: [
285
+ (r || i) && /* @__PURE__ */ d(J, {
145
286
  dateTime: e.time || e.startDate,
146
287
  className: "!mb-1 text-xs",
147
- children: [r, i && /* @__PURE__ */ u("span", {
288
+ children: [r, i && /* @__PURE__ */ d("span", {
148
289
  className: "text-muted-foreground/70",
149
290
  children: [" → ", i]
150
291
  })]
151
292
  }),
152
- e.title && /* @__PURE__ */ l(B, {
293
+ e.title && /* @__PURE__ */ u(q, {
153
294
  className: "text-sm sm:text-base mb-1",
154
295
  children: e.title
155
296
  }),
156
- f.length > 0 && /* @__PURE__ */ l("div", {
297
+ a.length > 0 && /* @__PURE__ */ u("div", {
157
298
  className: "flex flex-wrap gap-1.5 mt-1 mb-1",
158
- children: f.map((e) => /* @__PURE__ */ l(O, {
299
+ children: a.map((e) => /* @__PURE__ */ u(U, {
159
300
  label: e.label,
160
301
  color: e.color
161
302
  }, e.key))
162
303
  }),
163
- e.description && /* @__PURE__ */ l(H, {
304
+ e.description && /* @__PURE__ */ u(Y, {
164
305
  className: "text-sm text-muted-foreground line-clamp-2 sm:line-clamp-none",
165
306
  children: e.description
166
307
  }),
167
- e.content && c(e.content)
308
+ l(e.content)
168
309
  ] })]
169
310
  }, t);
170
311
  };
171
- return r ? /* @__PURE__ */ l("div", {
172
- className: o("px-4 sm:px-6 py-2", t),
173
- ...n,
174
- children: e.map((e, t) => /* @__PURE__ */ u("section", {
312
+ return i ? /* @__PURE__ */ u("div", {
313
+ ...x(r),
314
+ className: s("px-4 sm:px-6 py-2", t),
315
+ style: n,
316
+ children: e.map((e, t) => /* @__PURE__ */ d("section", {
175
317
  className: "mb-4",
176
- children: [/* @__PURE__ */ u("header", {
318
+ children: [/* @__PURE__ */ d("header", {
177
319
  className: "sticky top-0 z-10 -mx-4 sm:-mx-6 px-4 sm:px-6 py-1.5 backdrop-blur bg-background/90 text-xs font-semibold uppercase tracking-wide text-muted-foreground border-b",
178
- children: [/* @__PURE__ */ l("span", { children: e.key }), /* @__PURE__ */ l("span", {
320
+ children: [/* @__PURE__ */ u("span", { children: e.key }), /* @__PURE__ */ u("span", {
179
321
  className: "ml-2 text-muted-foreground/60 font-normal normal-case",
180
322
  children: e.items.length
181
323
  })]
182
- }), /* @__PURE__ */ l(P, {
324
+ }), /* @__PURE__ */ u(G, {
183
325
  className: "mt-3",
184
- children: e.items.map((e, n) => f(e, `${t}-${n}`))
326
+ children: e.items.map((e, n) => p(e, `${t}-${n}`))
185
327
  })]
186
328
  }, `${e.key}-${t}`))
187
- }) : /* @__PURE__ */ l(P, {
329
+ }) : /* @__PURE__ */ u(G, {
330
+ ...x(r),
188
331
  className: t,
189
- ...n,
190
- children: i.map((e, t) => f(e, t))
332
+ style: n,
333
+ children: a.map((e, t) => p(e, t))
191
334
  });
192
335
  }
193
- if (r === "horizontal") return /* @__PURE__ */ l(U, {
194
- className: o("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
195
- ...n,
196
- children: i.map((e, t) => /* @__PURE__ */ u(W, {
197
- className: o(e.className, s && "cursor-pointer"),
198
- onClick: () => s?.(e),
199
- children: [/* @__PURE__ */ u("div", {
336
+ if (i === "horizontal") return /* @__PURE__ */ u(Le, {
337
+ ...x(r),
338
+ className: s("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
339
+ style: n,
340
+ children: a.map((e, t) => /* @__PURE__ */ d(Re, {
341
+ className: s(e.className, c && "cursor-pointer"),
342
+ onClick: () => c?.(e),
343
+ children: [/* @__PURE__ */ d("div", {
200
344
  className: "flex flex-col items-center",
201
- children: [/* @__PURE__ */ l(R, {
345
+ children: [/* @__PURE__ */ u(K, {
202
346
  variant: e.variant || "default",
203
- children: e.icon && /* @__PURE__ */ l("span", {
347
+ children: e.icon && /* @__PURE__ */ u("span", {
204
348
  className: "text-xs",
205
349
  children: e.icon
206
350
  })
207
- }), /* @__PURE__ */ u("div", {
351
+ }), /* @__PURE__ */ d("div", {
208
352
  className: "mt-4 text-center",
209
353
  children: [
210
- e.time && /* @__PURE__ */ l(V, {
354
+ e.time && /* @__PURE__ */ u(J, {
211
355
  dateTime: e.time,
212
- children: D(e.time, a, d)
356
+ children: H(e.time, o, f)
213
357
  }),
214
- e.title && /* @__PURE__ */ l(B, { children: e.title }),
215
- e.description && /* @__PURE__ */ l(H, {
358
+ e.title && /* @__PURE__ */ u(q, { children: e.title }),
359
+ e.description && /* @__PURE__ */ u(Y, {
216
360
  className: "text-center line-clamp-2 sm:line-clamp-none",
217
361
  children: e.description
218
362
  }),
219
- e.content && c(e.content)
363
+ l(e.content)
220
364
  ]
221
365
  })]
222
- }), t < i.length - 1 && /* @__PURE__ */ l("div", { className: "absolute left-full w-16 border-t-2 border-gray-200 top-3" })]
366
+ }), t < a.length - 1 && /* @__PURE__ */ u("div", { className: "absolute left-full w-16 border-t-2 border-gray-200 top-3" })]
223
367
  }, t))
224
368
  });
225
- if (r === "gantt") {
226
- let r = E(i), c = e.minDate || r.minDate, p = e.maxDate || r.maxDate, m = T(w(e), c, p, d, f);
227
- return /* @__PURE__ */ u(G, {
228
- className: o("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
229
- ...n,
230
- children: [/* @__PURE__ */ u(K, { children: [/* @__PURE__ */ l(q, {
369
+ if (i === "gantt") {
370
+ let i = I(a);
371
+ if (!i.ok) return /* @__PURE__ */ u("div", {
372
+ className: "p-4 text-destructive",
373
+ "data-testid": "timeline-unusable-date-range",
374
+ role: "alert",
375
+ children: p("timeline.gantt.unusableRange.malformedRow", {
376
+ path: i.path,
377
+ value: z(i.value)
378
+ })
379
+ });
380
+ let l = i.rows, m = B(l, e.minDate, e.maxDate);
381
+ if (m) return /* @__PURE__ */ u("div", {
382
+ className: "p-4 text-destructive",
383
+ "data-testid": "timeline-unusable-date-range",
384
+ role: "alert",
385
+ children: p("timeline.gantt.unusableRange.malformedDate", {
386
+ path: m.path,
387
+ value: z(m.value)
388
+ })
389
+ });
390
+ let h = L(l), g = e.minDate || h.minDate, _ = e.maxDate || h.maxDate, v = N(E(e), g, _, f, p, e.maxDate ? void 0 : h.through);
391
+ return v ? /* @__PURE__ */ d(ze, {
392
+ ...x(r),
393
+ className: s("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
394
+ style: n,
395
+ children: [/* @__PURE__ */ d(Be, { children: [/* @__PURE__ */ u(X, {
231
396
  className: "flex items-center px-2 sm:px-4 py-2 sm:py-3",
232
- children: /* @__PURE__ */ l("span", {
397
+ children: /* @__PURE__ */ u("span", {
233
398
  className: "font-semibold text-xs sm:text-sm",
234
- children: e.rowLabel || f("timeline.gantt.rowLabel")
399
+ children: e.rowLabel || p("timeline.gantt.rowLabel")
235
400
  })
236
- }), /* @__PURE__ */ l(J, { children: /* @__PURE__ */ l("div", {
401
+ }), /* @__PURE__ */ u(Z, { children: /* @__PURE__ */ u("div", {
237
402
  className: "flex h-full",
238
- children: m.map((e, t) => /* @__PURE__ */ l("div", {
239
- className: "flex-1 px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center",
240
- children: e
403
+ children: v.units.map((e, t) => /* @__PURE__ */ u("div", {
404
+ className: "shrink-0 min-w-0 overflow-hidden px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center",
405
+ style: { width: `${P(v, e.start, e.end).width}%` },
406
+ children: e.label
241
407
  }, t))
242
- }) })] }), /* @__PURE__ */ l("div", { children: /* @__PURE__ */ u("div", {
408
+ }) })] }), /* @__PURE__ */ u("div", { children: /* @__PURE__ */ d("div", {
243
409
  className: "flex",
244
- children: [/* @__PURE__ */ l(q, { children: i.map((e, t) => /* @__PURE__ */ l(Y, { children: /* @__PURE__ */ l(X, {
410
+ children: [/* @__PURE__ */ u(X, { children: l.map((e, t) => /* @__PURE__ */ u(Q, { children: /* @__PURE__ */ u(Ve, {
245
411
  title: e.label,
246
412
  className: "truncate",
247
413
  children: e.label
248
- }) }, t)) }), /* @__PURE__ */ l(J, {
414
+ }) }, t)) }), /* @__PURE__ */ u(Z, {
249
415
  className: "relative",
250
- children: i.map((e, t) => /* @__PURE__ */ l(Y, {
416
+ children: l.map((e, t) => /* @__PURE__ */ u(Q, {
251
417
  className: "relative",
252
- children: (e.items || []).map((n, r) => {
253
- let i = ae(n.startDate, n.endDate, c, p);
254
- return /* @__PURE__ */ l(Z, {
418
+ children: e.items.map((n, r) => {
419
+ let i = V(n.startDate, n.endDate, v);
420
+ return /* @__PURE__ */ u(He, {
255
421
  start: i.start,
256
422
  width: i.width,
257
423
  variant: n.variant || "default",
258
- onClick: () => s?.(n, e, t, r),
259
- title: `${n.title || ""}\n${D(n.startDate, a, d)} - ${D(n.endDate, a, d)}`,
260
- children: /* @__PURE__ */ l(Q, { children: n.title })
424
+ onClick: () => c?.(n, e.authored, t, r),
425
+ title: `${n.title || ""}\n${H(n.startDate, o, f)} - ${H(n.endDate, o, f)}`,
426
+ children: /* @__PURE__ */ u(Ue, { children: n.title })
261
427
  }, r);
262
428
  })
263
429
  }, t))
264
430
  })]
265
431
  }) })]
432
+ }) : /* @__PURE__ */ u("div", {
433
+ className: "p-4 text-destructive",
434
+ "data-testid": "timeline-unusable-date-range",
435
+ role: "alert",
436
+ children: p("timeline.gantt.unusableRange.inverted", {
437
+ minDate: z(g),
438
+ maxDate: z(_)
439
+ })
266
440
  });
267
441
  }
268
442
  return null;
269
443
  };
270
- d.register("timeline", A, {
444
+ f.register("timeline", W, {
271
445
  namespace: "plugin-timeline",
446
+ skipFallback: !0,
272
447
  label: "Timeline",
273
448
  category: "data-display",
274
449
  inputs: [
@@ -279,14 +454,11 @@ d.register("timeline", A, {
279
454
  "vertical",
280
455
  "horizontal",
281
456
  "gantt"
282
- ],
283
- label: "Timeline Variant",
284
- defaultValue: "vertical"
457
+ ]
285
458
  },
286
459
  {
287
460
  name: "items",
288
461
  type: "array",
289
- label: "Timeline Items",
290
462
  description: "For vertical/horizontal: Array of { time, title, description, variant, icon, content }. For gantt: Array of { label, items: [{ title, startDate, endDate, variant }] }"
291
463
  },
292
464
  {
@@ -296,43 +468,30 @@ d.register("timeline", A, {
296
468
  "short",
297
469
  "long",
298
470
  "iso"
299
- ],
300
- label: "Date Format",
301
- defaultValue: "short"
471
+ ]
302
472
  },
303
473
  {
304
- name: "timeScale",
474
+ name: "scale",
305
475
  type: "enum",
306
- enum: [
307
- "day",
308
- "week",
309
- "month"
310
- ],
311
- label: "Time Scale (Gantt only)",
312
- defaultValue: "month"
476
+ enum: [...T]
313
477
  },
314
478
  {
315
479
  name: "rowLabel",
316
- type: "string",
317
- label: "Row Label (Gantt only)",
318
- defaultValue: "Items"
480
+ type: "string"
319
481
  },
320
482
  {
321
483
  name: "minDate",
322
484
  type: "string",
323
- label: "Min Date (Gantt only)",
324
485
  description: "Override auto-calculated min date (YYYY-MM-DD)"
325
486
  },
326
487
  {
327
488
  name: "maxDate",
328
489
  type: "string",
329
- label: "Max Date (Gantt only)",
330
490
  description: "Override auto-calculated max date (YYYY-MM-DD)"
331
491
  },
332
492
  {
333
493
  name: "className",
334
- type: "string",
335
- label: "CSS Class"
494
+ type: "string"
336
495
  }
337
496
  ],
338
497
  defaultProps: {
@@ -418,7 +577,7 @@ d.register("timeline", A, {
418
577
  gantt: {
419
578
  variant: "gantt",
420
579
  dateFormat: "short",
421
- timeScale: "month",
580
+ scale: "month",
422
581
  rowLabel: "Projects",
423
582
  items: [
424
583
  {
@@ -462,32 +621,37 @@ d.register("timeline", A, {
462
621
  }
463
622
  }
464
623
  });
465
- //#endregion
466
- //#region src/ObjectTimeline.tsx
467
- var j = {
468
- fieldOptionLabel: (e, t, n, r) => r,
469
- translateOptions: (e, t, n) => n,
470
- fieldLabel: (e, t, n) => n
471
- };
472
- function oe() {
473
- return re() ?? j;
624
+ function Te(e) {
625
+ return typeof e == "number" && Number.isInteger(e) && e > 0;
626
+ }
627
+ function Ee(e, t) {
628
+ return Te(e) ? e : t;
474
629
  }
475
- var M = v.object({
476
- title: v.string().optional(),
477
- date: v.string().optional(),
478
- description: v.string().optional(),
479
- variant: v.string().optional()
480
- }), se = v.object({
481
- mapping: M.optional(),
482
- objectName: v.string().optional(),
483
- titleField: v.string().optional(),
484
- dateField: v.string().optional(),
485
- startDateField: v.string().optional(),
486
- endDateField: v.string().optional(),
487
- descriptionField: v.string().optional(),
488
- groupByField: v.string().optional(),
489
- colorField: v.string().optional(),
490
- scale: v.enum([
630
+ function De(e, t) {
631
+ return e == null || Te(e) ? null : `[ObjectUI] ObjectTimeline row cap: ${typeof t == "string" && t ? `object-timeline on ${t}` : "object-timeline"} declared limit: ${String(e)}, which is not a positive integer. A row cap must be a positive integer (the spec refuses zero and negative values), so it was ignored and this timeline fell back to its default row cap (100).`;
632
+ }
633
+ var Oe = ["vertical", "horizontal"], ke = [
634
+ "timeline.startDateField",
635
+ "timeline.dateField",
636
+ "mapping.date",
637
+ "startDateField",
638
+ "dateField"
639
+ ], Ae = S.object({
640
+ title: S.string().optional(),
641
+ date: S.string().optional(),
642
+ description: S.string().optional(),
643
+ variant: S.string().optional()
644
+ }), je = S.object({
645
+ mapping: Ae.optional(),
646
+ objectName: S.string().optional(),
647
+ titleField: S.string().optional(),
648
+ dateField: S.string().optional(),
649
+ startDateField: S.string().optional(),
650
+ endDateField: S.string().optional(),
651
+ descriptionField: S.string().optional(),
652
+ groupByField: S.string().optional(),
653
+ colorField: S.string().optional(),
654
+ scale: S.enum([
491
655
  "hour",
492
656
  "day",
493
657
  "week",
@@ -495,174 +659,181 @@ var M = v.object({
495
659
  "quarter",
496
660
  "year"
497
661
  ]).optional()
498
- }), N = ({ schema: e, dataSource: o, className: s, onRowClick: c, onItemClick: d, ...h }) => {
499
- let [g, ee] = i([]), [re, _] = i(() => {
500
- let t = Array.isArray(e.items) && e.items.length > 0, n = Array.isArray(h.data) && h.data.length > 0;
662
+ }), Me = ({ schema: e, dataSource: s, className: c, onRowClick: l, onItemClick: f, ...g }) => {
663
+ let [v, y] = a([]), [te, x] = a(() => {
664
+ let t = Array.isArray(e.items) && e.items.length > 0, n = Array.isArray(g.data) && g.data.length > 0;
501
665
  return !t && !n && !!e.objectName;
502
- }), [v, y] = i(null), [b, x] = i(0), [C, w] = i(null), T = e.timeline;
666
+ }), [ne, re] = a(null), ie = i(0), [de, S] = a(0), C = e.timeline;
503
667
  n(() => {
504
- let t = se.safeParse(e);
668
+ let t = je.safeParse(e);
505
669
  t.success || console.warn("[ObjectTimeline] Invalid timeline configuration:", t.error.format());
506
- }, [e]);
507
- let E = te(e.bind);
508
- n(() => {
509
- let t = !0;
510
- return (async () => {
511
- if (!(!o || typeof o.getObjectSchema != "function" || !e.objectName)) try {
512
- let n = await o.getObjectSchema(e.objectName);
513
- t && w(n);
514
- } catch (e) {
515
- console.warn("Failed to fetch object def for ObjectTimeline", e);
516
- }
517
- })(), () => {
518
- t = !1;
519
- };
520
- }, [e.objectName, o]);
521
- let ae = JSON.stringify(e.filter ?? null), D = JSON.stringify(e.sort ?? null);
670
+ }, [e]), n(() => {
671
+ let t = De(e.limit, e.objectName);
672
+ t && console.warn(t);
673
+ }, [e.limit, e.objectName]);
674
+ let w = oe(e.bind), { ready: he, def: T } = fe(e.objectName ?? "", s), E = pe(), D = se(), O = le(e.filter, D), _e = JSON.stringify(O ?? null), ve = JSON.stringify(e.sort ?? null), k = !!e.objectName && !w && !e.items && !g.data, ye = ae(k ? e.objectName : void 0);
522
675
  n(() => {
523
- e.objectName && !E && !e.items && !h.data ? (async () => {
524
- if (!o || typeof o.find != "function" || !e.objectName) {
525
- _(!1);
676
+ let t = ++ie.current, n = () => ie.current === t, r = async () => {
677
+ if (!s || typeof s.find != "function" || !e.objectName) {
678
+ x(!1);
526
679
  return;
527
680
  }
528
- _(!0);
681
+ x(!0);
529
682
  try {
530
- let t = f(C?.fields), n = await o.find(e.objectName, {
531
- $filter: e.filter,
532
- $orderby: p(e.sort),
533
- $top: e.limit ?? 100,
534
- ...t.length > 0 ? { $expand: t } : {}
535
- }), r = m(n);
536
- ee(r);
683
+ let t = p(T?.fields), r = E?.isLoaded ? t.filter((t) => E.checkField(e.objectName, t, "read")) : t, i = await s.find(e.objectName, {
684
+ $filter: O,
685
+ $orderby: m(e.sort),
686
+ $top: Ee(e.limit, 100),
687
+ ...r.length > 0 ? { $expand: r } : {}
688
+ }), a = _(i);
689
+ n() && (y(a), re(null));
537
690
  } catch (e) {
538
- console.error(e), y(e);
691
+ console.error(e), n() && re(e);
539
692
  } finally {
540
- _(!1);
693
+ n() && x(!1);
541
694
  }
542
- })() : _(!1);
695
+ };
696
+ if (k) {
697
+ if (!he) return;
698
+ r();
699
+ } else x(!1);
543
700
  }, [
544
701
  e.objectName,
545
- o,
546
- E,
702
+ s,
703
+ w,
547
704
  e.items,
548
- h.data,
549
- b,
550
- C,
551
- ae,
552
- D,
553
- e.limit
705
+ g.data,
706
+ de,
707
+ he,
708
+ T,
709
+ _e,
710
+ ve,
711
+ e.limit,
712
+ E,
713
+ ye
554
714
  ]);
555
- let O = h.data || E || g, { t: k } = S(), { fieldOptionLabel: j } = oe(), M = T?.titleField ?? e.mapping?.title ?? e.titleField ?? "name", N = T?.startDateField ?? T?.dateField ?? e.mapping?.date ?? e.startDateField ?? e.dateField ?? "date", P = T?.endDateField ?? e.endDateField ?? N, F = e.mapping?.description ?? e.descriptionField ?? "description", I = e.mapping?.variant ?? "variant", L = T?.groupByField ?? e.groupByField, R = T?.colorField ?? e.colorField, z = r(() => {
715
+ let A = g.data || w || v, { t: j } = ge(), { fieldOptionLabel: be } = ue(), xe = C?.titleField ?? e.mapping?.title ?? e.titleField ?? "name", M = C?.startDateField ?? C?.dateField ?? e.mapping?.date ?? e.startDateField ?? e.dateField, N = C?.endDateField ?? e.endDateField ?? M, P = e.mapping?.description ?? e.descriptionField ?? "description", Se = e.mapping?.variant ?? "variant", F = C?.groupByField ?? e.groupByField, I = C?.colorField ?? e.colorField, L = r(() => {
556
716
  if (e.items) return e.items;
557
- if (!O || !Array.isArray(O)) return [];
558
- let t = C?.fields ?? {}, n = e.objectName || "", r = (e) => {
559
- if (!e || !t[e]?.options) return {};
560
- let n = {};
561
- for (let r of t[e].options) r && r.value != null && (n[String(r.value)] = r);
562
- return n;
563
- }, i = r(R), a = Array.isArray(T?.metaFields) ? T.metaFields.filter((e) => typeof e == "string" && e) : ["status", "priority"].filter((e) => t[e]), o = {};
564
- for (let e of a) o[e] = r(e);
565
- let s = (e) => {
566
- if (e == null || e === "") return;
567
- let t = i[String(e)];
568
- if (t?.color) return String(t.color);
569
- let n = String(e);
570
- if (/^#([0-9a-f]{3}){1,2}$/i.test(n) || n.startsWith("rgb") || n.startsWith("hsl")) return n;
571
- }, c = (e, t, r) => {
717
+ if (!A || !Array.isArray(A) || !M) return [];
718
+ let t = M, n = N ?? M, r = T?.fields ?? {}, i = e.objectName || "", a = (e) => {
719
+ if (!e || !r[e]?.options) return {};
720
+ let t = {};
721
+ for (let n of r[e].options) n && n.value != null && (t[String(n.value)] = n);
722
+ return t;
723
+ }, o = ["status", "priority"].filter((e) => r[e]), s = {};
724
+ for (let e of o) s[e] = a(e);
725
+ let c = h(r[I ?? ""]), l = (e, t, n) => {
572
726
  if (t == null || t === "") return null;
573
- let i = r[String(t)];
727
+ let r = n[String(t)];
574
728
  return {
575
- label: i?.label ? j(n, e, String(t), i.label) : String(t),
576
- color: i?.color
729
+ label: r?.label ? be(i, e, String(t), r.label) : String(t),
730
+ color: r?.color
577
731
  };
578
- }, l = O.map((e) => {
579
- let t = e[N], r = e[P], i = R ? e[R] : void 0, l = L ? e[L] : void 0, u = [];
580
- if (n) for (let t of a) {
581
- let n = c(t, e[t], o[t] || {});
582
- n && u.push({
732
+ }, u = A.map((e) => {
733
+ let r = e[t], a = e[n], u = I ? e[I] : void 0, d = F ? e[F] : void 0, f = [];
734
+ if (i) for (let t of o) {
735
+ let n = l(t, e[t], s[t] || {});
736
+ n && f.push({
583
737
  key: t,
584
738
  label: n.label,
585
739
  color: n.color
586
740
  });
587
741
  }
588
742
  return {
589
- title: e[M],
590
- time: t,
591
- startDate: t,
592
- endDate: r,
593
- description: e[F],
594
- variant: e[I] || "default",
595
- color: s(i),
596
- group: l,
597
- meta: u,
743
+ title: ee(e, xe),
744
+ time: r,
745
+ startDate: r,
746
+ endDate: a,
747
+ description: ee(e, P),
748
+ variant: e[Se] || "default",
749
+ color: c(u),
750
+ group: d,
751
+ meta: f,
598
752
  _data: e
599
753
  };
600
- });
601
- l.sort((e, t) => (e.startDate ? new Date(e.startDate).getTime() : Infinity) - (t.startDate ? new Date(t.startDate).getTime() : Infinity));
602
- let u = /* @__PURE__ */ new Date(), d = (e) => new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime(), f = d(u), p = 864e5, m = f - (u.getDay() + 6) % 7 * p + 7 * p, h = m + 7 * p, g = (e) => {
603
- if (!e) return k("timeline.bucket.noDate");
604
- let t = d(new Date(e));
605
- return Number.isNaN(t) ? k("timeline.bucket.noDate") : t < f ? k("timeline.bucket.overdue") : t === f ? k("timeline.bucket.today") : t === f + p ? k("timeline.bucket.tomorrow") : k(t < m ? "timeline.bucket.thisWeek" : t < h ? "timeline.bucket.nextWeek" : "timeline.bucket.later");
754
+ }), d = (e) => {
755
+ if (!e) return Infinity;
756
+ let t = b(e).getTime();
757
+ return Number.isNaN(t) ? Infinity : t;
758
+ };
759
+ u.sort((e, t) => d(e.startDate) - d(t.startDate));
760
+ let f = /* @__PURE__ */ new Date(), p = (e) => new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime(), m = p(f), g = 864e5, _ = m - (f.getDay() + 6) % 7 * g + 7 * g, v = _ + 7 * g, y = (e) => {
761
+ if (!e) return j("timeline.bucket.noDate");
762
+ let t = p(b(e));
763
+ return Number.isNaN(t) ? j("timeline.bucket.noDate") : t < m ? j("timeline.bucket.overdue") : t === m ? j("timeline.bucket.today") : t === m + g ? j("timeline.bucket.tomorrow") : j(t < _ ? "timeline.bucket.thisWeek" : t < v ? "timeline.bucket.nextWeek" : "timeline.bucket.later");
606
764
  };
607
- if (L && !l.every((e) => e.group == null || e.group === "")) {
608
- let e = r(L);
609
- return l.map((t) => {
610
- let n = c(L, t.group, e);
765
+ if (F && !u.every((e) => e.group == null || e.group === "")) {
766
+ let e = a(F);
767
+ return u.map((t) => {
768
+ let n = l(F, t.group, e);
611
769
  return {
612
770
  ...t,
613
- group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : k("timeline.bucket.unassigned")
771
+ group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : j("timeline.bucket.unassigned")
614
772
  };
615
773
  });
616
774
  }
617
- return l.map((e) => ({
775
+ return u.map((e) => ({
618
776
  ...e,
619
- group: g(e.startDate)
777
+ group: y(e.startDate)
620
778
  }));
621
779
  }, [
622
780
  e.items,
623
- O,
624
- C,
781
+ A,
782
+ T,
625
783
  e.objectName,
784
+ xe,
626
785
  M,
627
786
  N,
628
787
  P,
629
- F,
788
+ Se,
630
789
  I,
631
- R,
632
- L,
633
- k,
634
- j
635
- ]), B = t(async () => {
636
- x((e) => e + 1);
637
- }, []), { ref: V, isRefreshing: H, pullDistance: U } = ie({
638
- onRefresh: B,
639
- enabled: !!e.objectName && !!o
640
- }), W = ne({
790
+ F,
791
+ j,
792
+ be
793
+ ]), R = t(async () => {
794
+ S((e) => e + 1);
795
+ }, []), { ref: z, isRefreshing: Ce, pullDistance: B } = me({
796
+ onRefresh: R,
797
+ enabled: !!e.objectName && !!s
798
+ }), V = ce({
641
799
  navigation: e.navigation,
642
800
  objectName: e.objectName,
643
- onRowClick: c ?? d
644
- }), G = T?.scale ?? e.scale, K = {
801
+ onRowClick: l ?? f
802
+ }), H = C?.scale ?? e.scale, U = !!e.items;
803
+ if (!U && e.variant === "gantt") return /* @__PURE__ */ u("div", {
804
+ className: "p-4 text-destructive",
805
+ "data-testid": "timeline-unsupported-variant",
806
+ role: "alert",
807
+ children: j("timeline.unsupported.objectBoundGantt", { variants: Oe.join(", ") })
808
+ });
809
+ if (!U && !M) return /* @__PURE__ */ u("div", {
810
+ className: "p-4 text-destructive",
811
+ "data-testid": "timeline-missing-date-axis",
812
+ role: "alert",
813
+ children: j("timeline.unconfigured.noDateAxis", { fields: ke.join(", ") })
814
+ });
815
+ let we = {
645
816
  ...e,
646
- items: z || [],
647
- className: s || e.className,
648
- ...G ? { timeScale: G } : {},
817
+ items: L || [],
818
+ className: c || e.className,
819
+ ...H ? { scale: H } : {},
649
820
  onItemClick: (e) => {
650
821
  let t = e._data || e;
651
- W.handleClick(t), d?.(t);
822
+ V.handleClick(t), f?.(t);
652
823
  }
653
824
  };
654
- return v ? /* @__PURE__ */ u("div", {
825
+ return ne ? /* @__PURE__ */ d("div", {
655
826
  className: "p-4 text-destructive",
656
827
  "data-testid": "timeline-error",
657
828
  role: "alert",
658
- children: ["Error loading timeline: ", v.message]
659
- }) : re && (!z || z.length === 0) ? /* @__PURE__ */ u("div", {
829
+ children: ["Error loading timeline: ", ne.message]
830
+ }) : te && (!L || L.length === 0) ? /* @__PURE__ */ d("div", {
660
831
  className: "flex flex-col h-full min-h-[200px] p-4 gap-3",
661
832
  "data-testid": "timeline-loading",
662
833
  role: "status",
663
834
  "aria-live": "polite",
664
835
  "aria-busy": "true",
665
- children: [/* @__PURE__ */ l("span", {
836
+ children: [/* @__PURE__ */ u("span", {
666
837
  className: "sr-only",
667
838
  children: "Loading timeline…"
668
839
  }), [
@@ -670,35 +841,36 @@ var M = v.object({
670
841
  1,
671
842
  2,
672
843
  3
673
- ].map((e) => /* @__PURE__ */ u("div", {
844
+ ].map((e) => /* @__PURE__ */ d("div", {
674
845
  className: "flex items-start gap-3",
675
846
  style: { opacity: Math.max(.3, 1 - e * .18) },
676
- children: [/* @__PURE__ */ l("div", { className: "h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0" }), /* @__PURE__ */ u("div", {
847
+ children: [/* @__PURE__ */ u("div", { className: "h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0" }), /* @__PURE__ */ d("div", {
677
848
  className: "flex-1 space-y-2",
678
- children: [/* @__PURE__ */ l("div", { className: "h-4 w-1/3 rounded bg-muted/70 animate-pulse" }), /* @__PURE__ */ l("div", { className: "h-3 w-2/3 rounded bg-muted/50 animate-pulse" })]
849
+ children: [/* @__PURE__ */ u("div", { className: "h-4 w-1/3 rounded bg-muted/70 animate-pulse" }), /* @__PURE__ */ u("div", { className: "h-3 w-2/3 rounded bg-muted/50 animate-pulse" })]
679
850
  })]
680
851
  }, e))]
681
- }) : /* @__PURE__ */ u("div", {
682
- ref: V,
852
+ }) : /* @__PURE__ */ d("div", {
853
+ ref: z,
683
854
  className: "relative overflow-auto h-full min-w-0",
855
+ "data-testid": "timeline-canvas",
684
856
  children: [
685
- U > 0 && /* @__PURE__ */ l("div", {
857
+ B > 0 && /* @__PURE__ */ u("div", {
686
858
  className: "flex items-center justify-center text-xs text-muted-foreground",
687
- style: { height: U },
688
- children: H ? "Refreshing…" : "Pull to refresh"
859
+ style: { height: B },
860
+ children: Ce ? "Refreshing…" : "Pull to refresh"
689
861
  }),
690
- /* @__PURE__ */ l(A, { schema: K }),
691
- W.isOverlay && /* @__PURE__ */ l(a, {
692
- ...W,
862
+ /* @__PURE__ */ u(W, { schema: we }),
863
+ V.isOverlay && /* @__PURE__ */ u(o, {
864
+ ...V,
693
865
  title: "Timeline Item",
694
- children: (e) => /* @__PURE__ */ l("div", {
866
+ children: (e) => /* @__PURE__ */ u("div", {
695
867
  className: "space-y-3",
696
- children: Object.entries(e).map(([e, t]) => /* @__PURE__ */ u("div", {
868
+ children: Object.entries(e).map(([e, t]) => /* @__PURE__ */ d("div", {
697
869
  className: "flex flex-col",
698
- children: [/* @__PURE__ */ l("span", {
870
+ children: [/* @__PURE__ */ u("span", {
699
871
  className: "text-xs font-medium text-muted-foreground uppercase tracking-wide",
700
872
  children: e.replace(/_/g, " ")
701
- }), /* @__PURE__ */ l("span", {
873
+ }), /* @__PURE__ */ u("span", {
702
874
  className: "text-sm",
703
875
  children: String(t ?? "—")
704
876
  })]
@@ -707,26 +879,26 @@ var M = v.object({
707
879
  })
708
880
  ]
709
881
  });
710
- }, P = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("ol", {
882
+ }, G = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("ol", {
711
883
  ref: n,
712
- className: o("relative ml-3 border-l border-gray-200", e),
884
+ className: s("relative ml-3 border-l border-gray-200", e),
713
885
  ...t
714
886
  }));
715
- P.displayName = "Timeline";
716
- var F = s("ml-6", {
887
+ G.displayName = "Timeline";
888
+ var Ne = c("ml-6", {
717
889
  variants: { density: {
718
890
  default: "mb-10",
719
891
  compact: "mb-3",
720
892
  comfortable: "mb-6"
721
893
  } },
722
894
  defaultVariants: { density: "default" }
723
- }), I = e.forwardRef(({ className: e, density: t, ...n }, r) => /* @__PURE__ */ l("li", {
895
+ }), Pe = e.forwardRef(({ className: e, density: t, ...n }, r) => /* @__PURE__ */ u("li", {
724
896
  ref: r,
725
- className: o(F({ density: t }), e),
897
+ className: s(Ne({ density: t }), e),
726
898
  ...n
727
899
  }));
728
- I.displayName = "TimelineItem";
729
- var L = s("absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center", {
900
+ Pe.displayName = "TimelineItem";
901
+ var Fe = c("absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center", {
730
902
  variants: { variant: {
731
903
  default: "bg-blue-200 border-blue-400",
732
904
  success: "bg-emerald-200 border-emerald-500",
@@ -738,87 +910,87 @@ var L = s("absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center just
738
910
  done: "bg-emerald-200 border-emerald-500"
739
911
  } },
740
912
  defaultVariants: { variant: "default" }
741
- }), R = e.forwardRef(({ className: e, variant: t = "default", ...n }, r) => /* @__PURE__ */ l("div", {
913
+ }), K = e.forwardRef(({ className: e, variant: t = "default", ...n }, r) => /* @__PURE__ */ u("div", {
742
914
  ref: r,
743
- className: o(L({ variant: t }), e),
915
+ className: s(Fe({ variant: t }), e),
744
916
  ...n
745
917
  }));
746
- R.displayName = "TimelineMarker";
747
- var z = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
918
+ K.displayName = "TimelineMarker";
919
+ var Ie = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
748
920
  ref: n,
749
921
  className: e,
750
922
  ...t
751
923
  }));
752
- z.displayName = "TimelineContent";
753
- var B = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("h3", {
924
+ Ie.displayName = "TimelineContent";
925
+ var q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("h3", {
754
926
  ref: n,
755
- className: o("font-semibold text-lg mb-1", e),
927
+ className: s("font-semibold text-lg mb-1", e),
756
928
  ...t
757
929
  }));
758
- B.displayName = "TimelineTitle";
759
- var V = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("time", {
930
+ q.displayName = "TimelineTitle";
931
+ var J = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("time", {
760
932
  ref: n,
761
- className: o("text-sm font-normal text-gray-500 mb-2 block", e),
933
+ className: s("text-sm font-normal text-gray-500 mb-2 block", e),
762
934
  ...t
763
935
  }));
764
- V.displayName = "TimelineTime";
765
- var H = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("p", {
936
+ J.displayName = "TimelineTime";
937
+ var Y = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("p", {
766
938
  ref: n,
767
- className: o("text-base text-gray-700", e),
939
+ className: s("text-base text-gray-700", e),
768
940
  ...t
769
941
  }));
770
- H.displayName = "TimelineDescription";
771
- var U = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
942
+ Y.displayName = "TimelineDescription";
943
+ var Le = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
772
944
  ref: n,
773
- className: o("relative flex overflow-x-auto py-8", e),
945
+ className: s("relative flex overflow-x-auto py-8", e),
774
946
  ...t
775
947
  }));
776
- U.displayName = "TimelineHorizontal";
777
- var W = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
948
+ Le.displayName = "TimelineHorizontal";
949
+ var Re = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
778
950
  ref: n,
779
- className: o("shrink-0 w-64 relative", e),
951
+ className: s("shrink-0 w-64 relative", e),
780
952
  ...t
781
953
  }));
782
- W.displayName = "TimelineHorizontalItem";
783
- var G = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
954
+ Re.displayName = "TimelineHorizontalItem";
955
+ var ze = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
784
956
  ref: n,
785
- className: o("relative w-full border rounded-lg overflow-hidden", e),
957
+ className: s("relative w-full border rounded-lg overflow-hidden", e),
786
958
  ...t
787
959
  }));
788
- G.displayName = "TimelineGantt";
789
- var K = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
960
+ ze.displayName = "TimelineGantt";
961
+ var Be = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
790
962
  ref: n,
791
- className: o("flex border-b bg-gray-50", e),
963
+ className: s("flex border-b bg-gray-50", e),
792
964
  ...t
793
965
  }));
794
- K.displayName = "TimelineGanttHeader";
795
- var q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
966
+ Be.displayName = "TimelineGanttHeader";
967
+ var X = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
796
968
  ref: n,
797
- className: o("w-48 border-r bg-white", e),
969
+ className: s("w-48 border-r bg-white", e),
798
970
  ...t
799
971
  }));
800
- q.displayName = "TimelineGanttRowLabels";
801
- var J = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
972
+ X.displayName = "TimelineGanttRowLabels";
973
+ var Z = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
802
974
  ref: n,
803
- className: o("flex-1 overflow-x-auto", e),
975
+ className: s("flex-1 overflow-x-auto", e),
804
976
  ...t
805
977
  }));
806
- J.displayName = "TimelineGanttGrid";
807
- var Y = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
978
+ Z.displayName = "TimelineGanttGrid";
979
+ var Q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
808
980
  ref: n,
809
- className: o("flex items-center border-b min-h-12", e),
981
+ className: s("flex items-center border-b min-h-12", e),
810
982
  ...t
811
983
  }));
812
- Y.displayName = "TimelineGanttRow";
813
- var X = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
984
+ Q.displayName = "TimelineGanttRow";
985
+ var Ve = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
814
986
  ref: n,
815
- className: o("px-4 py-2 font-medium text-sm truncate", e),
987
+ className: s("px-4 py-2 font-medium text-sm truncate", e),
816
988
  ...t
817
989
  }));
818
- X.displayName = "TimelineGanttLabel";
819
- var Z = e.forwardRef(({ className: e, start: t = 0, width: n = 100, variant: r = "default", ...i }, a) => /* @__PURE__ */ l("div", {
990
+ Ve.displayName = "TimelineGanttLabel";
991
+ var He = e.forwardRef(({ className: e, start: t = 0, width: n = 100, variant: r = "default", ...i }, a) => /* @__PURE__ */ u("div", {
820
992
  ref: a,
821
- className: o("absolute h-8 rounded-md transition-colors cursor-pointer", {
993
+ className: s("absolute h-8 rounded-md transition-colors cursor-pointer", {
822
994
  default: "bg-blue-500 hover:bg-blue-600",
823
995
  success: "bg-green-500 hover:bg-green-600",
824
996
  warning: "bg-yellow-500 hover:bg-yellow-600",
@@ -831,70 +1003,127 @@ var Z = e.forwardRef(({ className: e, start: t = 0, width: n = 100, variant: r =
831
1003
  },
832
1004
  ...i
833
1005
  }));
834
- Z.displayName = "TimelineGanttBar";
835
- var Q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
1006
+ He.displayName = "TimelineGanttBar";
1007
+ var Ue = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("div", {
836
1008
  ref: n,
837
- className: o("px-2 py-1 text-white text-xs font-medium truncate", e),
1009
+ className: s("px-2 py-1 text-white text-xs font-medium truncate", e),
838
1010
  ...t
839
1011
  }));
840
- Q.displayName = "TimelineGanttBarContent";
841
- var ce = {
1012
+ Ue.displayName = "TimelineGanttBarContent";
1013
+ var We = {
842
1014
  filter: !0,
843
1015
  sort: !0,
844
1016
  limit: "limit"
845
- }, $ = ({ schema: e, ...t }) => {
846
- let { dataSource: n } = _() || {};
847
- return /* @__PURE__ */ l(ee, {
1017
+ }, $ = g(({ schema: e, ...t }) => {
1018
+ let { dataSource: n } = de() || {};
1019
+ return /* @__PURE__ */ u(ie, {
848
1020
  schema: e,
849
- mapping: ce,
1021
+ mapping: We,
850
1022
  dataSource: n,
851
1023
  testId: "object-timeline",
852
1024
  errorTitle: "This timeline’s data source could not be resolved",
853
- children: (e) => /* @__PURE__ */ l(N, {
1025
+ children: (e) => /* @__PURE__ */ u(Me, {
854
1026
  schema: e,
855
1027
  dataSource: n,
856
1028
  ...t
857
1029
  })
858
1030
  });
859
- };
860
- d.register("object-timeline", $, {
861
- namespace: "plugin-timeline",
862
- label: "Object Timeline",
863
- category: "view",
864
- inputs: [{
1031
+ }), Ge = [
1032
+ {
865
1033
  name: "objectName",
866
1034
  type: "string",
867
- label: "Object Name",
868
- required: !0
869
- }, {
1035
+ description: "Object this timeline binds to. Optional because the component-level `dataSource` binding can supply the object instead — this block registers through `ElementDataSourceGate`, which lowers the binding onto this key before the renderer sees the node. A timeline drawn from `items`, `data` or a `bind` path issues no query and needs none to draw, but `navigation` still reads it: without it `page` opens nothing and `new_window` / `openNewTab` open no record page."
1036
+ },
1037
+ {
870
1038
  name: "variant",
871
1039
  type: "enum",
872
1040
  enum: [
873
1041
  "vertical",
874
1042
  "horizontal",
875
1043
  "gantt"
1044
+ ]
1045
+ },
1046
+ {
1047
+ name: "filter",
1048
+ type: "array",
1049
+ description: "Base query filter in the rule-array form `[{ field, operator, value }, ...]`, narrowing the records the timeline fetches. Context tokens such as `{current_user_id}` are resolved first, then the filter is lowered to `$filter` on the query. Authored `items` or `data` suppress that query, so the key then narrows nothing. The MongoDB-style record form is not this key’s shape."
1050
+ },
1051
+ {
1052
+ name: "sort",
1053
+ type: "array",
1054
+ description: "Order of the records the timeline fetches, in `[{ field, order }]` form, lowered to `$orderby` on the same query. The rail draws entries composed from records by their start date, earliest first, whatever this order. Authored `items` or `data` suppress the query, so the key then orders nothing."
1055
+ },
1056
+ {
1057
+ name: "navigation",
1058
+ type: "object",
1059
+ description: "What an entry click opens — the `{ mode, size, openNewTab, preventNavigation }` block a list view declares. With the key ABSENT a click opens nothing: this renderer supplies no drawer default. `mode` is an overlay (`drawer`, `modal`, `split`, `popover`), `new_window`, `page` or `none`, and a block written without `mode` takes the spec’s `page` default. `drawer`, `modal` and `popover` open the entry’s record in that overlay, but `split` opens nothing, because the timeline hands the split shell no main panel; `new_window` opens the record page in a new tab; `none` opens nothing. `page` opens the record page of the timeline’s `objectName` through the record navigator the host publishes (the console publishes one on its custom pages, record pages and list views); under a host that publishes none, such as an embedded renderer, or on a timeline that names no `objectName`, there is no record page to open and the click opens nothing. `preventNavigation: true` opens nothing whatever the mode, `openNewTab: true` opens the record page in a new tab and outranks every mode except `none`, and `size` sets the overlay width. On a timeline that names no `objectName`, `new_window` and `openNewTab` open no record page either: the new tab’s address is a slash and the entry’s `id` alone (its `_id` when it has no `id`, `undefined` when it has neither). A click handler from a parent view outranks the whole key."
1060
+ },
1061
+ {
1062
+ name: "timeline",
1063
+ type: "object",
1064
+ description: "Timeline configuration, the author face — the same block `ListViewSchema.timeline` declares: { startDateField, endDateField, titleField, groupByField, colorField, scale }. The flat top-level spellings beside it are the runtime handoff, not a second authoring spelling. On entries composed from records, `startDateField` is the entry’s date, `endDateField` the end printed after it, `titleField` the title, `groupByField` the field whose value heads each group (without it, entries group into date buckets), and `colorField` the field whose option colour, or the value itself when it is a colour literal, paints the marker. Each outranks the flat key of the same binding, and `titleField` / `startDateField` outrank `mapping`’s `title` / `date`. `scale` sets the axis unit of the gantt branch, which on this block draws authored `items` only."
1065
+ },
1066
+ {
1067
+ name: "limit",
1068
+ type: "number",
1069
+ description: "Maximum number of records loaded onto the rail (row cap); lowered to the query's top-level `$top` (renderer default 100). A timeline renders one rail with no pagination control, so this is the author's window rather than a page size. A value that is not a positive integer is ignored with a console warning, and the default cap applies."
1070
+ },
1071
+ {
1072
+ name: "data",
1073
+ type: "array",
1074
+ description: "Pre-fetched records — read FIRST as the rail's row source, ahead of the data-scope binding and the fetch, and composed into entries through the same `timeline` field bindings a fetched row takes; authoring it suppresses the object query entirely. Distinct from `items`, which is the already-composed entry shape and wins over this key when both are written."
1075
+ },
1076
+ {
1077
+ name: "items",
1078
+ type: "array",
1079
+ description: "Static inline entries — read ahead of every record source, `data` above included, and bypasses the object query entirely (the renderer becomes a pass-through). Each element is objectui's declared timeline element, `@object-ui/types`'s `TimelineFeedItem` (`variant` absent / `vertical` / `horizontal`) or `TimelineGanttItem` (`variant: 'gantt'`), the arm this node's `variant` selects. They are drawn as written: the `timeline` block’s field bindings, `mapping` and `descriptionField` do not apply to them."
1080
+ },
1081
+ {
1082
+ name: "dateFormat",
1083
+ type: "enum",
1084
+ enum: [
1085
+ "short",
1086
+ "long",
1087
+ "iso"
876
1088
  ],
877
- defaultValue: "vertical"
878
- }]
879
- }), d.register("timeline", $, {
1089
+ description: "How each entry's date is rendered (renderer default `short`): `short` / `long` are locale-formatted, `iso` is the locale-free machine form."
1090
+ },
1091
+ {
1092
+ name: "rowLabel",
1093
+ type: "string",
1094
+ description: "Header label for the gantt row column — read by the gantt branch only, which on this block needs authored `items`. Without it the header shows the default label."
1095
+ },
1096
+ {
1097
+ name: "minDate",
1098
+ type: "string",
1099
+ description: "Pin the gantt axis start (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `minDate` after `maxDate`, refuses the chart with a diagnostic naming it."
1100
+ },
1101
+ {
1102
+ name: "maxDate",
1103
+ type: "string",
1104
+ description: "Pin the gantt axis end (ISO `yyyy-mm-dd`) instead of deriving it from the rows; only a non-empty value is honoured. A value that is not a date, or a `maxDate` before `minDate`, refuses the chart with a diagnostic naming it."
1105
+ },
1106
+ {
1107
+ name: "descriptionField",
1108
+ type: "string",
1109
+ description: "Field rendered as each entry's description (renderer default `description`). It is declared flat because the `timeline` block has no member for it, and `mapping.description` outranks it when both are written."
1110
+ },
1111
+ {
1112
+ name: "mapping",
1113
+ type: "object",
1114
+ description: "Record-to-entry field mapping ({ title, date, description, variant }) — the objectui-side binding record read BETWEEN the `timeline` block and the flat fallbacks. Its `variant` member (the field whose value picks each marker colour, renderer default `variant`) is the only spelling that binding has. On the vertical rail a colour that `timeline.colorField` resolves for an entry outranks that marker colour."
1115
+ }
1116
+ ];
1117
+ f.register("object-timeline", $, {
1118
+ namespace: "plugin-timeline",
1119
+ label: "Object Timeline",
1120
+ category: "view",
1121
+ inputs: [...Ge]
1122
+ }), f.register("timeline", $, {
880
1123
  namespace: "view",
881
1124
  label: "Timeline View",
882
1125
  category: "view",
883
- inputs: [{
884
- name: "objectName",
885
- type: "string",
886
- label: "Object Name",
887
- required: !0
888
- }, {
889
- name: "variant",
890
- type: "enum",
891
- enum: [
892
- "vertical",
893
- "horizontal",
894
- "gantt"
895
- ],
896
- defaultValue: "vertical"
897
- }]
1126
+ inputs: [...Ge]
898
1127
  });
899
1128
  //#endregion
900
- export { N as ObjectTimeline, $ as ObjectTimelineRenderer, C as TIMELINE_SCALES, P as Timeline, z as TimelineContent, H as TimelineDescription, G as TimelineGantt, Z as TimelineGanttBar, Q as TimelineGanttBarContent, J as TimelineGanttGrid, K as TimelineGanttHeader, X as TimelineGanttLabel, Y as TimelineGanttRow, q as TimelineGanttRowLabels, U as TimelineHorizontal, W as TimelineHorizontalItem, I as TimelineItem, R as TimelineMarker, A as TimelineRenderer, V as TimelineTime, B as TimelineTitle, T as generateTimeScaleHeaders, w as resolveTimelineScale, F as timelineItemVariants, L as timelineMarkerVariants };
1129
+ export { Me as ObjectTimeline, $ as ObjectTimelineRenderer, T as TIMELINE_SCALES, G as Timeline, Ie as TimelineContent, Y as TimelineDescription, ze as TimelineGantt, He as TimelineGanttBar, Ue as TimelineGanttBarContent, Z as TimelineGanttGrid, Be as TimelineGanttHeader, Ve as TimelineGanttLabel, Q as TimelineGanttRow, X as TimelineGanttRowLabels, Le as TimelineHorizontal, Re as TimelineHorizontalItem, Pe as TimelineItem, K as TimelineMarker, W as TimelineRenderer, J as TimelineTime, q as TimelineTitle, Se as generateTimeScaleHeaders, E as resolveTimelineScale, Ne as timelineItemVariants, Fe as timelineMarkerVariants };