@object-ui/plugin-timeline 17.6.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, useSafeFieldLabel 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
+ }
81
135
  return {
82
- minDate: new Date(n).toISOString().split("T")[0],
83
- maxDate: new Date(r).toISOString().split("T")[0]
136
+ start: u[0].start,
137
+ end: u[u.length - 1].end,
138
+ units: u
84
139
  };
85
140
  }
86
- function D(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;
141
+ function P(e, t, n) {
142
+ let r = e.end - e.start;
88
143
  return {
89
- start: c / s * 100,
90
- width: l / s * 100
144
+ start: (t - e.start) / r * 100,
145
+ width: (n - t) / r * 100
91
146
  };
92
147
  }
93
- function O(e, t, n) {
94
- let r = new Date(e);
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
+ }
185
+ return {
186
+ ok: !0,
187
+ rows: t
188
+ };
189
+ }
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
+ })));
197
+ return {
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
229
+ };
230
+ }
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 k({ 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 A(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 A(e) {
121
262
  }
122
263
  return t;
123
264
  }
124
- var j = ({ 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 = A(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 ? O(e.time, a, d) : e.startDate ? O(e.startDate, a, d) : "", i = e.endDate && e.endDate !== e.startDate ? O(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(k, {
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: O(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 = D(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${O(n.startDate, a, d)} - ${O(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", j, {
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", j, {
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", j, {
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", j, {
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,22 +621,37 @@ d.register("timeline", j, {
462
621
  }
463
622
  }
464
623
  });
465
- var M = v.object({
466
- title: v.string().optional(),
467
- date: v.string().optional(),
468
- description: v.string().optional(),
469
- variant: v.string().optional()
470
- }), ae = v.object({
471
- mapping: M.optional(),
472
- objectName: v.string().optional(),
473
- titleField: v.string().optional(),
474
- dateField: v.string().optional(),
475
- startDateField: v.string().optional(),
476
- endDateField: v.string().optional(),
477
- descriptionField: v.string().optional(),
478
- groupByField: v.string().optional(),
479
- colorField: v.string().optional(),
480
- scale: v.enum([
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;
629
+ }
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([
481
655
  "hour",
482
656
  "day",
483
657
  "week",
@@ -485,174 +659,181 @@ var M = v.object({
485
659
  "quarter",
486
660
  "year"
487
661
  ]).optional()
488
- }), N = ({ schema: e, dataSource: o, className: s, onRowClick: c, onItemClick: d, ...h }) => {
489
- let [g, ee] = i([]), [_, v] = i(() => {
490
- 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;
491
665
  return !t && !n && !!e.objectName;
492
- }), [y, b] = i(null), [x, C] = i(0), [w, T] = i(null), E = e.timeline;
666
+ }), [ne, re] = a(null), ie = i(0), [de, S] = a(0), C = e.timeline;
493
667
  n(() => {
494
- let t = ae.safeParse(e);
668
+ let t = je.safeParse(e);
495
669
  t.success || console.warn("[ObjectTimeline] Invalid timeline configuration:", t.error.format());
496
- }, [e]);
497
- let D = te(e.bind);
498
- n(() => {
499
- let t = !0;
500
- return (async () => {
501
- if (!(!o || typeof o.getObjectSchema != "function" || !e.objectName)) try {
502
- let n = await o.getObjectSchema(e.objectName);
503
- t && T(n);
504
- } catch (e) {
505
- console.warn("Failed to fetch object def for ObjectTimeline", e);
506
- }
507
- })(), () => {
508
- t = !1;
509
- };
510
- }, [e.objectName, o]);
511
- let O = JSON.stringify(e.filter ?? null), k = 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);
512
675
  n(() => {
513
- e.objectName && !D && !e.items && !h.data ? (async () => {
514
- if (!o || typeof o.find != "function" || !e.objectName) {
515
- v(!1);
676
+ let t = ++ie.current, n = () => ie.current === t, r = async () => {
677
+ if (!s || typeof s.find != "function" || !e.objectName) {
678
+ x(!1);
516
679
  return;
517
680
  }
518
- v(!0);
681
+ x(!0);
519
682
  try {
520
- let t = f(w?.fields), n = await o.find(e.objectName, {
521
- $filter: e.filter,
522
- $orderby: p(e.sort),
523
- $top: e.limit ?? 100,
524
- ...t.length > 0 ? { $expand: t } : {}
525
- }), r = m(n);
526
- 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));
527
690
  } catch (e) {
528
- console.error(e), b(e);
691
+ console.error(e), n() && re(e);
529
692
  } finally {
530
- v(!1);
693
+ n() && x(!1);
531
694
  }
532
- })() : v(!1);
695
+ };
696
+ if (k) {
697
+ if (!he) return;
698
+ r();
699
+ } else x(!1);
533
700
  }, [
534
701
  e.objectName,
535
- o,
536
- D,
537
- e.items,
538
- h.data,
539
- x,
702
+ s,
540
703
  w,
541
- O,
542
- k,
543
- e.limit
704
+ e.items,
705
+ g.data,
706
+ de,
707
+ he,
708
+ T,
709
+ _e,
710
+ ve,
711
+ e.limit,
712
+ E,
713
+ ye
544
714
  ]);
545
- let A = h.data || D || g, { t: M } = S(), { fieldOptionLabel: N } = re(), P = E?.titleField ?? e.mapping?.title ?? e.titleField ?? "name", F = E?.startDateField ?? E?.dateField ?? e.mapping?.date ?? e.startDateField ?? e.dateField ?? "date", I = E?.endDateField ?? e.endDateField ?? F, L = e.mapping?.description ?? e.descriptionField ?? "description", R = e.mapping?.variant ?? "variant", z = E?.groupByField ?? e.groupByField, B = E?.colorField ?? e.colorField, V = 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(() => {
546
716
  if (e.items) return e.items;
547
- if (!A || !Array.isArray(A)) return [];
548
- let t = w?.fields ?? {}, n = e.objectName || "", r = (e) => {
549
- if (!e || !t[e]?.options) return {};
550
- let n = {};
551
- for (let r of t[e].options) r && r.value != null && (n[String(r.value)] = r);
552
- return n;
553
- }, i = r(B), a = Array.isArray(E?.metaFields) ? E.metaFields.filter((e) => typeof e == "string" && e) : ["status", "priority"].filter((e) => t[e]), o = {};
554
- for (let e of a) o[e] = r(e);
555
- let s = (e) => {
556
- if (e == null || e === "") return;
557
- let t = i[String(e)];
558
- if (t?.color) return String(t.color);
559
- let n = String(e);
560
- if (/^#([0-9a-f]{3}){1,2}$/i.test(n) || n.startsWith("rgb") || n.startsWith("hsl")) return n;
561
- }, 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) => {
562
726
  if (t == null || t === "") return null;
563
- let i = r[String(t)];
727
+ let r = n[String(t)];
564
728
  return {
565
- label: i?.label ? N(n, e, String(t), i.label) : String(t),
566
- color: i?.color
729
+ label: r?.label ? be(i, e, String(t), r.label) : String(t),
730
+ color: r?.color
567
731
  };
568
- }, l = A.map((e) => {
569
- let t = e[F], r = e[I], i = B ? e[B] : void 0, l = z ? e[z] : void 0, u = [];
570
- if (n) for (let t of a) {
571
- let n = c(t, e[t], o[t] || {});
572
- 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({
573
737
  key: t,
574
738
  label: n.label,
575
739
  color: n.color
576
740
  });
577
741
  }
578
742
  return {
579
- title: e[P],
580
- time: t,
581
- startDate: t,
582
- endDate: r,
583
- description: e[L],
584
- variant: e[R] || "default",
585
- color: s(i),
586
- group: l,
587
- 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,
588
752
  _data: e
589
753
  };
590
- });
591
- l.sort((e, t) => (e.startDate ? new Date(e.startDate).getTime() : Infinity) - (t.startDate ? new Date(t.startDate).getTime() : Infinity));
592
- 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) => {
593
- if (!e) return M("timeline.bucket.noDate");
594
- let t = d(new Date(e));
595
- return Number.isNaN(t) ? M("timeline.bucket.noDate") : t < f ? M("timeline.bucket.overdue") : t === f ? M("timeline.bucket.today") : t === f + p ? M("timeline.bucket.tomorrow") : M(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");
596
764
  };
597
- if (z && !l.every((e) => e.group == null || e.group === "")) {
598
- let e = r(z);
599
- return l.map((t) => {
600
- let n = c(z, 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);
601
769
  return {
602
770
  ...t,
603
- group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : M("timeline.bucket.unassigned")
771
+ group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : j("timeline.bucket.unassigned")
604
772
  };
605
773
  });
606
774
  }
607
- return l.map((e) => ({
775
+ return u.map((e) => ({
608
776
  ...e,
609
- group: g(e.startDate)
777
+ group: y(e.startDate)
610
778
  }));
611
779
  }, [
612
780
  e.items,
613
781
  A,
614
- w,
782
+ T,
615
783
  e.objectName,
784
+ xe,
785
+ M,
786
+ N,
616
787
  P,
617
- F,
788
+ Se,
618
789
  I,
619
- L,
620
- R,
621
- B,
622
- z,
623
- M,
624
- N
625
- ]), H = t(async () => {
626
- C((e) => e + 1);
627
- }, []), { ref: U, isRefreshing: W, pullDistance: G } = ie({
628
- onRefresh: H,
629
- enabled: !!e.objectName && !!o
630
- }), K = 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({
631
799
  navigation: e.navigation,
632
800
  objectName: e.objectName,
633
- onRowClick: c ?? d
634
- }), q = E?.scale ?? e.scale, J = {
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 = {
635
816
  ...e,
636
- items: V || [],
637
- className: s || e.className,
638
- ...q ? { timeScale: q } : {},
817
+ items: L || [],
818
+ className: c || e.className,
819
+ ...H ? { scale: H } : {},
639
820
  onItemClick: (e) => {
640
821
  let t = e._data || e;
641
- K.handleClick(t), d?.(t);
822
+ V.handleClick(t), f?.(t);
642
823
  }
643
824
  };
644
- return y ? /* @__PURE__ */ u("div", {
825
+ return ne ? /* @__PURE__ */ d("div", {
645
826
  className: "p-4 text-destructive",
646
827
  "data-testid": "timeline-error",
647
828
  role: "alert",
648
- children: ["Error loading timeline: ", y.message]
649
- }) : _ && (!V || V.length === 0) ? /* @__PURE__ */ u("div", {
829
+ children: ["Error loading timeline: ", ne.message]
830
+ }) : te && (!L || L.length === 0) ? /* @__PURE__ */ d("div", {
650
831
  className: "flex flex-col h-full min-h-[200px] p-4 gap-3",
651
832
  "data-testid": "timeline-loading",
652
833
  role: "status",
653
834
  "aria-live": "polite",
654
835
  "aria-busy": "true",
655
- children: [/* @__PURE__ */ l("span", {
836
+ children: [/* @__PURE__ */ u("span", {
656
837
  className: "sr-only",
657
838
  children: "Loading timeline…"
658
839
  }), [
@@ -660,35 +841,36 @@ var M = v.object({
660
841
  1,
661
842
  2,
662
843
  3
663
- ].map((e) => /* @__PURE__ */ u("div", {
844
+ ].map((e) => /* @__PURE__ */ d("div", {
664
845
  className: "flex items-start gap-3",
665
846
  style: { opacity: Math.max(.3, 1 - e * .18) },
666
- 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", {
667
848
  className: "flex-1 space-y-2",
668
- 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" })]
669
850
  })]
670
851
  }, e))]
671
- }) : /* @__PURE__ */ u("div", {
672
- ref: U,
852
+ }) : /* @__PURE__ */ d("div", {
853
+ ref: z,
673
854
  className: "relative overflow-auto h-full min-w-0",
855
+ "data-testid": "timeline-canvas",
674
856
  children: [
675
- G > 0 && /* @__PURE__ */ l("div", {
857
+ B > 0 && /* @__PURE__ */ u("div", {
676
858
  className: "flex items-center justify-center text-xs text-muted-foreground",
677
- style: { height: G },
678
- children: W ? "Refreshing…" : "Pull to refresh"
859
+ style: { height: B },
860
+ children: Ce ? "Refreshing…" : "Pull to refresh"
679
861
  }),
680
- /* @__PURE__ */ l(j, { schema: J }),
681
- K.isOverlay && /* @__PURE__ */ l(a, {
682
- ...K,
862
+ /* @__PURE__ */ u(W, { schema: we }),
863
+ V.isOverlay && /* @__PURE__ */ u(o, {
864
+ ...V,
683
865
  title: "Timeline Item",
684
- children: (e) => /* @__PURE__ */ l("div", {
866
+ children: (e) => /* @__PURE__ */ u("div", {
685
867
  className: "space-y-3",
686
- children: Object.entries(e).map(([e, t]) => /* @__PURE__ */ u("div", {
868
+ children: Object.entries(e).map(([e, t]) => /* @__PURE__ */ d("div", {
687
869
  className: "flex flex-col",
688
- children: [/* @__PURE__ */ l("span", {
870
+ children: [/* @__PURE__ */ u("span", {
689
871
  className: "text-xs font-medium text-muted-foreground uppercase tracking-wide",
690
872
  children: e.replace(/_/g, " ")
691
- }), /* @__PURE__ */ l("span", {
873
+ }), /* @__PURE__ */ u("span", {
692
874
  className: "text-sm",
693
875
  children: String(t ?? "—")
694
876
  })]
@@ -697,26 +879,26 @@ var M = v.object({
697
879
  })
698
880
  ]
699
881
  });
700
- }, P = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("ol", {
882
+ }, G = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ u("ol", {
701
883
  ref: n,
702
- className: o("relative ml-3 border-l border-gray-200", e),
884
+ className: s("relative ml-3 border-l border-gray-200", e),
703
885
  ...t
704
886
  }));
705
- P.displayName = "Timeline";
706
- var F = s("ml-6", {
887
+ G.displayName = "Timeline";
888
+ var Ne = c("ml-6", {
707
889
  variants: { density: {
708
890
  default: "mb-10",
709
891
  compact: "mb-3",
710
892
  comfortable: "mb-6"
711
893
  } },
712
894
  defaultVariants: { density: "default" }
713
- }), 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", {
714
896
  ref: r,
715
- className: o(F({ density: t }), e),
897
+ className: s(Ne({ density: t }), e),
716
898
  ...n
717
899
  }));
718
- I.displayName = "TimelineItem";
719
- 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", {
720
902
  variants: { variant: {
721
903
  default: "bg-blue-200 border-blue-400",
722
904
  success: "bg-emerald-200 border-emerald-500",
@@ -728,87 +910,87 @@ var L = s("absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center just
728
910
  done: "bg-emerald-200 border-emerald-500"
729
911
  } },
730
912
  defaultVariants: { variant: "default" }
731
- }), 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", {
732
914
  ref: r,
733
- className: o(L({ variant: t }), e),
915
+ className: s(Fe({ variant: t }), e),
734
916
  ...n
735
917
  }));
736
- R.displayName = "TimelineMarker";
737
- 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", {
738
920
  ref: n,
739
921
  className: e,
740
922
  ...t
741
923
  }));
742
- z.displayName = "TimelineContent";
743
- 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", {
744
926
  ref: n,
745
- className: o("font-semibold text-lg mb-1", e),
927
+ className: s("font-semibold text-lg mb-1", e),
746
928
  ...t
747
929
  }));
748
- B.displayName = "TimelineTitle";
749
- 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", {
750
932
  ref: n,
751
- 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),
752
934
  ...t
753
935
  }));
754
- V.displayName = "TimelineTime";
755
- 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", {
756
938
  ref: n,
757
- className: o("text-base text-gray-700", e),
939
+ className: s("text-base text-gray-700", e),
758
940
  ...t
759
941
  }));
760
- H.displayName = "TimelineDescription";
761
- 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", {
762
944
  ref: n,
763
- className: o("relative flex overflow-x-auto py-8", e),
945
+ className: s("relative flex overflow-x-auto py-8", e),
764
946
  ...t
765
947
  }));
766
- U.displayName = "TimelineHorizontal";
767
- 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", {
768
950
  ref: n,
769
- className: o("shrink-0 w-64 relative", e),
951
+ className: s("shrink-0 w-64 relative", e),
770
952
  ...t
771
953
  }));
772
- W.displayName = "TimelineHorizontalItem";
773
- 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", {
774
956
  ref: n,
775
- className: o("relative w-full border rounded-lg overflow-hidden", e),
957
+ className: s("relative w-full border rounded-lg overflow-hidden", e),
776
958
  ...t
777
959
  }));
778
- G.displayName = "TimelineGantt";
779
- 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", {
780
962
  ref: n,
781
- className: o("flex border-b bg-gray-50", e),
963
+ className: s("flex border-b bg-gray-50", e),
782
964
  ...t
783
965
  }));
784
- K.displayName = "TimelineGanttHeader";
785
- 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", {
786
968
  ref: n,
787
- className: o("w-48 border-r bg-white", e),
969
+ className: s("w-48 border-r bg-white", e),
788
970
  ...t
789
971
  }));
790
- q.displayName = "TimelineGanttRowLabels";
791
- 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", {
792
974
  ref: n,
793
- className: o("flex-1 overflow-x-auto", e),
975
+ className: s("flex-1 overflow-x-auto", e),
794
976
  ...t
795
977
  }));
796
- J.displayName = "TimelineGanttGrid";
797
- 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", {
798
980
  ref: n,
799
- className: o("flex items-center border-b min-h-12", e),
981
+ className: s("flex items-center border-b min-h-12", e),
800
982
  ...t
801
983
  }));
802
- Y.displayName = "TimelineGanttRow";
803
- 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", {
804
986
  ref: n,
805
- 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),
806
988
  ...t
807
989
  }));
808
- X.displayName = "TimelineGanttLabel";
809
- 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", {
810
992
  ref: a,
811
- className: o("absolute h-8 rounded-md transition-colors cursor-pointer", {
993
+ className: s("absolute h-8 rounded-md transition-colors cursor-pointer", {
812
994
  default: "bg-blue-500 hover:bg-blue-600",
813
995
  success: "bg-green-500 hover:bg-green-600",
814
996
  warning: "bg-yellow-500 hover:bg-yellow-600",
@@ -821,70 +1003,127 @@ var Z = e.forwardRef(({ className: e, start: t = 0, width: n = 100, variant: r =
821
1003
  },
822
1004
  ...i
823
1005
  }));
824
- Z.displayName = "TimelineGanttBar";
825
- 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", {
826
1008
  ref: n,
827
- 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),
828
1010
  ...t
829
1011
  }));
830
- Q.displayName = "TimelineGanttBarContent";
831
- var oe = {
1012
+ Ue.displayName = "TimelineGanttBarContent";
1013
+ var We = {
832
1014
  filter: !0,
833
1015
  sort: !0,
834
1016
  limit: "limit"
835
- }, $ = ({ schema: e, ...t }) => {
836
- let { dataSource: n } = _() || {};
837
- return /* @__PURE__ */ l(ee, {
1017
+ }, $ = g(({ schema: e, ...t }) => {
1018
+ let { dataSource: n } = de() || {};
1019
+ return /* @__PURE__ */ u(ie, {
838
1020
  schema: e,
839
- mapping: oe,
1021
+ mapping: We,
840
1022
  dataSource: n,
841
1023
  testId: "object-timeline",
842
1024
  errorTitle: "This timeline’s data source could not be resolved",
843
- children: (e) => /* @__PURE__ */ l(N, {
1025
+ children: (e) => /* @__PURE__ */ u(Me, {
844
1026
  schema: e,
845
1027
  dataSource: n,
846
1028
  ...t
847
1029
  })
848
1030
  });
849
- };
850
- d.register("object-timeline", $, {
851
- namespace: "plugin-timeline",
852
- label: "Object Timeline",
853
- category: "view",
854
- inputs: [{
1031
+ }), Ge = [
1032
+ {
855
1033
  name: "objectName",
856
1034
  type: "string",
857
- label: "Object Name",
858
- required: !0
859
- }, {
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
+ {
860
1038
  name: "variant",
861
1039
  type: "enum",
862
1040
  enum: [
863
1041
  "vertical",
864
1042
  "horizontal",
865
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"
866
1088
  ],
867
- defaultValue: "vertical"
868
- }]
869
- }), 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", $, {
870
1123
  namespace: "view",
871
1124
  label: "Timeline View",
872
1125
  category: "view",
873
- inputs: [{
874
- name: "objectName",
875
- type: "string",
876
- label: "Object Name",
877
- required: !0
878
- }, {
879
- name: "variant",
880
- type: "enum",
881
- enum: [
882
- "vertical",
883
- "horizontal",
884
- "gantt"
885
- ],
886
- defaultValue: "vertical"
887
- }]
1126
+ inputs: [...Ge]
888
1127
  });
889
1128
  //#endregion
890
- 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, j 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 };