@object-ui/plugin-timeline 17.2.0 → 17.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,354 @@
1
1
  # @object-ui/plugin-timeline
2
2
 
3
+ ## 17.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 01c9188: fix(plugin-timeline): dates follow the active locale instead of a hardcoded en-US
8
+
9
+ A `zh` console rendered a fully Chinese timeline widget whose axis read
10
+ `Aug 11` / `Sep 2026` and whose item dates read `August 11, 2026`
11
+ (objectui#4513). `renderer.tsx` handed `Intl` a literal `'en-US'` at four sites
12
+ — the hour, day and month gantt headers, and the `long` item date — so nothing
13
+ a user or a tenant configured could reach them.
14
+
15
+ A fifth site was the same defect spelled as an omission: the `short` item date
16
+ called `toLocaleDateString()` with no tag at all, which means the _machine's_
17
+ locale. It agreed with the other four only by the accident of an en-US runner,
18
+ and rendered a third locale on anyone else's machine.
19
+
20
+ All five now resolve through `useDisplayLocale()` from `@object-ui/i18n`
21
+ (tenant regional default → active UI language → `en`) — the one channel every
22
+ field, number and currency renderer already uses, converged there in
23
+ objectui#4468. The locale is read once in `TimelineRenderer` and threaded into
24
+ the two module-level date helpers, which cannot host a hook themselves.
25
+
26
+ English output is byte-identical at all five sites: `'en'` and the retired
27
+ `'en-US'` produce the same forms, and `generateTimeScaleHeaders` gained an
28
+ optional trailing `locale` parameter that defaults to `'en'`, so existing
29
+ three-argument callers are unaffected. The locale-free header vocabularies
30
+ (`Week n`, `Qn YYYY`, `YYYY`) and all non-date rendering are untouched.
31
+
32
+ - 0082db8: The timeline's gantt bucket labels and its row-label default speak the session language
33
+
34
+ objectui#4513 routed every `Intl` call in the timeline renderer through `useDisplayLocale()`, so a Chinese session renders `2026年8月` on the month axis and `2026年8月11日` on item dates. Three sibling strings in the same renderer never went through `Intl` at all and stayed English on that same Chinese axis: the `week` header (`Week 1`), the `quarter` header (`Q3 2026`), and the gantt row-label column default (`Items`). The half-fixed state was the visible one — a Chinese date axis with English bucket labels beside it.
35
+
36
+ They are a translation concern rather than a locale-resolver one, and that distinction is the fix: a locale TAG formats a date, only a TRANSLATION spells a word. All three now resolve through the package's existing channel — `useTimelineTranslation` / `TIMELINE_DEFAULT_TRANSLATIONS`, the `createSafeTranslation` factory `ObjectTimeline` already uses for `timeline.bucket.*` — under three new keys carried by all ten locale packs: `timeline.scale.week`, `timeline.scale.quarter`, `timeline.gantt.rowLabel`.
37
+
38
+ The week number and the quarter/year ride the channel's own `{{hole}}` parameters rather than being concatenated, because the word order belongs to the translation: Chinese puts the year first (`2026年第3季度`), which no `Q${q} ${year}` template can produce at all. Only the row-label DEFAULT moved — an author who writes `rowLabel` still supplies their own string, and the `year` scale stays a bare `String(getFullYear())` with no vocabulary in it to translate.
39
+
40
+ English output is byte-identical to the retired literals: the `en` pack values are the same two templates the code used to interpolate by hand. `generateTimeScaleHeaders` is a pure exported function and cannot host a hook, so the translate fn is threaded in as an optional fifth parameter on the seam #4513 opened for `locale`, defaulting to the package's own defaults table — the same lookup the channel serves with no `I18nProvider` mounted. Existing three- and four-argument call sites are unaffected.
41
+
42
+ One consequence is worth stating because it looks like a bug and is not: dates and vocabulary resolve through different channels on purpose. `useDisplayLocale()` puts the tenant's regional default first (how this organization writes dates), while `t` follows the UI language (what this user reads). A tenant configured `en` whose user reads Chinese chrome therefore sees `Aug 2026` beside `第 1 周` — the same split `timeline.bucket.*` has always had.
43
+
44
+ ### Patch Changes
45
+
46
+ - Updated dependencies [0e67b53]
47
+ - Updated dependencies [ceccdcf]
48
+ - Updated dependencies [d6e5124]
49
+ - Updated dependencies [debad27]
50
+ - Updated dependencies [dc2aa3e]
51
+ - Updated dependencies [ee66e2e]
52
+ - Updated dependencies [ee26e65]
53
+ - Updated dependencies [5900ac5]
54
+ - Updated dependencies [932cbcd]
55
+ - Updated dependencies [734d186]
56
+ - Updated dependencies [f650253]
57
+ - Updated dependencies [3d9769a]
58
+ - Updated dependencies [8f85f8b]
59
+ - Updated dependencies [d0c3b26]
60
+ - Updated dependencies [3fc2971]
61
+ - Updated dependencies [aca27fa]
62
+ - Updated dependencies [dde7283]
63
+ - Updated dependencies [f7c6430]
64
+ - Updated dependencies [4dadf0d]
65
+ - Updated dependencies [ae10a01]
66
+ - Updated dependencies [92876f0]
67
+ - Updated dependencies [f279deb]
68
+ - Updated dependencies [4b70d28]
69
+ - Updated dependencies [eb7f586]
70
+ - Updated dependencies [e901131]
71
+ - Updated dependencies [d9d3463]
72
+ - Updated dependencies [2a40f69]
73
+ - Updated dependencies [bec3e14]
74
+ - Updated dependencies [613b167]
75
+ - Updated dependencies [b4d3c22]
76
+ - Updated dependencies [1f9b905]
77
+ - Updated dependencies [cb13400]
78
+ - Updated dependencies [828549a]
79
+ - Updated dependencies [e1ade8f]
80
+ - Updated dependencies [bc64bfe]
81
+ - Updated dependencies [abb0f81]
82
+ - Updated dependencies [38ab505]
83
+ - Updated dependencies [3e19fe7]
84
+ - Updated dependencies [bb58d1d]
85
+ - Updated dependencies [5cc847c]
86
+ - Updated dependencies [fa21254]
87
+ - Updated dependencies [33c32bf]
88
+ - Updated dependencies [66fb4fa]
89
+ - Updated dependencies [b953a97]
90
+ - Updated dependencies [d7f3e30]
91
+ - Updated dependencies [6d641c9]
92
+ - Updated dependencies [7e4f0e5]
93
+ - Updated dependencies [c911544]
94
+ - Updated dependencies [a84385b]
95
+ - Updated dependencies [45e1949]
96
+ - Updated dependencies [92250d6]
97
+ - Updated dependencies [c1d939f]
98
+ - Updated dependencies [58bebf6]
99
+ - Updated dependencies [405e808]
100
+ - Updated dependencies [49ae9f4]
101
+ - Updated dependencies [a3ae404]
102
+ - Updated dependencies [bfdf3d4]
103
+ - Updated dependencies [bb68488]
104
+ - Updated dependencies [c0f9a4b]
105
+ - Updated dependencies [b1e42d0]
106
+ - Updated dependencies [2459a3e]
107
+ - Updated dependencies [ac853ce]
108
+ - Updated dependencies [fa51109]
109
+ - Updated dependencies [d6aa172]
110
+ - Updated dependencies [fe52a04]
111
+ - Updated dependencies [d46f9b8]
112
+ - Updated dependencies [3f5f87c]
113
+ - Updated dependencies [2fea4d2]
114
+ - Updated dependencies [f5e1143]
115
+ - Updated dependencies [7f1cb33]
116
+ - Updated dependencies [f148a64]
117
+ - Updated dependencies [bb68488]
118
+ - Updated dependencies [2e3b0c0]
119
+ - Updated dependencies [9461dd3]
120
+ - Updated dependencies [78fa331]
121
+ - Updated dependencies [47f551b]
122
+ - Updated dependencies [31ab1ac]
123
+ - Updated dependencies [0082db8]
124
+ - Updated dependencies [ab04728]
125
+ - Updated dependencies [5bf09fd]
126
+ - Updated dependencies [06915b0]
127
+ - Updated dependencies [ff84b05]
128
+ - @object-ui/i18n@17.5.0
129
+ - @object-ui/react@17.5.0
130
+ - @object-ui/components@17.5.0
131
+ - @object-ui/core@17.5.0
132
+ - @object-ui/types@17.5.0
133
+ - @object-ui/mobile@17.5.0
134
+
135
+ ## 17.4.0
136
+
137
+ ### Patch Changes
138
+
139
+ - 022002a: `PageComponentSchema.dataSource` now reaches the remaining object-bound public
140
+ blocks: `object-gantt` / `object-timeline` / `object-map` / `object-pivot` /
141
+ `object-master-detail-form` / `embeddable-form` / `record:line_items`
142
+ (objectstack#7121).
143
+
144
+ objectstack#6953 wired the spec's per-element data binding
145
+ (`dataSource: { object, view?, filter?, sort?, limit? }`) to the eight blocks it
146
+ named and left the same declaration inert on these seven. Each gates its fetch on
147
+ its own object key and nothing mapped `dataSource.object` onto it, so a page
148
+ written the way the spec documents rendered an empty gantt / an empty timeline
149
+ rail / a map with no markers / an empty cross-tab / a field-less form — with no
150
+ request and no diagnostic anywhere. Spec-valid metadata rendering nothing is the
151
+ objectstack#4413 shape.
152
+
153
+ Composition follows objectstack#5576's landed semantics unchanged, through the
154
+ shared `ElementDataSourceGate` (no change to it or to the resolution layer): a
155
+ named saved view supplies the baseline, a key written on the component itself
156
+ overrides it, an explicit binding key overrides both, `filter` AND-combines
157
+ ("additional filter criteria" — a binding can narrow a view, never widen it), and
158
+ a `view` name that does not resolve renders a configuration error on every one of
159
+ these blocks instead of degrading to the object's full scope.
160
+
161
+ Each block maps **only** the keys it genuinely reads, which for this batch means
162
+ several keys stay deliberately unmapped rather than being parked somewhere
163
+ plausible:
164
+
165
+ - `object-gantt` and `object-map` take `object` / `filter` / `sort`; neither has a
166
+ row cap or a field-list read site.
167
+ - `object-pivot` takes `object` / `filter`; a cross-tab orders itself by its own
168
+ row/column grouping and cannot be computed over a truncated page.
169
+ - `object-timeline` takes `object` only — its fetch is
170
+ `find(objectName, { options: { $top: 100 } })`, with no filter/sort read site
171
+ at all, so a named view is error-checked and then contributes nothing.
172
+ - `embeddable-form` and `object-master-detail-form` take `object` only (the
173
+ parent object, in the master-detail case); a form that writes one record has no
174
+ collection query for `filter` / `sort` / `limit` to narrow.
175
+ - `record:line_items` takes `object` onto **`childObject`** — the collection it
176
+ actually lists — and nothing else: its query is the parent FK plus a fixed
177
+ `$top: 500`, and its `columns` are editable `GridColumn` objects rather than a
178
+ field-name projection a view could supply.
179
+
180
+ The per-block coverage table, including every residual gap named above, is in
181
+ `content/docs/guide/data-source.md`.
182
+
183
+ No behaviour change for a block that carries no `dataSource`: the binding-free
184
+ path returns the schema by reference, so nothing remounts and nothing refetches.
185
+
186
+ - 523be48: `object-timeline` and `record:line_items` now apply the filter / sort / row cap they are given, so a named `dataSource.view` narrows them instead of contributing nothing
187
+
188
+ These were the two residual gaps in objectstack#7121's per-block coverage table
189
+ (objectstack#7137). Both blocks are object-bound lists, both accepted the spec's
190
+ per-element `dataSource` binding, and neither had a read site for `filter` or
191
+ `sort` anywhere in its fetch:
192
+
193
+ - `object-timeline`'s entire query was
194
+ `find(objectName, { options: { $top: 100 } })`.
195
+ - `record:line_items`' was the parent FK plus a fixed `$top: 500`.
196
+
197
+ So `dataSource: { object, view: 'hot' }` resolved the view — a typo still reported
198
+ a configuration error, it never degraded into an unfiltered query — and then
199
+ dropped everything the view said. The rendered rows could be **wider than the view
200
+ they named**, silently, which is exactly the class of mistake AI-authored metadata
201
+ hides best: the page looks like it works. objectstack#7121 deliberately left the
202
+ keys unmapped and recorded the gap rather than writing composed values onto schema
203
+ keys nobody read; this closes it at the fetch instead.
204
+
205
+ What each block now reads:
206
+
207
+ - **`object-timeline`** — `$filter: schema.filter`,
208
+ `$orderby: convertSortToQueryParams(schema.sort)`, and
209
+ `$top: schema.limit ?? 100`, matching the form `object-gantt` / `object-map` /
210
+ `object-calendar` already use. Its registry mapping gains
211
+ `filter` / `sort` / `limit`; `columns` stays unmapped, because a timeline
212
+ projects the fields its `timeline` config names.
213
+ - **`record:line_items`** — the composed filter is **AND-combined** with the parent
214
+ relationship condition through `mergeFilterNodes`, never substituted for it, the
215
+ same way `record:related_list` composes its own since objectstack#7118: a
216
+ line-items panel is always scoped to the record it sits on, so an _additional_
217
+ criterion can only narrow this parent's children and can never surface another
218
+ parent's rows. `sort` becomes the load order and `limit` the row cap (default
219
+ 500). `columns` stays unmapped — here they are `GridColumn[]` driving an editable
220
+ grid, not a field-name projection, so a view's column list would be the wrong
221
+ _shape_ rather than merely a wider answer.
222
+
223
+ **Behaviour change worth knowing about:** the timeline's default window is now a
224
+ real cap. `{ options: { $top: 100 } }` nested the limit under a key that is not a
225
+ `QueryParams` field and that no adapter in this repo reads (`convertQueryParams`
226
+ maps `params.$top`), so the intended window never reached the wire and a timeline
227
+ over a large object fetched whatever the server chose to return. It is now sent as
228
+ `$top`, and authorable via `limit` or a view's `pagination.pageSize`.
229
+
230
+ `@object-ui/core` gains `convertSortToQueryParams`, the sort→`$orderby` lowering
231
+ the three sibling blocks each inline privately. It is shared rather than copied
232
+ twice more, and is slightly more faithful to the declared contract than those
233
+ copies: a sort entry that omits `order` means ascending instead of being dropped
234
+ (the string spelling `"amount"` already meant ascending in the same copies), and
235
+ nothing orderable yields `undefined` rather than a truthy empty `{}`. Migrating
236
+ the three existing copies onto it is objectstack#7148 and is not done here.
237
+
238
+ - Updated dependencies [794c497]
239
+ - Updated dependencies [993336f]
240
+ - Updated dependencies [f0a625a]
241
+ - Updated dependencies [b5980f4]
242
+ - Updated dependencies [8aad9fd]
243
+ - Updated dependencies [6719877]
244
+ - Updated dependencies [56ff091]
245
+ - Updated dependencies [7864f03]
246
+ - Updated dependencies [0cbdca8]
247
+ - Updated dependencies [d229dfa]
248
+ - Updated dependencies [ecae400]
249
+ - Updated dependencies [4bc6c23]
250
+ - Updated dependencies [d3e738a]
251
+ - Updated dependencies [c3b01a7]
252
+ - Updated dependencies [f5f8744]
253
+ - Updated dependencies [7ed3360]
254
+ - Updated dependencies [69becd2]
255
+ - Updated dependencies [5e52495]
256
+ - Updated dependencies [0fa5e4d]
257
+ - Updated dependencies [b750823]
258
+ - Updated dependencies [5bfaabd]
259
+ - Updated dependencies [e06810e]
260
+ - Updated dependencies [ab3ad4f]
261
+ - Updated dependencies [c2fd122]
262
+ - Updated dependencies [ac2139c]
263
+ - Updated dependencies [b14ab3a]
264
+ - Updated dependencies [e24d767]
265
+ - Updated dependencies [8c60819]
266
+ - Updated dependencies [aca561a]
267
+ - Updated dependencies [e64a52e]
268
+ - Updated dependencies [844d17f]
269
+ - Updated dependencies [48132f7]
270
+ - Updated dependencies [4dcd52a]
271
+ - Updated dependencies [42ae5c6]
272
+ - Updated dependencies [0ef9dfd]
273
+ - Updated dependencies [1d723e3]
274
+ - Updated dependencies [0109f54]
275
+ - Updated dependencies [7e5bb5d]
276
+ - Updated dependencies [fbc23e0]
277
+ - Updated dependencies [6d762da]
278
+ - Updated dependencies [e6fdbdc]
279
+ - Updated dependencies [54233b1]
280
+ - Updated dependencies [f9faa7d]
281
+ - Updated dependencies [97b63d7]
282
+ - Updated dependencies [6bb454a]
283
+ - Updated dependencies [523be48]
284
+ - Updated dependencies [7e2b7e9]
285
+ - Updated dependencies [33526fd]
286
+ - Updated dependencies [32413ec]
287
+ - Updated dependencies [c1e1e6b]
288
+ - @object-ui/components@17.4.0
289
+ - @object-ui/react@17.4.0
290
+ - @object-ui/core@17.4.0
291
+ - @object-ui/i18n@17.4.0
292
+ - @object-ui/types@17.4.0
293
+ - @object-ui/mobile@17.4.0
294
+
295
+ ## 17.3.0
296
+
297
+ ### Patch Changes
298
+
299
+ - Updated dependencies [18cd432]
300
+ - Updated dependencies [532cf8b]
301
+ - Updated dependencies [680080a]
302
+ - Updated dependencies [a7651e6]
303
+ - Updated dependencies [d915c47]
304
+ - Updated dependencies [b71fc92]
305
+ - Updated dependencies [65516ba]
306
+ - Updated dependencies [94c5b7c]
307
+ - Updated dependencies [ca0fa8f]
308
+ - Updated dependencies [34595eb]
309
+ - Updated dependencies [3889ffb]
310
+ - Updated dependencies [5781fb1]
311
+ - Updated dependencies [7e2406a]
312
+ - Updated dependencies [9e9e9a9]
313
+ - Updated dependencies [56409c2]
314
+ - Updated dependencies [042e09d]
315
+ - Updated dependencies [9cbcbf4]
316
+ - Updated dependencies [85c4c9c]
317
+ - Updated dependencies [fd54c3e]
318
+ - Updated dependencies [4eeb932]
319
+ - Updated dependencies [5c856ec]
320
+ - Updated dependencies [23018cc]
321
+ - Updated dependencies [53811d1]
322
+ - Updated dependencies [68b6a28]
323
+ - Updated dependencies [0554e88]
324
+ - Updated dependencies [d915c47]
325
+ - Updated dependencies [f44d872]
326
+ - Updated dependencies [28b2e65]
327
+ - Updated dependencies [509104a]
328
+ - Updated dependencies [825bbe3]
329
+ - Updated dependencies [6195841]
330
+ - Updated dependencies [5dd0127]
331
+ - Updated dependencies [06632e9]
332
+ - Updated dependencies [a415684]
333
+ - Updated dependencies [a4cff5b]
334
+ - Updated dependencies [175bd79]
335
+ - Updated dependencies [5af2852]
336
+ - Updated dependencies [f833d3a]
337
+ - Updated dependencies [a6ec93d]
338
+ - Updated dependencies [2a9513d]
339
+ - Updated dependencies [71be406]
340
+ - Updated dependencies [d22ae31]
341
+ - Updated dependencies [c7ed4c3]
342
+ - Updated dependencies [2409e1d]
343
+ - Updated dependencies [789fe3e]
344
+ - Updated dependencies [8d8094a]
345
+ - @object-ui/core@17.3.0
346
+ - @object-ui/components@17.3.0
347
+ - @object-ui/types@17.3.0
348
+ - @object-ui/i18n@17.3.0
349
+ - @object-ui/react@17.3.0
350
+ - @object-ui/mobile@17.3.0
351
+
3
352
  ## 17.2.0
4
353
 
5
354
  ### Minor Changes
@@ -1021,6 +1370,7 @@
1021
1370
  ### Patch Changes
1022
1371
 
1023
1372
  - 1b6dc64: fix: complete Tailwind v3→v4 migration cleanup
1373
+
1024
1374
  - Rename deprecated `flex-shrink-0` → `shrink-0` and `flex-grow-N` →
1025
1375
  `grow-N` (Tailwind v4 dropped the long-form aliases). Affects
1026
1376
  data-table, fields/index, FileField, ChatbotEnhanced,
@@ -1083,6 +1433,7 @@
1083
1433
  Library builds (vite lib mode) now externalize every non-relative import instead of bundling third-party CJS dependencies into the published dist. This avoids inlined `require("react")` / `require("react-dom")` calls that cause `Calling \`require\` for "react" in an environment that doesn't expose the \`require\` function` runtime errors when consumer apps re-bundle the published dist.
1084
1434
 
1085
1435
  Specifically fixes:
1436
+
1086
1437
  - `@object-ui/plugin-dashboard` no longer inlines `react-grid-layout` (and its transitive `react-draggable` / `react-resizable` CJS bundles). `react-grid-layout` is now declared as a peer dependency so consumers install a single ESM-friendly copy.
1087
1438
  - `@object-ui/components`, `@object-ui/plugin-calendar`, `@object-ui/plugin-charts`, `@object-ui/plugin-designer` no longer inline `react-i18next` / `i18next` / `use-sync-external-store` CJS shims.
1088
1439
  - All plugin packages now use a unified `external: (id) => !/^[./]/.test(id) && !id.startsWith(__dirname)` rule, ensuring future additions of CJS deps are automatically externalized.
@@ -1141,15 +1492,18 @@
1141
1492
  - b2be122: fix(mobile): round 2 — kanban readability, calendar default view, timeline dot clipping
1142
1493
 
1143
1494
  **Kanban**
1495
+
1144
1496
  - Remove `font-mono` from card titles, descriptions, column headers, and empty-state labels — CRM cards no longer render in a monospace font.
1145
1497
  - Constrain column body height (`max-h-full min-h-0` + `h-full` on the layout root) so `ScrollArea` activates and cards don't bleed past the viewport bottom.
1146
1498
  - Opportunistically derive `description` (e.g. `$60K · Acme Corp · @owner`) and up to two `badges` (priority/severity/industry/rating) in `ObjectKanban` when the schema/source omits them, giving mobile cards more context at a glance.
1147
1499
 
1148
1500
  **Calendar**
1501
+
1149
1502
  - `ObjectCalendar` previously hardcoded `view={schema.defaultView ?? 'month'}`, making the view-selector dropdown a no-op. Wire the `view` state through to the `<Calendar>` prop so user selection is respected.
1150
1503
  - On mobile (viewport < 768 px) coerce `day` defaults to `month` via a synchronous lazy initialiser and a resize/orientation effect — avoids the useless 24-hour empty-hour grid for date-only events.
1151
1504
 
1152
1505
  **Timeline**
1506
+
1153
1507
  - Add `ml-3` to the `<Timeline>` `<ol>` so the `absolute -left-3` marker dots are no longer clipped at the scroll-container edge.
1154
1508
 
1155
1509
  - Updated dependencies [a2d7023]
package/README.md CHANGED
@@ -75,17 +75,6 @@ const schema = {
75
75
  };
76
76
  ```
77
77
 
78
- <!-- release-metadata:v3.3.0 -->
79
-
80
- ## Compatibility
81
-
82
- - **React:** 18.x or 19.x
83
- - **Node.js:** ≥ 18
84
- - **TypeScript:** ≥ 5.0 (strict mode)
85
- - **`@objectstack/spec`:** ^3.3.0
86
- - **`@objectstack/client`:** ^3.3.0
87
- - **Tailwind CSS:** ≥ 3.4 (for packages with UI)
88
-
89
78
  ## Links
90
79
 
91
80
  - 📚 [Documentation](https://www.objectui.org/docs/plugins/plugin-timeline)
@@ -1,5 +1,15 @@
1
1
  import { default as React } from 'react';
2
2
  import { DataSource, TimelineSchema, ListViewTimelineConfig } from '@object-ui/types';
3
+ /**
4
+ * Rows fetched when the author declared no `limit`.
5
+ *
6
+ * The number is the one this component has always intended: before
7
+ * objectstack#7137 the fetch passed `{ options: { $top: 100 } }`, and `options`
8
+ * is not a `QueryParams` key — no adapter in this repo reads it, so the cap never
9
+ * reached the wire and the timeline fetched whatever the server chose to return.
10
+ * The window is now real, and authorable.
11
+ */
12
+ export declare const DEFAULT_TIMELINE_LIMIT = 100;
3
13
  export interface ObjectTimelineProps {
4
14
  schema: TimelineSchema & {
5
15
  objectName?: string;
@@ -9,6 +19,31 @@ export interface ObjectTimelineProps {
9
19
  * has always declared on it, and that this renderer now actually reads.
10
20
  */
11
21
  timeline?: ListViewTimelineConfig;
22
+ /**
23
+ * Query filter for the object fetch, in any shape `toFilterNode` accepts
24
+ * (spec `ViewFilterRule[]`, ObjectQL AST nodes, or a MongoDB-style object).
25
+ *
26
+ * Read here, not merged here: when a `dataSource` binding is present,
27
+ * `ElementDataSourceGate` has already AND-combined this key with the view's
28
+ * filter and the binding's own before the schema reaches this component
29
+ * (objectstack#7137) — the same single sink every other object-bound block
30
+ * composes through.
31
+ */
32
+ filter?: any[] | Record<string, any>;
33
+ /**
34
+ * Query ordering — the legacy `"name desc"` clause or the spec's
35
+ * `SortConfig[]`, both lowered through `convertSortToQueryParams`.
36
+ */
37
+ sort?: string | Array<{
38
+ field?: string;
39
+ order?: 'asc' | 'desc';
40
+ }>;
41
+ /**
42
+ * Row cap for the fetch. Defaults to {@link DEFAULT_TIMELINE_LIMIT}; a
43
+ * timeline renders one rail with no pagination control, so this is the
44
+ * author's window rather than a page size.
45
+ */
46
+ limit?: number;
12
47
  /** @deprecated Use timeline.titleField instead */
13
48
  titleField?: string;
14
49
  /** @deprecated Use timeline.startDateField instead */
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectTimeline.d.ts","sourceRoot":"","sources":["../src/ObjectTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAmD3F,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,GAAG;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB;;;;WAIG;QACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;QAClC,kDAAkD;QAClD,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,sDAAsD;QACtD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,sDAAsD;QACtD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,oDAAoD;QACpD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,oDAAoD;QACpD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,kDAAkD;QAClD,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,6CAA6C;QAC7C,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;QAE/D,OAAO,CAAC,EAAE;YACR,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAA;KACF,CAAC;IACF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACrC;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAyVxD,CAAA"}
1
+ {"version":3,"file":"ObjectTimeline.d.ts","sourceRoot":"","sources":["../src/ObjectTimeline.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AA8B3F;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAuB1C,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,GAAG;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB;;;;WAIG;QACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;QAClC;;;;;;;;;WASG;QACH,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACrC;;;WAGG;QACH,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;SAAE,CAAC,CAAC;QAClE;;;;WAIG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,kDAAkD;QAClD,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,sDAAsD;QACtD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,sDAAsD;QACtD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,oDAAoD;QACpD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,oDAAoD;QACpD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,kDAAkD;QAClD,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,6CAA6C;QAC7C,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;QAE/D,OAAO,CAAC,EAAE;YACR,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAA;KACF,CAAC;IACF,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CACrC;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA0WxD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,QAAA,MAAM,QAAQ,iHASZ,CAAA;AAGF,QAAA,MAAM,oBAAoB;;8EASxB,CAAA;AAEF,QAAA,MAAM,YAAY;;qHAShB,CAAA;AAGF,QAAA,MAAM,sBAAsB;;8EAiB3B,CAAA;AAED,KAAK,qBAAqB,GAAG,YAAY,CAAC,OAAO,sBAAsB,CAAC,CAAC,SAAS,CAAC,CAAA;AAEnF,QAAA,MAAM,cAAc;cAGN,qBAAqB;wCAUjC,CAAA;AAGF,QAAA,MAAM,eAAe,6GASnB,CAAA;AAGF,QAAA,MAAM,aAAa,qHASjB,CAAA;AAGF,QAAA,MAAM,YAAY,mHAShB,CAAA;AAGF,QAAA,MAAM,mBAAmB,yHASvB,CAAA;AAIF,QAAA,MAAM,kBAAkB,6GAStB,CAAA;AAGF,QAAA,MAAM,sBAAsB,6GAS1B,CAAA;AAIF,QAAA,MAAM,aAAa,6GASjB,CAAA;AAGF,QAAA,MAAM,mBAAmB,6GASvB,CAAA;AAGF,QAAA,MAAM,sBAAsB,6GAS1B,CAAA;AAGF,QAAA,MAAM,iBAAiB,6GASrB,CAAA;AAGF,QAAA,MAAM,gBAAgB,6GASpB,CAAA;AAGF,QAAA,MAAM,kBAAkB,6GAStB,CAAA;AAGF,QAAA,MAAM,gBAAgB;YAGV,MAAM;YACN,MAAM;cACJ,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM;wCA0BjE,CAAA;AAGF,QAAA,MAAM,uBAAuB,6GAS3B,CAAA;AAGF,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,GACxB,CAAA;AAGD,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAO5D,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,CAGhD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,QAAA,MAAM,QAAQ,iHASZ,CAAA;AAGF,QAAA,MAAM,oBAAoB;;8EASxB,CAAA;AAEF,QAAA,MAAM,YAAY;;qHAShB,CAAA;AAGF,QAAA,MAAM,sBAAsB;;8EAiB3B,CAAA;AAED,KAAK,qBAAqB,GAAG,YAAY,CAAC,OAAO,sBAAsB,CAAC,CAAC,SAAS,CAAC,CAAA;AAEnF,QAAA,MAAM,cAAc;cAGN,qBAAqB;wCAUjC,CAAA;AAGF,QAAA,MAAM,eAAe,6GASnB,CAAA;AAGF,QAAA,MAAM,aAAa,qHASjB,CAAA;AAGF,QAAA,MAAM,YAAY,mHAShB,CAAA;AAGF,QAAA,MAAM,mBAAmB,yHASvB,CAAA;AAIF,QAAA,MAAM,kBAAkB,6GAStB,CAAA;AAGF,QAAA,MAAM,sBAAsB,6GAS1B,CAAA;AAIF,QAAA,MAAM,aAAa,6GASjB,CAAA;AAGF,QAAA,MAAM,mBAAmB,6GASvB,CAAA;AAGF,QAAA,MAAM,sBAAsB,6GAS1B,CAAA;AAGF,QAAA,MAAM,iBAAiB,6GASrB,CAAA;AAGF,QAAA,MAAM,gBAAgB,6GASpB,CAAA;AAGF,QAAA,MAAM,kBAAkB,6GAStB,CAAA;AAGF,QAAA,MAAM,gBAAgB;YAGV,MAAM;YACN,MAAM;cACJ,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM;wCA0BjE,CAAA;AAGF,QAAA,MAAM,uBAAuB,6GAS3B,CAAA;AAGF,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,GACxB,CAAA;AAGD,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAiC5D,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,CAiBhD,CAAC"}
package/dist/index.js CHANGED
@@ -2,13 +2,30 @@ import * as e from "react";
2
2
  import { useCallback as t, useEffect as n, useMemo as r, useState as i } from "react";
3
3
  import { NavigationOverlay as a, cn as o, cva as s, renderChildren as c } from "@object-ui/components";
4
4
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
- import { ComponentRegistry as d, buildExpandFields as f, extractRecords as p } from "@object-ui/core";
6
- import { useDataScope as m, useNavigationOverlay as h, useObjectLabel as g, useSchemaContext as _ } from "@object-ui/react";
7
- import { usePullToRefresh as ee } from "@object-ui/mobile";
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";
8
9
  import { z as v } from "zod";
9
- import { createSafeTranslation as y } from "@object-ui/i18n";
10
- //#region src/renderer.tsx
11
- var b = /* @__PURE__ */ new Set([
10
+ //#region src/useTimelineTranslation.ts
11
+ var y = {
12
+ "timeline.bucket.overdue": "Overdue",
13
+ "timeline.bucket.today": "Today",
14
+ "timeline.bucket.tomorrow": "Tomorrow",
15
+ "timeline.bucket.thisWeek": "This week",
16
+ "timeline.bucket.nextWeek": "Next week",
17
+ "timeline.bucket.later": "Later",
18
+ "timeline.bucket.noDate": "No date",
19
+ "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
+ "timeline.scale.week": "Week {{n}}",
26
+ "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([
12
29
  "hour",
13
30
  "day",
14
31
  "week",
@@ -16,71 +33,72 @@ var b = /* @__PURE__ */ new Set([
16
33
  "quarter",
17
34
  "year"
18
35
  ]);
19
- function x(e) {
36
+ function w(e) {
20
37
  let t = e.scale ?? e.timeScale;
21
- return typeof t == "string" && b.has(t) ? t : "month";
38
+ return typeof t == "string" && C.has(t) ? t : "month";
22
39
  }
23
- function S(e, t, n) {
24
- let r = [], i = new Date(t), a = new Date(n);
25
- if (Number.isNaN(i.getTime()) || Number.isNaN(a.getTime()) || i > a) return r;
26
- let o = new Date(i);
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);
27
44
  switch (e) {
28
45
  case "hour":
29
- for (; o <= a;) r.push(o.toLocaleString("en-US", {
46
+ for (; c <= s;) a.push(c.toLocaleString(r, {
30
47
  month: "short",
31
48
  day: "numeric",
32
49
  hour: "numeric"
33
- })), o.setHours(o.getHours() + 1);
50
+ })), c.setHours(c.getHours() + 1);
34
51
  break;
35
52
  case "day":
36
- for (; o <= a;) r.push(o.toLocaleDateString("en-US", {
53
+ for (; c <= s;) a.push(c.toLocaleDateString(r, {
37
54
  month: "short",
38
55
  day: "numeric"
39
- })), o.setDate(o.getDate() + 1);
56
+ })), c.setDate(c.getDate() + 1);
40
57
  break;
41
58
  case "week": {
42
59
  let e = 1;
43
- for (; o <= a;) r.push(`Week ${e++}`), o.setDate(o.getDate() + 7);
60
+ for (; c <= s;) a.push(i("timeline.scale.week", { n: e++ })), c.setDate(c.getDate() + 7);
44
61
  break;
45
62
  }
46
63
  case "quarter":
47
- for (o.setMonth(Math.floor(o.getMonth() / 3) * 3, 1); o <= a;) r.push(`Q${Math.floor(o.getMonth() / 3) + 1} ${o.getFullYear()}`), o.setMonth(o.getMonth() + 3);
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);
48
68
  break;
49
69
  case "year":
50
- for (o.setMonth(0, 1); o <= a;) r.push(String(o.getFullYear())), o.setFullYear(o.getFullYear() + 1);
51
- break;
52
- default:
53
- for (; o <= a;) r.push(o.toLocaleDateString("en-US", {
54
- month: "short",
55
- year: "numeric"
56
- })), o.setMonth(o.getMonth() + 1);
70
+ for (c.setMonth(0, 1); c <= s;) a.push(String(c.getFullYear())), c.setFullYear(c.getFullYear() + 1);
57
71
  break;
72
+ default: for (; c <= s;) a.push(c.toLocaleDateString(r, {
73
+ month: "short",
74
+ year: "numeric"
75
+ })), c.setMonth(c.getMonth() + 1);
58
76
  }
59
- return r;
77
+ return a;
60
78
  }
61
- function C(e) {
79
+ function E(e) {
62
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()));
63
81
  return {
64
82
  minDate: new Date(n).toISOString().split("T")[0],
65
83
  maxDate: new Date(r).toISOString().split("T")[0]
66
84
  };
67
85
  }
68
- function w(e, t, n, r) {
86
+ function ae(e, t, n, r) {
69
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;
70
88
  return {
71
89
  start: c / s * 100,
72
90
  width: l / s * 100
73
91
  };
74
92
  }
75
- function T(e, t) {
76
- let n = new Date(e);
77
- return t === "short" ? n.toLocaleDateString() : t === "long" ? n.toLocaleDateString("en-US", {
93
+ function D(e, t, n) {
94
+ let r = new Date(e);
95
+ return t === "short" ? r.toLocaleDateString(n) : t === "long" ? r.toLocaleDateString(n, {
78
96
  year: "numeric",
79
97
  month: "long",
80
98
  day: "numeric"
81
- }) : n.toISOString().split("T")[0];
99
+ }) : r.toISOString().split("T")[0];
82
100
  }
83
- function E({ label: e, color: t }) {
101
+ function O({ label: e, color: t }) {
84
102
  let n = t ? {
85
103
  backgroundColor: `${t}22`,
86
104
  color: t,
@@ -92,7 +110,7 @@ function E({ label: e, color: t }) {
92
110
  children: e
93
111
  });
94
112
  }
95
- function D(e) {
113
+ function k(e) {
96
114
  let t = [];
97
115
  for (let n of e) {
98
116
  let e = n.group == null ? "" : String(n.group), r = t[t.length - 1];
@@ -103,14 +121,14 @@ function D(e) {
103
121
  }
104
122
  return t;
105
123
  }
106
- var O = ({ schema: e, className: t, ...n }) => {
107
- let { variant: r = "vertical", items: i = [], dateFormat: a = "short", onItemClick: s } = e;
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();
108
126
  if (r === "vertical") {
109
- let e = D(i), r = e.some((e) => e.key !== ""), d = (e, t) => {
127
+ let e = k(i), r = e.some((e) => e.key !== ""), f = (e, t) => {
110
128
  let n = e.color ? {
111
129
  backgroundColor: `${e.color}33`,
112
130
  borderColor: e.color
113
- } : void 0, r = e.time ? T(e.time, a) : e.startDate ? T(e.startDate, a) : "", i = e.endDate && e.endDate !== e.startDate ? T(e.endDate, a) : "", d = Array.isArray(e.meta) ? e.meta : [];
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 : [];
114
132
  return /* @__PURE__ */ u(I, {
115
133
  density: "compact",
116
134
  className: o(e.className, s && "cursor-pointer"),
@@ -135,9 +153,9 @@ var O = ({ schema: e, className: t, ...n }) => {
135
153
  className: "text-sm sm:text-base mb-1",
136
154
  children: e.title
137
155
  }),
138
- d.length > 0 && /* @__PURE__ */ l("div", {
156
+ f.length > 0 && /* @__PURE__ */ l("div", {
139
157
  className: "flex flex-wrap gap-1.5 mt-1 mb-1",
140
- children: d.map((e) => /* @__PURE__ */ l(E, {
158
+ children: f.map((e) => /* @__PURE__ */ l(O, {
141
159
  label: e.label,
142
160
  color: e.color
143
161
  }, e.key))
@@ -163,13 +181,13 @@ var O = ({ schema: e, className: t, ...n }) => {
163
181
  })]
164
182
  }), /* @__PURE__ */ l(P, {
165
183
  className: "mt-3",
166
- children: e.items.map((e, n) => d(e, `${t}-${n}`))
184
+ children: e.items.map((e, n) => f(e, `${t}-${n}`))
167
185
  })]
168
186
  }, `${e.key}-${t}`))
169
187
  }) : /* @__PURE__ */ l(P, {
170
188
  className: t,
171
189
  ...n,
172
- children: i.map((e, t) => d(e, t))
190
+ children: i.map((e, t) => f(e, t))
173
191
  });
174
192
  }
175
193
  if (r === "horizontal") return /* @__PURE__ */ l(U, {
@@ -191,7 +209,7 @@ var O = ({ schema: e, className: t, ...n }) => {
191
209
  children: [
192
210
  e.time && /* @__PURE__ */ l(V, {
193
211
  dateTime: e.time,
194
- children: T(e.time, a)
212
+ children: D(e.time, a, d)
195
213
  }),
196
214
  e.title && /* @__PURE__ */ l(B, { children: e.title }),
197
215
  e.description && /* @__PURE__ */ l(H, {
@@ -205,7 +223,7 @@ var O = ({ schema: e, className: t, ...n }) => {
205
223
  }, t))
206
224
  });
207
225
  if (r === "gantt") {
208
- let r = C(i), c = e.minDate || r.minDate, d = e.maxDate || r.maxDate, f = S(x(e), c, d);
226
+ let r = E(i), c = e.minDate || r.minDate, p = e.maxDate || r.maxDate, m = T(w(e), c, p, d, f);
209
227
  return /* @__PURE__ */ u(G, {
210
228
  className: o("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
211
229
  ...n,
@@ -213,11 +231,11 @@ var O = ({ schema: e, className: t, ...n }) => {
213
231
  className: "flex items-center px-2 sm:px-4 py-2 sm:py-3",
214
232
  children: /* @__PURE__ */ l("span", {
215
233
  className: "font-semibold text-xs sm:text-sm",
216
- children: e.rowLabel || "Items"
234
+ children: e.rowLabel || f("timeline.gantt.rowLabel")
217
235
  })
218
236
  }), /* @__PURE__ */ l(J, { children: /* @__PURE__ */ l("div", {
219
237
  className: "flex h-full",
220
- children: f.map((e, t) => /* @__PURE__ */ l("div", {
238
+ children: m.map((e, t) => /* @__PURE__ */ l("div", {
221
239
  className: "flex-1 px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center",
222
240
  children: e
223
241
  }, t))
@@ -232,13 +250,13 @@ var O = ({ schema: e, className: t, ...n }) => {
232
250
  children: i.map((e, t) => /* @__PURE__ */ l(Y, {
233
251
  className: "relative",
234
252
  children: (e.items || []).map((n, r) => {
235
- let i = w(n.startDate, n.endDate, c, d);
253
+ let i = ae(n.startDate, n.endDate, c, p);
236
254
  return /* @__PURE__ */ l(Z, {
237
255
  start: i.start,
238
256
  width: i.width,
239
257
  variant: n.variant || "default",
240
258
  onClick: () => s?.(n, e, t, r),
241
- title: `${n.title || ""}\n${T(n.startDate, a)} - ${T(n.endDate, a)}`,
259
+ title: `${n.title || ""}\n${D(n.startDate, a, d)} - ${D(n.endDate, a, d)}`,
242
260
  children: /* @__PURE__ */ l(Q, { children: n.title })
243
261
  }, r);
244
262
  })
@@ -249,7 +267,7 @@ var O = ({ schema: e, className: t, ...n }) => {
249
267
  }
250
268
  return null;
251
269
  };
252
- d.register("timeline", O, {
270
+ d.register("timeline", A, {
253
271
  namespace: "plugin-timeline",
254
272
  label: "Timeline",
255
273
  category: "data-display",
@@ -444,34 +462,22 @@ d.register("timeline", O, {
444
462
  }
445
463
  }
446
464
  });
447
- var k = y({
448
- "timeline.bucket.overdue": "Overdue",
449
- "timeline.bucket.today": "Today",
450
- "timeline.bucket.tomorrow": "Tomorrow",
451
- "timeline.bucket.thisWeek": "This week",
452
- "timeline.bucket.nextWeek": "Next week",
453
- "timeline.bucket.later": "Later",
454
- "timeline.bucket.noDate": "No date",
455
- "timeline.bucket.unassigned": "Unassigned",
456
- "timeline.relative.today": "Today",
457
- "timeline.relative.tomorrow": "Tomorrow",
458
- "timeline.relative.yesterday": "Yesterday",
459
- "timeline.relative.inDays": "In {{n}} days",
460
- "timeline.relative.daysAgo": "{{n}} days ago"
461
- }, "timeline.bucket.today"), A = {
465
+ //#endregion
466
+ //#region src/ObjectTimeline.tsx
467
+ var j = {
462
468
  fieldOptionLabel: (e, t, n, r) => r,
463
469
  translateOptions: (e, t, n) => n,
464
470
  fieldLabel: (e, t, n) => n
465
471
  };
466
- function j() {
467
- return g() ?? A;
472
+ function oe() {
473
+ return re() ?? j;
468
474
  }
469
475
  var M = v.object({
470
476
  title: v.string().optional(),
471
477
  date: v.string().optional(),
472
478
  description: v.string().optional(),
473
479
  variant: v.string().optional()
474
- }), te = v.object({
480
+ }), se = v.object({
475
481
  mapping: M.optional(),
476
482
  objectName: v.string().optional(),
477
483
  titleField: v.string().optional(),
@@ -489,65 +495,72 @@ var M = v.object({
489
495
  "quarter",
490
496
  "year"
491
497
  ]).optional()
492
- }), N = ({ schema: e, dataSource: o, className: s, onRowClick: c, onItemClick: d, ...g }) => {
493
- let [_, v] = i([]), [y, b] = i(() => {
494
- let t = Array.isArray(e.items) && e.items.length > 0, n = Array.isArray(g.data) && g.data.length > 0;
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;
495
501
  return !t && !n && !!e.objectName;
496
- }), [x, S] = i(null), [C, w] = i(0), [T, E] = i(null), D = e.timeline;
502
+ }), [v, y] = i(null), [b, x] = i(0), [C, w] = i(null), T = e.timeline;
497
503
  n(() => {
498
- let t = te.safeParse(e);
504
+ let t = se.safeParse(e);
499
505
  t.success || console.warn("[ObjectTimeline] Invalid timeline configuration:", t.error.format());
500
506
  }, [e]);
501
- let A = m(e.bind);
507
+ let E = te(e.bind);
502
508
  n(() => {
503
509
  let t = !0;
504
510
  return (async () => {
505
511
  if (!(!o || typeof o.getObjectSchema != "function" || !e.objectName)) try {
506
512
  let n = await o.getObjectSchema(e.objectName);
507
- t && E(n);
513
+ t && w(n);
508
514
  } catch (e) {
509
515
  console.warn("Failed to fetch object def for ObjectTimeline", e);
510
516
  }
511
517
  })(), () => {
512
518
  t = !1;
513
519
  };
514
- }, [e.objectName, o]), n(() => {
515
- e.objectName && !A && !e.items && !g.data ? (async () => {
520
+ }, [e.objectName, o]);
521
+ let ae = JSON.stringify(e.filter ?? null), D = JSON.stringify(e.sort ?? null);
522
+ n(() => {
523
+ e.objectName && !E && !e.items && !h.data ? (async () => {
516
524
  if (!o || typeof o.find != "function" || !e.objectName) {
517
- b(!1);
525
+ _(!1);
518
526
  return;
519
527
  }
520
- b(!0);
528
+ _(!0);
521
529
  try {
522
- let t = f(T?.fields), n = p(await o.find(e.objectName, {
523
- options: { $top: 100 },
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,
524
534
  ...t.length > 0 ? { $expand: t } : {}
525
- }));
526
- v(n);
535
+ }), r = m(n);
536
+ ee(r);
527
537
  } catch (e) {
528
- console.error(e), S(e);
538
+ console.error(e), y(e);
529
539
  } finally {
530
- b(!1);
540
+ _(!1);
531
541
  }
532
- })() : b(!1);
542
+ })() : _(!1);
533
543
  }, [
534
544
  e.objectName,
535
545
  o,
536
- A,
546
+ E,
537
547
  e.items,
538
- g.data,
548
+ h.data,
549
+ b,
539
550
  C,
540
- T
551
+ ae,
552
+ D,
553
+ e.limit
541
554
  ]);
542
- let M = g.data || A || _, { t: N } = k(), { fieldOptionLabel: P } = j(), F = D?.titleField ?? e.mapping?.title ?? e.titleField ?? "name", I = D?.startDateField ?? D?.dateField ?? e.mapping?.date ?? e.startDateField ?? e.dateField ?? "date", L = D?.endDateField ?? e.endDateField ?? I, R = e.mapping?.description ?? e.descriptionField ?? "description", z = e.mapping?.variant ?? "variant", B = D?.groupByField ?? e.groupByField, V = D?.colorField ?? e.colorField, H = r(() => {
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(() => {
543
556
  if (e.items) return e.items;
544
- if (!M || !Array.isArray(M)) return [];
545
- let t = T?.fields ?? {}, n = e.objectName || "", r = (e) => {
557
+ if (!O || !Array.isArray(O)) return [];
558
+ let t = C?.fields ?? {}, n = e.objectName || "", r = (e) => {
546
559
  if (!e || !t[e]?.options) return {};
547
560
  let n = {};
548
561
  for (let r of t[e].options) r && r.value != null && (n[String(r.value)] = r);
549
562
  return n;
550
- }, i = r(V), a = Array.isArray(D?.metaFields) ? D.metaFields.filter((e) => typeof e == "string" && e) : ["status", "priority"].filter((e) => t[e]), o = {};
563
+ }, i = r(R), a = Array.isArray(T?.metaFields) ? T.metaFields.filter((e) => typeof e == "string" && e) : ["status", "priority"].filter((e) => t[e]), o = {};
551
564
  for (let e of a) o[e] = r(e);
552
565
  let s = (e) => {
553
566
  if (e == null || e === "") return;
@@ -559,11 +572,11 @@ var M = v.object({
559
572
  if (t == null || t === "") return null;
560
573
  let i = r[String(t)];
561
574
  return {
562
- label: i?.label ? P(n, e, String(t), i.label) : String(t),
575
+ label: i?.label ? j(n, e, String(t), i.label) : String(t),
563
576
  color: i?.color
564
577
  };
565
- }, l = M.map((e) => {
566
- let t = e[I], r = e[L], i = V ? e[V] : void 0, l = B ? e[B] : void 0, u = [];
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 = [];
567
580
  if (n) for (let t of a) {
568
581
  let n = c(t, e[t], o[t] || {});
569
582
  n && u.push({
@@ -573,12 +586,12 @@ var M = v.object({
573
586
  });
574
587
  }
575
588
  return {
576
- title: e[F],
589
+ title: e[M],
577
590
  time: t,
578
591
  startDate: t,
579
592
  endDate: r,
580
- description: e[R],
581
- variant: e[z] || "default",
593
+ description: e[F],
594
+ variant: e[I] || "default",
582
595
  color: s(i),
583
596
  group: l,
584
597
  meta: u,
@@ -587,17 +600,17 @@ var M = v.object({
587
600
  });
588
601
  l.sort((e, t) => (e.startDate ? new Date(e.startDate).getTime() : Infinity) - (t.startDate ? new Date(t.startDate).getTime() : Infinity));
589
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) => {
590
- if (!e) return N("timeline.bucket.noDate");
603
+ if (!e) return k("timeline.bucket.noDate");
591
604
  let t = d(new Date(e));
592
- return Number.isNaN(t) ? N("timeline.bucket.noDate") : t < f ? N("timeline.bucket.overdue") : t === f ? N("timeline.bucket.today") : t === f + p ? N("timeline.bucket.tomorrow") : N(t < m ? "timeline.bucket.thisWeek" : t < h ? "timeline.bucket.nextWeek" : "timeline.bucket.later");
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");
593
606
  };
594
- if (B && !l.every((e) => e.group == null || e.group === "")) {
595
- let e = r(B);
607
+ if (L && !l.every((e) => e.group == null || e.group === "")) {
608
+ let e = r(L);
596
609
  return l.map((t) => {
597
- let n = c(B, t.group, e);
610
+ let n = c(L, t.group, e);
598
611
  return {
599
612
  ...t,
600
- group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : N("timeline.bucket.unassigned")
613
+ group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : k("timeline.bucket.unassigned")
601
614
  };
602
615
  });
603
616
  }
@@ -607,43 +620,43 @@ var M = v.object({
607
620
  }));
608
621
  }, [
609
622
  e.items,
610
- M,
611
- T,
623
+ O,
624
+ C,
612
625
  e.objectName,
626
+ M,
627
+ N,
628
+ P,
613
629
  F,
614
630
  I,
615
- L,
616
631
  R,
617
- z,
618
- V,
619
- B,
620
- N,
621
- P
622
- ]), { ref: U, isRefreshing: W, pullDistance: G } = ee({
623
- onRefresh: t(async () => {
624
- w((e) => e + 1);
625
- }, []),
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,
626
639
  enabled: !!e.objectName && !!o
627
- }), K = h({
640
+ }), W = ne({
628
641
  navigation: e.navigation,
629
642
  objectName: e.objectName,
630
643
  onRowClick: c ?? d
631
- }), q = D?.scale ?? e.scale, J = {
644
+ }), G = T?.scale ?? e.scale, K = {
632
645
  ...e,
633
- items: H || [],
646
+ items: z || [],
634
647
  className: s || e.className,
635
- ...q ? { timeScale: q } : {},
648
+ ...G ? { timeScale: G } : {},
636
649
  onItemClick: (e) => {
637
650
  let t = e._data || e;
638
- K.handleClick(t), d?.(t);
651
+ W.handleClick(t), d?.(t);
639
652
  }
640
653
  };
641
- return x ? /* @__PURE__ */ u("div", {
654
+ return v ? /* @__PURE__ */ u("div", {
642
655
  className: "p-4 text-destructive",
643
656
  "data-testid": "timeline-error",
644
657
  role: "alert",
645
- children: ["Error loading timeline: ", x.message]
646
- }) : y && (!H || H.length === 0) ? /* @__PURE__ */ u("div", {
658
+ children: ["Error loading timeline: ", v.message]
659
+ }) : re && (!z || z.length === 0) ? /* @__PURE__ */ u("div", {
647
660
  className: "flex flex-col h-full min-h-[200px] p-4 gap-3",
648
661
  "data-testid": "timeline-loading",
649
662
  role: "status",
@@ -666,17 +679,17 @@ var M = v.object({
666
679
  })]
667
680
  }, e))]
668
681
  }) : /* @__PURE__ */ u("div", {
669
- ref: U,
682
+ ref: V,
670
683
  className: "relative overflow-auto h-full min-w-0",
671
684
  children: [
672
- G > 0 && /* @__PURE__ */ l("div", {
685
+ U > 0 && /* @__PURE__ */ l("div", {
673
686
  className: "flex items-center justify-center text-xs text-muted-foreground",
674
- style: { height: G },
675
- children: W ? "Refreshing…" : "Pull to refresh"
687
+ style: { height: U },
688
+ children: H ? "Refreshing…" : "Pull to refresh"
676
689
  }),
677
- /* @__PURE__ */ l(O, { schema: J }),
678
- K.isOverlay && /* @__PURE__ */ l(a, {
679
- ...K,
690
+ /* @__PURE__ */ l(A, { schema: K }),
691
+ W.isOverlay && /* @__PURE__ */ l(a, {
692
+ ...W,
680
693
  title: "Timeline Item",
681
694
  children: (e) => /* @__PURE__ */ l("div", {
682
695
  className: "space-y-3",
@@ -825,12 +838,23 @@ var Q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
825
838
  ...t
826
839
  }));
827
840
  Q.displayName = "TimelineGanttBarContent";
828
- var $ = ({ schema: e, ...t }) => {
841
+ var ce = {
842
+ filter: !0,
843
+ sort: !0,
844
+ limit: "limit"
845
+ }, $ = ({ schema: e, ...t }) => {
829
846
  let { dataSource: n } = _() || {};
830
- return /* @__PURE__ */ l(N, {
847
+ return /* @__PURE__ */ l(ee, {
831
848
  schema: e,
849
+ mapping: ce,
832
850
  dataSource: n,
833
- ...t
851
+ testId: "object-timeline",
852
+ errorTitle: "This timeline’s data source could not be resolved",
853
+ children: (e) => /* @__PURE__ */ l(N, {
854
+ schema: e,
855
+ dataSource: n,
856
+ ...t
857
+ })
834
858
  });
835
859
  };
836
860
  d.register("object-timeline", $, {
@@ -873,4 +897,4 @@ d.register("object-timeline", $, {
873
897
  }]
874
898
  });
875
899
  //#endregion
876
- export { N as ObjectTimeline, $ as ObjectTimelineRenderer, b 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, O as TimelineRenderer, V as TimelineTime, B as TimelineTitle, S as generateTimeScaleHeaders, x as resolveTimelineScale, F as timelineItemVariants, L as timelineMarkerVariants };
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 };
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/components"),require("react/jsx-runtime"),require("@object-ui/core"),require("@object-ui/react"),require("@object-ui/mobile"),require("zod"),require("@object-ui/i18n")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/components`,`react/jsx-runtime`,`@object-ui/core`,`@object-ui/react`,`@object-ui/mobile`,`zod`,`@object-ui/i18n`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginTimeline={},e.React,e.ObjectUIComponents,e.react_jsx_runtime,e.ObjectUICore,e.ObjectUIReact,e.ObjectUIMobile,e.zod,e._object_ui_i18n))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule?u(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var g=new Set([`hour`,`day`,`week`,`month`,`quarter`,`year`]);function _(e){let t=e.scale??e.timeScale;return typeof t==`string`&&g.has(t)?t:`month`}function v(e,t,n){let r=[],i=new Date(t),a=new Date(n);if(Number.isNaN(i.getTime())||Number.isNaN(a.getTime())||i>a)return r;let o=new Date(i);switch(e){case`hour`:for(;o<=a;)r.push(o.toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`})),o.setHours(o.getHours()+1);break;case`day`:for(;o<=a;)r.push(o.toLocaleDateString(`en-US`,{month:`short`,day:`numeric`})),o.setDate(o.getDate()+1);break;case`week`:{let e=1;for(;o<=a;)r.push(`Week ${e++}`),o.setDate(o.getDate()+7);break}case`quarter`:for(o.setMonth(Math.floor(o.getMonth()/3)*3,1);o<=a;)r.push(`Q${Math.floor(o.getMonth()/3)+1} ${o.getFullYear()}`),o.setMonth(o.getMonth()+3);break;case`year`:for(o.setMonth(0,1);o<=a;)r.push(String(o.getFullYear())),o.setFullYear(o.getFullYear()+1);break;default:for(;o<=a;)r.push(o.toLocaleDateString(`en-US`,{month:`short`,year:`numeric`})),o.setMonth(o.getMonth()+1);break}return r}function y(e){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()));return{minDate:new Date(n).toISOString().split(`T`)[0],maxDate:new Date(r).toISOString().split(`T`)[0]}}function b(e,t,n,r){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;return{start:c/s*100,width:l/s*100}}function x(e,t){let n=new Date(e);return t===`short`?n.toLocaleDateString():t===`long`?n.toLocaleDateString(`en-US`,{year:`numeric`,month:`long`,day:`numeric`}):n.toISOString().split(`T`)[0]}function S({label:e,color:t}){let i=t?{backgroundColor:`${t}22`,color:t,borderColor:`${t}55`}:void 0;return(0,r.jsx)(`span`,{className:(0,n.cn)(`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium`,!t&&`bg-muted text-muted-foreground border-transparent`),style:i,children:e})}function C(e){let t=[];for(let n of e){let e=n.group==null?``:String(n.group),r=t[t.length-1];r&&r.key===e?r.items.push(n):t.push({key:e,items:[n]})}return t}var w=({schema:e,className:t,...i})=>{let{variant:a=`vertical`,items:o=[],dateFormat:s=`short`,onItemClick:c}=e;if(a===`vertical`){let e=C(o),a=e.some(e=>e.key!==``),l=(e,t)=>{let i=e.color?{backgroundColor:`${e.color}33`,borderColor:e.color}:void 0,a=e.time?x(e.time,s):e.startDate?x(e.startDate,s):``,o=e.endDate&&e.endDate!==e.startDate?x(e.endDate,s):``,l=Array.isArray(e.meta)?e.meta:[];return(0,r.jsxs)(N,{density:`compact`,className:(0,n.cn)(e.className,c&&`cursor-pointer`),onClick:()=>c?.(e),children:[(0,r.jsx)(F,{variant:e.color?`default`:e.variant||`default`,style:i,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(I,{children:[(a||o)&&(0,r.jsxs)(R,{dateTime:e.time||e.startDate,className:`!mb-1 text-xs`,children:[a,o&&(0,r.jsxs)(`span`,{className:`text-muted-foreground/70`,children:[` → `,o]})]}),e.title&&(0,r.jsx)(L,{className:`text-sm sm:text-base mb-1`,children:e.title}),l.length>0&&(0,r.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mt-1 mb-1`,children:l.map(e=>(0,r.jsx)(S,{label:e.label,color:e.color},e.key))}),e.description&&(0,r.jsx)(z,{className:`text-sm text-muted-foreground line-clamp-2 sm:line-clamp-none`,children:e.description}),e.content&&(0,n.renderChildren)(e.content)]})]},t)};return a?(0,r.jsx)(`div`,{className:(0,n.cn)(`px-4 sm:px-6 py-2`,t),...i,children:e.map((e,t)=>(0,r.jsxs)(`section`,{className:`mb-4`,children:[(0,r.jsxs)(`header`,{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`,children:[(0,r.jsx)(`span`,{children:e.key}),(0,r.jsx)(`span`,{className:`ml-2 text-muted-foreground/60 font-normal normal-case`,children:e.items.length})]}),(0,r.jsx)(j,{className:`mt-3`,children:e.items.map((e,n)=>l(e,`${t}-${n}`))})]},`${e.key}-${t}`))}):(0,r.jsx)(j,{className:t,...i,children:o.map((e,t)=>l(e,t))})}if(a===`horizontal`)return(0,r.jsx)(B,{className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),...i,children:o.map((e,t)=>(0,r.jsxs)(V,{className:(0,n.cn)(e.className,c&&`cursor-pointer`),onClick:()=>c?.(e),children:[(0,r.jsxs)(`div`,{className:`flex flex-col items-center`,children:[(0,r.jsx)(F,{variant:e.variant||`default`,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(`div`,{className:`mt-4 text-center`,children:[e.time&&(0,r.jsx)(R,{dateTime:e.time,children:x(e.time,s)}),e.title&&(0,r.jsx)(L,{children:e.title}),e.description&&(0,r.jsx)(z,{className:`text-center line-clamp-2 sm:line-clamp-none`,children:e.description}),e.content&&(0,n.renderChildren)(e.content)]})]}),t<o.length-1&&(0,r.jsx)(`div`,{className:`absolute left-full w-16 border-t-2 border-gray-200 top-3`})]},t))});if(a===`gantt`){let a=y(o),l=e.minDate||a.minDate,u=e.maxDate||a.maxDate,d=v(_(e),l,u);return(0,r.jsxs)(H,{className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),...i,children:[(0,r.jsxs)(U,{children:[(0,r.jsx)(W,{className:`flex items-center px-2 sm:px-4 py-2 sm:py-3`,children:(0,r.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:e.rowLabel||`Items`})}),(0,r.jsx)(G,{children:(0,r.jsx)(`div`,{className:`flex h-full`,children:d.map((e,t)=>(0,r.jsx)(`div`,{className:`flex-1 px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center`,children:e},t))})})]}),(0,r.jsx)(`div`,{children:(0,r.jsxs)(`div`,{className:`flex`,children:[(0,r.jsx)(W,{children:o.map((e,t)=>(0,r.jsx)(K,{children:(0,r.jsx)(q,{title:e.label,className:`truncate`,children:e.label})},t))}),(0,r.jsx)(G,{className:`relative`,children:o.map((e,t)=>(0,r.jsx)(K,{className:`relative`,children:(e.items||[]).map((n,i)=>{let a=b(n.startDate,n.endDate,l,u);return(0,r.jsx)(J,{start:a.start,width:a.width,variant:n.variant||`default`,onClick:()=>c?.(n,e,t,i),title:`${n.title||``}\n${x(n.startDate,s)} - ${x(n.endDate,s)}`,children:(0,r.jsx)(Y,{children:n.title})},i)})},t))})]})})]})}return null};i.ComponentRegistry.register(`timeline`,w,{namespace:`plugin-timeline`,label:`Timeline`,category:`data-display`,inputs:[{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],label:`Timeline Variant`,defaultValue:`vertical`},{name:`items`,type:`array`,label:`Timeline Items`,description:`For vertical/horizontal: Array of { time, title, description, variant, icon, content }. For gantt: Array of { label, items: [{ title, startDate, endDate, variant }] }`},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`],label:`Date Format`,defaultValue:`short`},{name:`timeScale`,type:`enum`,enum:[`day`,`week`,`month`],label:`Time Scale (Gantt only)`,defaultValue:`month`},{name:`rowLabel`,type:`string`,label:`Row Label (Gantt only)`,defaultValue:`Items`},{name:`minDate`,type:`string`,label:`Min Date (Gantt only)`,description:`Override auto-calculated min date (YYYY-MM-DD)`},{name:`maxDate`,type:`string`,label:`Max Date (Gantt only)`,description:`Override auto-calculated max date (YYYY-MM-DD)`},{name:`className`,type:`string`,label:`CSS Class`}],defaultProps:{variant:`vertical`,dateFormat:`short`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`,icon:`🚀`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`,icon:`🎨`},{time:`2024-03-15`,title:`Beta Release`,description:`Released beta version to testers`,variant:`warning`,icon:`⚡`},{time:`2024-04-01`,title:`Launch`,description:`Official product launch`,variant:`success`,icon:`🎉`}]},examples:{vertical:{variant:`vertical`,dateFormat:`long`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`}]},horizontal:{variant:`horizontal`,dateFormat:`short`,items:[{time:`2024-01-01`,title:`Q1`,description:`First quarter`,variant:`default`},{time:`2024-04-01`,title:`Q2`,description:`Second quarter`,variant:`info`},{time:`2024-07-01`,title:`Q3`,description:`Third quarter`,variant:`warning`},{time:`2024-10-01`,title:`Q4`,description:`Fourth quarter`,variant:`success`}]},gantt:{variant:`gantt`,dateFormat:`short`,timeScale:`month`,rowLabel:`Projects`,items:[{label:`Backend Development`,items:[{title:`API Design`,startDate:`2024-01-01`,endDate:`2024-01-31`,variant:`success`},{title:`Implementation`,startDate:`2024-02-01`,endDate:`2024-03-31`,variant:`info`}]},{label:`Frontend Development`,items:[{title:`UI Design`,startDate:`2024-01-15`,endDate:`2024-02-15`,variant:`warning`},{title:`Component Dev`,startDate:`2024-02-15`,endDate:`2024-04-15`,variant:`default`}]},{label:`Testing`,items:[{title:`QA Phase`,startDate:`2024-03-01`,endDate:`2024-04-30`,variant:`danger`}]}]}}});var T=(0,c.createSafeTranslation)({"timeline.bucket.overdue":`Overdue`,"timeline.bucket.today":`Today`,"timeline.bucket.tomorrow":`Tomorrow`,"timeline.bucket.thisWeek":`This week`,"timeline.bucket.nextWeek":`Next week`,"timeline.bucket.later":`Later`,"timeline.bucket.noDate":`No date`,"timeline.bucket.unassigned":`Unassigned`,"timeline.relative.today":`Today`,"timeline.relative.tomorrow":`Tomorrow`,"timeline.relative.yesterday":`Yesterday`,"timeline.relative.inDays":`In {{n}} days`,"timeline.relative.daysAgo":`{{n}} days ago`},`timeline.bucket.today`),E={fieldOptionLabel:(e,t,n,r)=>r,translateOptions:(e,t,n)=>n,fieldLabel:(e,t,n)=>n};function D(){return(0,a.useObjectLabel)()??E}var O=s.z.object({title:s.z.string().optional(),date:s.z.string().optional(),description:s.z.string().optional(),variant:s.z.string().optional()}),k=s.z.object({mapping:O.optional(),objectName:s.z.string().optional(),titleField:s.z.string().optional(),dateField:s.z.string().optional(),startDateField:s.z.string().optional(),endDateField:s.z.string().optional(),descriptionField:s.z.string().optional(),groupByField:s.z.string().optional(),colorField:s.z.string().optional(),scale:s.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).optional()}),A=({schema:e,dataSource:s,className:c,onRowClick:l,onItemClick:u,...d})=>{let[f,p]=(0,t.useState)([]),[m,h]=(0,t.useState)(()=>{let t=Array.isArray(e.items)&&e.items.length>0,n=Array.isArray(d.data)&&d.data.length>0;return!t&&!n&&!!e.objectName}),[g,_]=(0,t.useState)(null),[v,y]=(0,t.useState)(0),[b,x]=(0,t.useState)(null),S=e.timeline;(0,t.useEffect)(()=>{let t=k.safeParse(e);t.success||console.warn(`[ObjectTimeline] Invalid timeline configuration:`,t.error.format())},[e]);let C=(0,a.useDataScope)(e.bind);(0,t.useEffect)(()=>{let t=!0;return(async()=>{if(!(!s||typeof s.getObjectSchema!=`function`||!e.objectName))try{let n=await s.getObjectSchema(e.objectName);t&&x(n)}catch(e){console.warn(`Failed to fetch object def for ObjectTimeline`,e)}})(),()=>{t=!1}},[e.objectName,s]),(0,t.useEffect)(()=>{e.objectName&&!C&&!e.items&&!d.data?(async()=>{if(!s||typeof s.find!=`function`||!e.objectName){h(!1);return}h(!0);try{let t=(0,i.buildExpandFields)(b?.fields),n=(0,i.extractRecords)(await s.find(e.objectName,{options:{$top:100},...t.length>0?{$expand:t}:{}}));p(n)}catch(e){console.error(e),_(e)}finally{h(!1)}})():h(!1)},[e.objectName,s,C,e.items,d.data,v,b]);let E=d.data||C||f,{t:O}=T(),{fieldOptionLabel:A}=D(),j=S?.titleField??e.mapping?.title??e.titleField??`name`,M=S?.startDateField??S?.dateField??e.mapping?.date??e.startDateField??e.dateField??`date`,N=S?.endDateField??e.endDateField??M,P=e.mapping?.description??e.descriptionField??`description`,F=e.mapping?.variant??`variant`,I=S?.groupByField??e.groupByField,L=S?.colorField??e.colorField,R=(0,t.useMemo)(()=>{if(e.items)return e.items;if(!E||!Array.isArray(E))return[];let t=b?.fields??{},n=e.objectName||``,r=e=>{if(!e||!t[e]?.options)return{};let n={};for(let r of t[e].options)r&&r.value!=null&&(n[String(r.value)]=r);return n},i=r(L),a=Array.isArray(S?.metaFields)?S.metaFields.filter(e=>typeof e==`string`&&e):[`status`,`priority`].filter(e=>t[e]),o={};for(let e of a)o[e]=r(e);let s=e=>{if(e==null||e===``)return;let t=i[String(e)];if(t?.color)return String(t.color);let n=String(e);if(/^#([0-9a-f]{3}){1,2}$/i.test(n)||n.startsWith(`rgb`)||n.startsWith(`hsl`))return n},c=(e,t,r)=>{if(t==null||t===``)return null;let i=r[String(t)];return{label:i?.label?A(n,e,String(t),i.label):String(t),color:i?.color}},l=E.map(e=>{let t=e[M],r=e[N],i=L?e[L]:void 0,l=I?e[I]:void 0,u=[];if(n)for(let t of a){let n=c(t,e[t],o[t]||{});n&&u.push({key:t,label:n.label,color:n.color})}return{title:e[j],time:t,startDate:t,endDate:r,description:e[P],variant:e[F]||`default`,color:s(i),group:l,meta:u,_data:e}});l.sort((e,t)=>(e.startDate?new Date(e.startDate).getTime():1/0)-(t.startDate?new Date(t.startDate).getTime():1/0));let u=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=>{if(!e)return O(`timeline.bucket.noDate`);let t=d(new Date(e));return Number.isNaN(t)?O(`timeline.bucket.noDate`):t<f?O(`timeline.bucket.overdue`):t===f?O(`timeline.bucket.today`):t===f+p?O(`timeline.bucket.tomorrow`):O(t<m?`timeline.bucket.thisWeek`:t<h?`timeline.bucket.nextWeek`:`timeline.bucket.later`)};if(I&&!l.every(e=>e.group==null||e.group===``)){let e=r(I);return l.map(t=>{let n=c(I,t.group,e);return{...t,group:n?n.label:t.group!=null&&t.group!==``?String(t.group):O(`timeline.bucket.unassigned`)}})}return l.map(e=>({...e,group:g(e.startDate)}))},[e.items,E,b,e.objectName,j,M,N,P,F,L,I,O,A]),{ref:z,isRefreshing:B,pullDistance:V}=(0,o.usePullToRefresh)({onRefresh:(0,t.useCallback)(async()=>{y(e=>e+1)},[]),enabled:!!e.objectName&&!!s}),H=(0,a.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:l??u}),U=S?.scale??e.scale,W={...e,items:R||[],className:c||e.className,...U?{timeScale:U}:{},onItemClick:e=>{let t=e._data||e;H.handleClick(t),u?.(t)}};return g?(0,r.jsxs)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-error`,role:`alert`,children:[`Error loading timeline: `,g.message]}):m&&(!R||R.length===0)?(0,r.jsxs)(`div`,{className:`flex flex-col h-full min-h-[200px] p-4 gap-3`,"data-testid":`timeline-loading`,role:`status`,"aria-live":`polite`,"aria-busy":`true`,children:[(0,r.jsx)(`span`,{className:`sr-only`,children:`Loading timeline…`}),[0,1,2,3].map(e=>(0,r.jsxs)(`div`,{className:`flex items-start gap-3`,style:{opacity:Math.max(.3,1-e*.18)},children:[(0,r.jsx)(`div`,{className:`h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0`}),(0,r.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,r.jsx)(`div`,{className:`h-4 w-1/3 rounded bg-muted/70 animate-pulse`}),(0,r.jsx)(`div`,{className:`h-3 w-2/3 rounded bg-muted/50 animate-pulse`})]})]},e))]}):(0,r.jsxs)(`div`,{ref:z,className:`relative overflow-auto h-full min-w-0`,children:[V>0&&(0,r.jsx)(`div`,{className:`flex items-center justify-center text-xs text-muted-foreground`,style:{height:V},children:B?`Refreshing…`:`Pull to refresh`}),(0,r.jsx)(w,{schema:W}),H.isOverlay&&(0,r.jsx)(n.NavigationOverlay,{...H,title:`Timeline Item`,children:e=>(0,r.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,r.jsxs)(`div`,{className:`flex flex-col`,children:[(0,r.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,r.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},j=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`ol`,{ref:i,className:(0,n.cn)(`relative ml-3 border-l border-gray-200`,e),...t}));j.displayName=`Timeline`;var M=(0,n.cva)(`ml-6`,{variants:{density:{default:`mb-10`,compact:`mb-3`,comfortable:`mb-6`}},defaultVariants:{density:`default`}}),N=t.forwardRef(({className:e,density:t,...i},a)=>(0,r.jsx)(`li`,{ref:a,className:(0,n.cn)(M({density:t}),e),...i}));N.displayName=`TimelineItem`;var P=(0,n.cva)(`absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center`,{variants:{variant:{default:`bg-blue-200 border-blue-400`,success:`bg-emerald-200 border-emerald-500`,warning:`bg-amber-200 border-amber-500`,danger:`bg-red-200 border-red-500`,info:`bg-purple-200 border-purple-500`,todo:`bg-slate-200 border-slate-400`,"in-progress":`bg-blue-200 border-blue-500`,done:`bg-emerald-200 border-emerald-500`}},defaultVariants:{variant:`default`}}),F=t.forwardRef(({className:e,variant:t=`default`,...i},a)=>(0,r.jsx)(`div`,{ref:a,className:(0,n.cn)(P({variant:t}),e),...i}));F.displayName=`TimelineMarker`;var I=t.forwardRef(({className:e,...t},n)=>(0,r.jsx)(`div`,{ref:n,className:e,...t}));I.displayName=`TimelineContent`;var L=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`h3`,{ref:i,className:(0,n.cn)(`font-semibold text-lg mb-1`,e),...t}));L.displayName=`TimelineTitle`;var R=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`time`,{ref:i,className:(0,n.cn)(`text-sm font-normal text-gray-500 mb-2 block`,e),...t}));R.displayName=`TimelineTime`;var z=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`p`,{ref:i,className:(0,n.cn)(`text-base text-gray-700`,e),...t}));z.displayName=`TimelineDescription`;var B=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative flex overflow-x-auto py-8`,e),...t}));B.displayName=`TimelineHorizontal`;var V=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`shrink-0 w-64 relative`,e),...t}));V.displayName=`TimelineHorizontalItem`;var H=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative w-full border rounded-lg overflow-hidden`,e),...t}));H.displayName=`TimelineGantt`;var U=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex border-b bg-gray-50`,e),...t}));U.displayName=`TimelineGanttHeader`;var W=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`w-48 border-r bg-white`,e),...t}));W.displayName=`TimelineGanttRowLabels`;var G=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex-1 overflow-x-auto`,e),...t}));G.displayName=`TimelineGanttGrid`;var K=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex items-center border-b min-h-12`,e),...t}));K.displayName=`TimelineGanttRow`;var q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-4 py-2 font-medium text-sm truncate`,e),...t}));q.displayName=`TimelineGanttLabel`;var J=t.forwardRef(({className:e,start:t=0,width:i=100,variant:a=`default`,...o},s)=>(0,r.jsx)(`div`,{ref:s,className:(0,n.cn)(`absolute h-8 rounded-md transition-colors cursor-pointer`,{default:`bg-blue-500 hover:bg-blue-600`,success:`bg-green-500 hover:bg-green-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,danger:`bg-red-500 hover:bg-red-600`,info:`bg-purple-500 hover:bg-purple-600`}[a],e),style:{left:`${t}%`,width:`${i}%`},...o}));J.displayName=`TimelineGanttBar`;var Y=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-2 py-1 text-white text-xs font-medium truncate`,e),...t}));Y.displayName=`TimelineGanttBarContent`;var X=({schema:e,...t})=>{let{dataSource:n}=(0,a.useSchemaContext)()||{};return(0,r.jsx)(A,{schema:e,dataSource:n,...t})};i.ComponentRegistry.register(`object-timeline`,X,{namespace:`plugin-timeline`,label:`Object Timeline`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],defaultValue:`vertical`}]}),i.ComponentRegistry.register(`timeline`,X,{namespace:`view`,label:`Timeline View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],defaultValue:`vertical`}]}),e.ObjectTimeline=A,e.ObjectTimelineRenderer=X,e.TIMELINE_SCALES=g,e.Timeline=j,e.TimelineContent=I,e.TimelineDescription=z,e.TimelineGantt=H,e.TimelineGanttBar=J,e.TimelineGanttBarContent=Y,e.TimelineGanttGrid=G,e.TimelineGanttHeader=U,e.TimelineGanttLabel=q,e.TimelineGanttRow=K,e.TimelineGanttRowLabels=W,e.TimelineHorizontal=B,e.TimelineHorizontalItem=V,e.TimelineItem=N,e.TimelineMarker=F,e.TimelineRenderer=w,e.TimelineTime=R,e.TimelineTitle=L,e.generateTimeScaleHeaders=v,e.resolveTimelineScale=_,e.timelineItemVariants=M,e.timelineMarkerVariants=P});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/components"),require("react/jsx-runtime"),require("@object-ui/core"),require("@object-ui/i18n"),require("@object-ui/react"),require("@object-ui/mobile"),require("zod")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/components`,`react/jsx-runtime`,`@object-ui/core`,`@object-ui/i18n`,`@object-ui/react`,`@object-ui/mobile`,`zod`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginTimeline={},e.React,e.ObjectUIComponents,e.react_jsx_runtime,e.ObjectUICore,e._object_ui_i18n,e.ObjectUIReact,e.ObjectUIMobile,e.zod))})(this,function(e,t,n,r,i,a,o,s,c){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var l=Object.create,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,f=Object.getOwnPropertyNames,p=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,h=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=f(t),a=0,o=i.length,s;a<o;a++)s=i[a],!m.call(e,s)&&s!==n&&u(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=d(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:l(p(e)),h(t||!e||!e.__esModule||!m.call(e,`default`)?u(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var g={"timeline.bucket.overdue":`Overdue`,"timeline.bucket.today":`Today`,"timeline.bucket.tomorrow":`Tomorrow`,"timeline.bucket.thisWeek":`This week`,"timeline.bucket.nextWeek":`Next week`,"timeline.bucket.later":`Later`,"timeline.bucket.noDate":`No date`,"timeline.bucket.unassigned":`Unassigned`,"timeline.relative.today":`Today`,"timeline.relative.tomorrow":`Tomorrow`,"timeline.relative.yesterday":`Yesterday`,"timeline.relative.inDays":`In {{n}} days`,"timeline.relative.daysAgo":`{{n}} days ago`,"timeline.scale.week":`Week {{n}}`,"timeline.scale.quarter":`Q{{quarter}} {{year}}`,"timeline.gantt.rowLabel":`Items`},_=`timeline.bucket.today`,v=(e,t)=>Object.entries(t??{}).reduce((e,[t,n])=>e.split(`{{${t}}}`).join(String(n)),g[e]||e),y=(0,a.createSafeTranslation)(g,_),b=new Set([`hour`,`day`,`week`,`month`,`quarter`,`year`]);function x(e){let t=e.scale??e.timeScale;return typeof t==`string`&&b.has(t)?t:`month`}function S(e,t,n,r=`en`,i=v){let a=[],o=new Date(t),s=new Date(n);if(Number.isNaN(o.getTime())||Number.isNaN(s.getTime())||o>s)return a;let c=new Date(o);switch(e){case`hour`:for(;c<=s;)a.push(c.toLocaleString(r,{month:`short`,day:`numeric`,hour:`numeric`})),c.setHours(c.getHours()+1);break;case`day`:for(;c<=s;)a.push(c.toLocaleDateString(r,{month:`short`,day:`numeric`})),c.setDate(c.getDate()+1);break;case`week`:{let e=1;for(;c<=s;)a.push(i(`timeline.scale.week`,{n:e++})),c.setDate(c.getDate()+7);break}case`quarter`:for(c.setMonth(Math.floor(c.getMonth()/3)*3,1);c<=s;)a.push(i(`timeline.scale.quarter`,{quarter:Math.floor(c.getMonth()/3)+1,year:c.getFullYear()})),c.setMonth(c.getMonth()+3);break;case`year`:for(c.setMonth(0,1);c<=s;)a.push(String(c.getFullYear())),c.setFullYear(c.getFullYear()+1);break;default:for(;c<=s;)a.push(c.toLocaleDateString(r,{month:`short`,year:`numeric`})),c.setMonth(c.getMonth()+1)}return a}function C(e){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()));return{minDate:new Date(n).toISOString().split(`T`)[0],maxDate:new Date(r).toISOString().split(`T`)[0]}}function w(e,t,n,r){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;return{start:c/s*100,width:l/s*100}}function T(e,t,n){let r=new Date(e);return t===`short`?r.toLocaleDateString(n):t===`long`?r.toLocaleDateString(n,{year:`numeric`,month:`long`,day:`numeric`}):r.toISOString().split(`T`)[0]}function E({label:e,color:t}){let i=t?{backgroundColor:`${t}22`,color:t,borderColor:`${t}55`}:void 0;return(0,r.jsx)(`span`,{className:(0,n.cn)(`inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium`,!t&&`bg-muted text-muted-foreground border-transparent`),style:i,children:e})}function D(e){let t=[];for(let n of e){let e=n.group==null?``:String(n.group),r=t[t.length-1];r&&r.key===e?r.items.push(n):t.push({key:e,items:[n]})}return t}var O=({schema:e,className:t,...i})=>{let{variant:o=`vertical`,items:s=[],dateFormat:c=`short`,onItemClick:l}=e,u=(0,a.useDisplayLocale)(),{t:d}=y();if(o===`vertical`){let e=D(s),a=e.some(e=>e.key!==``),o=(e,t)=>{let i=e.color?{backgroundColor:`${e.color}33`,borderColor:e.color}:void 0,a=e.time?T(e.time,c,u):e.startDate?T(e.startDate,c,u):``,o=e.endDate&&e.endDate!==e.startDate?T(e.endDate,c,u):``,s=Array.isArray(e.meta)?e.meta:[];return(0,r.jsxs)(I,{density:`compact`,className:(0,n.cn)(e.className,l&&`cursor-pointer`),onClick:()=>l?.(e),children:[(0,r.jsx)(R,{variant:e.color?`default`:e.variant||`default`,style:i,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(z,{children:[(a||o)&&(0,r.jsxs)(V,{dateTime:e.time||e.startDate,className:`!mb-1 text-xs`,children:[a,o&&(0,r.jsxs)(`span`,{className:`text-muted-foreground/70`,children:[` → `,o]})]}),e.title&&(0,r.jsx)(B,{className:`text-sm sm:text-base mb-1`,children:e.title}),s.length>0&&(0,r.jsx)(`div`,{className:`flex flex-wrap gap-1.5 mt-1 mb-1`,children:s.map(e=>(0,r.jsx)(E,{label:e.label,color:e.color},e.key))}),e.description&&(0,r.jsx)(H,{className:`text-sm text-muted-foreground line-clamp-2 sm:line-clamp-none`,children:e.description}),e.content&&(0,n.renderChildren)(e.content)]})]},t)};return a?(0,r.jsx)(`div`,{className:(0,n.cn)(`px-4 sm:px-6 py-2`,t),...i,children:e.map((e,t)=>(0,r.jsxs)(`section`,{className:`mb-4`,children:[(0,r.jsxs)(`header`,{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`,children:[(0,r.jsx)(`span`,{children:e.key}),(0,r.jsx)(`span`,{className:`ml-2 text-muted-foreground/60 font-normal normal-case`,children:e.items.length})]}),(0,r.jsx)(P,{className:`mt-3`,children:e.items.map((e,n)=>o(e,`${t}-${n}`))})]},`${e.key}-${t}`))}):(0,r.jsx)(P,{className:t,...i,children:s.map((e,t)=>o(e,t))})}if(o===`horizontal`)return(0,r.jsx)(U,{className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),...i,children:s.map((e,t)=>(0,r.jsxs)(W,{className:(0,n.cn)(e.className,l&&`cursor-pointer`),onClick:()=>l?.(e),children:[(0,r.jsxs)(`div`,{className:`flex flex-col items-center`,children:[(0,r.jsx)(R,{variant:e.variant||`default`,children:e.icon&&(0,r.jsx)(`span`,{className:`text-xs`,children:e.icon})}),(0,r.jsxs)(`div`,{className:`mt-4 text-center`,children:[e.time&&(0,r.jsx)(V,{dateTime:e.time,children:T(e.time,c,u)}),e.title&&(0,r.jsx)(B,{children:e.title}),e.description&&(0,r.jsx)(H,{className:`text-center line-clamp-2 sm:line-clamp-none`,children:e.description}),e.content&&(0,n.renderChildren)(e.content)]})]}),t<s.length-1&&(0,r.jsx)(`div`,{className:`absolute left-full w-16 border-t-2 border-gray-200 top-3`})]},t))});if(o===`gantt`){let a=C(s),o=e.minDate||a.minDate,f=e.maxDate||a.maxDate,p=S(x(e),o,f,u,d);return(0,r.jsxs)(G,{className:(0,n.cn)(`overflow-x-auto [-webkit-overflow-scrolling:touch]`,t),...i,children:[(0,r.jsxs)(K,{children:[(0,r.jsx)(q,{className:`flex items-center px-2 sm:px-4 py-2 sm:py-3`,children:(0,r.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:e.rowLabel||d(`timeline.gantt.rowLabel`)})}),(0,r.jsx)(J,{children:(0,r.jsx)(`div`,{className:`flex h-full`,children:p.map((e,t)=>(0,r.jsx)(`div`,{className:`flex-1 px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center`,children:e},t))})})]}),(0,r.jsx)(`div`,{children:(0,r.jsxs)(`div`,{className:`flex`,children:[(0,r.jsx)(q,{children:s.map((e,t)=>(0,r.jsx)(Y,{children:(0,r.jsx)(X,{title:e.label,className:`truncate`,children:e.label})},t))}),(0,r.jsx)(J,{className:`relative`,children:s.map((e,t)=>(0,r.jsx)(Y,{className:`relative`,children:(e.items||[]).map((n,i)=>{let a=w(n.startDate,n.endDate,o,f);return(0,r.jsx)(Z,{start:a.start,width:a.width,variant:n.variant||`default`,onClick:()=>l?.(n,e,t,i),title:`${n.title||``}\n${T(n.startDate,c,u)} - ${T(n.endDate,c,u)}`,children:(0,r.jsx)(Q,{children:n.title})},i)})},t))})]})})]})}return null};i.ComponentRegistry.register(`timeline`,O,{namespace:`plugin-timeline`,label:`Timeline`,category:`data-display`,inputs:[{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],label:`Timeline Variant`,defaultValue:`vertical`},{name:`items`,type:`array`,label:`Timeline Items`,description:`For vertical/horizontal: Array of { time, title, description, variant, icon, content }. For gantt: Array of { label, items: [{ title, startDate, endDate, variant }] }`},{name:`dateFormat`,type:`enum`,enum:[`short`,`long`,`iso`],label:`Date Format`,defaultValue:`short`},{name:`timeScale`,type:`enum`,enum:[`day`,`week`,`month`],label:`Time Scale (Gantt only)`,defaultValue:`month`},{name:`rowLabel`,type:`string`,label:`Row Label (Gantt only)`,defaultValue:`Items`},{name:`minDate`,type:`string`,label:`Min Date (Gantt only)`,description:`Override auto-calculated min date (YYYY-MM-DD)`},{name:`maxDate`,type:`string`,label:`Max Date (Gantt only)`,description:`Override auto-calculated max date (YYYY-MM-DD)`},{name:`className`,type:`string`,label:`CSS Class`}],defaultProps:{variant:`vertical`,dateFormat:`short`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`,icon:`🚀`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`,icon:`🎨`},{time:`2024-03-15`,title:`Beta Release`,description:`Released beta version to testers`,variant:`warning`,icon:`⚡`},{time:`2024-04-01`,title:`Launch`,description:`Official product launch`,variant:`success`,icon:`🎉`}]},examples:{vertical:{variant:`vertical`,dateFormat:`long`,items:[{time:`2024-01-15`,title:`Project Started`,description:`Kickoff meeting and initial planning`,variant:`success`},{time:`2024-02-01`,title:`First Milestone`,description:`Completed initial design phase`,variant:`info`}]},horizontal:{variant:`horizontal`,dateFormat:`short`,items:[{time:`2024-01-01`,title:`Q1`,description:`First quarter`,variant:`default`},{time:`2024-04-01`,title:`Q2`,description:`Second quarter`,variant:`info`},{time:`2024-07-01`,title:`Q3`,description:`Third quarter`,variant:`warning`},{time:`2024-10-01`,title:`Q4`,description:`Fourth quarter`,variant:`success`}]},gantt:{variant:`gantt`,dateFormat:`short`,timeScale:`month`,rowLabel:`Projects`,items:[{label:`Backend Development`,items:[{title:`API Design`,startDate:`2024-01-01`,endDate:`2024-01-31`,variant:`success`},{title:`Implementation`,startDate:`2024-02-01`,endDate:`2024-03-31`,variant:`info`}]},{label:`Frontend Development`,items:[{title:`UI Design`,startDate:`2024-01-15`,endDate:`2024-02-15`,variant:`warning`},{title:`Component Dev`,startDate:`2024-02-15`,endDate:`2024-04-15`,variant:`default`}]},{label:`Testing`,items:[{title:`QA Phase`,startDate:`2024-03-01`,endDate:`2024-04-30`,variant:`danger`}]}]}}});var k={fieldOptionLabel:(e,t,n,r)=>r,translateOptions:(e,t,n)=>n,fieldLabel:(e,t,n)=>n};function A(){return(0,o.useObjectLabel)()??k}var j=c.z.object({title:c.z.string().optional(),date:c.z.string().optional(),description:c.z.string().optional(),variant:c.z.string().optional()}),M=c.z.object({mapping:j.optional(),objectName:c.z.string().optional(),titleField:c.z.string().optional(),dateField:c.z.string().optional(),startDateField:c.z.string().optional(),endDateField:c.z.string().optional(),descriptionField:c.z.string().optional(),groupByField:c.z.string().optional(),colorField:c.z.string().optional(),scale:c.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).optional()}),N=({schema:e,dataSource:a,className:c,onRowClick:l,onItemClick:u,...d})=>{let[f,p]=(0,t.useState)([]),[m,h]=(0,t.useState)(()=>{let t=Array.isArray(e.items)&&e.items.length>0,n=Array.isArray(d.data)&&d.data.length>0;return!t&&!n&&!!e.objectName}),[g,_]=(0,t.useState)(null),[v,b]=(0,t.useState)(0),[x,S]=(0,t.useState)(null),C=e.timeline;(0,t.useEffect)(()=>{let t=M.safeParse(e);t.success||console.warn(`[ObjectTimeline] Invalid timeline configuration:`,t.error.format())},[e]);let w=(0,o.useDataScope)(e.bind);(0,t.useEffect)(()=>{let t=!0;return(async()=>{if(!(!a||typeof a.getObjectSchema!=`function`||!e.objectName))try{let n=await a.getObjectSchema(e.objectName);t&&S(n)}catch(e){console.warn(`Failed to fetch object def for ObjectTimeline`,e)}})(),()=>{t=!1}},[e.objectName,a]);let T=JSON.stringify(e.filter??null),E=JSON.stringify(e.sort??null);(0,t.useEffect)(()=>{e.objectName&&!w&&!e.items&&!d.data?(async()=>{if(!a||typeof a.find!=`function`||!e.objectName){h(!1);return}h(!0);try{let t=(0,i.buildExpandFields)(x?.fields),n=await a.find(e.objectName,{$filter:e.filter,$orderby:(0,i.convertSortToQueryParams)(e.sort),$top:e.limit??100,...t.length>0?{$expand:t}:{}}),r=(0,i.extractRecords)(n);p(r)}catch(e){console.error(e),_(e)}finally{h(!1)}})():h(!1)},[e.objectName,a,w,e.items,d.data,v,x,T,E,e.limit]);let D=d.data||w||f,{t:k}=y(),{fieldOptionLabel:j}=A(),N=C?.titleField??e.mapping?.title??e.titleField??`name`,P=C?.startDateField??C?.dateField??e.mapping?.date??e.startDateField??e.dateField??`date`,F=C?.endDateField??e.endDateField??P,I=e.mapping?.description??e.descriptionField??`description`,L=e.mapping?.variant??`variant`,R=C?.groupByField??e.groupByField,z=C?.colorField??e.colorField,B=(0,t.useMemo)(()=>{if(e.items)return e.items;if(!D||!Array.isArray(D))return[];let t=x?.fields??{},n=e.objectName||``,r=e=>{if(!e||!t[e]?.options)return{};let n={};for(let r of t[e].options)r&&r.value!=null&&(n[String(r.value)]=r);return n},i=r(z),a=Array.isArray(C?.metaFields)?C.metaFields.filter(e=>typeof e==`string`&&e):[`status`,`priority`].filter(e=>t[e]),o={};for(let e of a)o[e]=r(e);let s=e=>{if(e==null||e===``)return;let t=i[String(e)];if(t?.color)return String(t.color);let n=String(e);if(/^#([0-9a-f]{3}){1,2}$/i.test(n)||n.startsWith(`rgb`)||n.startsWith(`hsl`))return n},c=(e,t,r)=>{if(t==null||t===``)return null;let i=r[String(t)];return{label:i?.label?j(n,e,String(t),i.label):String(t),color:i?.color}},l=D.map(e=>{let t=e[P],r=e[F],i=z?e[z]:void 0,l=R?e[R]:void 0,u=[];if(n)for(let t of a){let n=c(t,e[t],o[t]||{});n&&u.push({key:t,label:n.label,color:n.color})}return{title:e[N],time:t,startDate:t,endDate:r,description:e[I],variant:e[L]||`default`,color:s(i),group:l,meta:u,_data:e}});l.sort((e,t)=>(e.startDate?new Date(e.startDate).getTime():1/0)-(t.startDate?new Date(t.startDate).getTime():1/0));let u=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=>{if(!e)return k(`timeline.bucket.noDate`);let t=d(new Date(e));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`)};if(R&&!l.every(e=>e.group==null||e.group===``)){let e=r(R);return l.map(t=>{let n=c(R,t.group,e);return{...t,group:n?n.label:t.group!=null&&t.group!==``?String(t.group):k(`timeline.bucket.unassigned`)}})}return l.map(e=>({...e,group:g(e.startDate)}))},[e.items,D,x,e.objectName,N,P,F,I,L,z,R,k,j]),V=(0,t.useCallback)(async()=>{b(e=>e+1)},[]),{ref:H,isRefreshing:U,pullDistance:W}=(0,s.usePullToRefresh)({onRefresh:V,enabled:!!e.objectName&&!!a}),G=(0,o.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:l??u}),K=C?.scale??e.scale,q={...e,items:B||[],className:c||e.className,...K?{timeScale:K}:{},onItemClick:e=>{let t=e._data||e;G.handleClick(t),u?.(t)}};return g?(0,r.jsxs)(`div`,{className:`p-4 text-destructive`,"data-testid":`timeline-error`,role:`alert`,children:[`Error loading timeline: `,g.message]}):m&&(!B||B.length===0)?(0,r.jsxs)(`div`,{className:`flex flex-col h-full min-h-[200px] p-4 gap-3`,"data-testid":`timeline-loading`,role:`status`,"aria-live":`polite`,"aria-busy":`true`,children:[(0,r.jsx)(`span`,{className:`sr-only`,children:`Loading timeline…`}),[0,1,2,3].map(e=>(0,r.jsxs)(`div`,{className:`flex items-start gap-3`,style:{opacity:Math.max(.3,1-e*.18)},children:[(0,r.jsx)(`div`,{className:`h-3 w-3 rounded-full bg-muted/70 animate-pulse mt-1.5 shrink-0`}),(0,r.jsxs)(`div`,{className:`flex-1 space-y-2`,children:[(0,r.jsx)(`div`,{className:`h-4 w-1/3 rounded bg-muted/70 animate-pulse`}),(0,r.jsx)(`div`,{className:`h-3 w-2/3 rounded bg-muted/50 animate-pulse`})]})]},e))]}):(0,r.jsxs)(`div`,{ref:H,className:`relative overflow-auto h-full min-w-0`,children:[W>0&&(0,r.jsx)(`div`,{className:`flex items-center justify-center text-xs text-muted-foreground`,style:{height:W},children:U?`Refreshing…`:`Pull to refresh`}),(0,r.jsx)(O,{schema:q}),G.isOverlay&&(0,r.jsx)(n.NavigationOverlay,{...G,title:`Timeline Item`,children:e=>(0,r.jsx)(`div`,{className:`space-y-3`,children:Object.entries(e).map(([e,t])=>(0,r.jsxs)(`div`,{className:`flex flex-col`,children:[(0,r.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wide`,children:e.replace(/_/g,` `)}),(0,r.jsx)(`span`,{className:`text-sm`,children:String(t??`—`)})]},e))})})]})},P=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`ol`,{ref:i,className:(0,n.cn)(`relative ml-3 border-l border-gray-200`,e),...t}));P.displayName=`Timeline`;var F=(0,n.cva)(`ml-6`,{variants:{density:{default:`mb-10`,compact:`mb-3`,comfortable:`mb-6`}},defaultVariants:{density:`default`}}),I=t.forwardRef(({className:e,density:t,...i},a)=>(0,r.jsx)(`li`,{ref:a,className:(0,n.cn)(F({density:t}),e),...i}));I.displayName=`TimelineItem`;var L=(0,n.cva)(`absolute -left-3 w-6 h-6 rounded-full border-2 flex items-center justify-center`,{variants:{variant:{default:`bg-blue-200 border-blue-400`,success:`bg-emerald-200 border-emerald-500`,warning:`bg-amber-200 border-amber-500`,danger:`bg-red-200 border-red-500`,info:`bg-purple-200 border-purple-500`,todo:`bg-slate-200 border-slate-400`,"in-progress":`bg-blue-200 border-blue-500`,done:`bg-emerald-200 border-emerald-500`}},defaultVariants:{variant:`default`}}),R=t.forwardRef(({className:e,variant:t=`default`,...i},a)=>(0,r.jsx)(`div`,{ref:a,className:(0,n.cn)(L({variant:t}),e),...i}));R.displayName=`TimelineMarker`;var z=t.forwardRef(({className:e,...t},n)=>(0,r.jsx)(`div`,{ref:n,className:e,...t}));z.displayName=`TimelineContent`;var B=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`h3`,{ref:i,className:(0,n.cn)(`font-semibold text-lg mb-1`,e),...t}));B.displayName=`TimelineTitle`;var V=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`time`,{ref:i,className:(0,n.cn)(`text-sm font-normal text-gray-500 mb-2 block`,e),...t}));V.displayName=`TimelineTime`;var H=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`p`,{ref:i,className:(0,n.cn)(`text-base text-gray-700`,e),...t}));H.displayName=`TimelineDescription`;var U=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative flex overflow-x-auto py-8`,e),...t}));U.displayName=`TimelineHorizontal`;var W=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`shrink-0 w-64 relative`,e),...t}));W.displayName=`TimelineHorizontalItem`;var G=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`relative w-full border rounded-lg overflow-hidden`,e),...t}));G.displayName=`TimelineGantt`;var K=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex border-b bg-gray-50`,e),...t}));K.displayName=`TimelineGanttHeader`;var q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`w-48 border-r bg-white`,e),...t}));q.displayName=`TimelineGanttRowLabels`;var J=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex-1 overflow-x-auto`,e),...t}));J.displayName=`TimelineGanttGrid`;var Y=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`flex items-center border-b min-h-12`,e),...t}));Y.displayName=`TimelineGanttRow`;var X=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-4 py-2 font-medium text-sm truncate`,e),...t}));X.displayName=`TimelineGanttLabel`;var Z=t.forwardRef(({className:e,start:t=0,width:i=100,variant:a=`default`,...o},s)=>(0,r.jsx)(`div`,{ref:s,className:(0,n.cn)(`absolute h-8 rounded-md transition-colors cursor-pointer`,{default:`bg-blue-500 hover:bg-blue-600`,success:`bg-green-500 hover:bg-green-600`,warning:`bg-yellow-500 hover:bg-yellow-600`,danger:`bg-red-500 hover:bg-red-600`,info:`bg-purple-500 hover:bg-purple-600`}[a],e),style:{left:`${t}%`,width:`${i}%`},...o}));Z.displayName=`TimelineGanttBar`;var Q=t.forwardRef(({className:e,...t},i)=>(0,r.jsx)(`div`,{ref:i,className:(0,n.cn)(`px-2 py-1 text-white text-xs font-medium truncate`,e),...t}));Q.displayName=`TimelineGanttBarContent`;var ee={filter:!0,sort:!0,limit:`limit`},$=({schema:e,...t})=>{let{dataSource:n}=(0,o.useSchemaContext)()||{};return(0,r.jsx)(o.ElementDataSourceGate,{schema:e,mapping:ee,dataSource:n,testId:`object-timeline`,errorTitle:`This timeline’s data source could not be resolved`,children:e=>(0,r.jsx)(N,{schema:e,dataSource:n,...t})})};i.ComponentRegistry.register(`object-timeline`,$,{namespace:`plugin-timeline`,label:`Object Timeline`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],defaultValue:`vertical`}]}),i.ComponentRegistry.register(`timeline`,$,{namespace:`view`,label:`Timeline View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`variant`,type:`enum`,enum:[`vertical`,`horizontal`,`gantt`],defaultValue:`vertical`}]}),e.ObjectTimeline=N,e.ObjectTimelineRenderer=$,e.TIMELINE_SCALES=b,e.Timeline=P,e.TimelineContent=z,e.TimelineDescription=H,e.TimelineGantt=G,e.TimelineGanttBar=Z,e.TimelineGanttBarContent=Q,e.TimelineGanttGrid=J,e.TimelineGanttHeader=K,e.TimelineGanttLabel=X,e.TimelineGanttRow=Y,e.TimelineGanttRowLabels=q,e.TimelineHorizontal=U,e.TimelineHorizontalItem=W,e.TimelineItem=I,e.TimelineMarker=R,e.TimelineRenderer=O,e.TimelineTime=V,e.TimelineTitle=B,e.generateTimeScaleHeaders=S,e.resolveTimelineScale=x,e.timelineItemVariants=F,e.timelineMarkerVariants=L});
@@ -1,4 +1,5 @@
1
1
  import { TimelineSchema } from '@object-ui/types';
2
+ import { TimelineTranslate } from './useTimelineTranslation';
2
3
  /**
3
4
  * ObjectUI
4
5
  * Copyright (c) 2024-present ObjectStack Inc.
@@ -30,8 +31,25 @@ export declare function resolveTimelineScale(schema: {
30
31
  * scale produces a non-empty header row — `hour` / `quarter` / `year` used to
31
32
  * fall through the month/week/day chain and return `[]`, blanking the axis
32
33
  * (#2942). Exported for the spec-parity test.
34
+ *
35
+ * `locale` is threaded in rather than read here: this is a pure function, and
36
+ * the session's locale lives behind a hook (#4513). The three `Intl` branches
37
+ * below used to pass a literal `'en-US'`, so a fully Chinese timeline rendered
38
+ * an English axis. The default is `'en'` — the same concrete last resort
39
+ * `useDisplayLocale()` falls back to, and byte-identical to the retired
40
+ * `'en-US'` at all three sites — so the existing 3-argument call sites keep
41
+ * producing exactly what they produced before.
42
+ *
43
+ * `t` is threaded on the same seam and for the same reason (#4520). The two are
44
+ * different kinds of dependency and each covers what the other cannot: a locale
45
+ * TAG formats a date, a TRANSLATION spells a word. The `week` and `quarter`
46
+ * branches never touched `Intl`, so #4513 left them reading `Week 1` / `Q3
47
+ * 2026` on an axis that had just become Chinese. Its default is the package's
48
+ * own defaults table, which is what the channel serves with no `I18nProvider`
49
+ * mounted, so 3- and 4-argument call sites keep producing byte-identical
50
+ * English.
33
51
  */
34
- export declare function generateTimeScaleHeaders(scale: string, minDate: string, maxDate: string): string[];
52
+ export declare function generateTimeScaleHeaders(scale: string, minDate: string, maxDate: string, locale?: string, t?: TimelineTranslate): string[];
35
53
  export declare const TimelineRenderer: ({ schema, className, ...props }: {
36
54
  schema: TimelineSchema;
37
55
  className?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAuBvD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAE9C,CAAC;AAEH;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAG7F;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoDlG;AA4FD,eAAO,MAAM,gBAAgB,GAAI,iCAAiC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,6BA+NjI,CAAC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsBvD,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAGlC;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAE9C,CAAC;AAEH;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAG7F;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAa,EACrB,CAAC,GAAE,iBAA4C,GAC9C,MAAM,EAAE,CAyDV;AAsGD,eAAO,MAAM,gBAAgB,GAAI,iCAAiC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,6BAsPjI,CAAC"}
@@ -12,6 +12,31 @@
12
12
  * embed) without an I18nProvider on the React tree.
13
13
  */
14
14
  export declare const TIMELINE_DEFAULT_TRANSLATIONS: Record<string, string>;
15
+ /**
16
+ * The translate fn shape this package threads into its pure helpers.
17
+ *
18
+ * `generateTimeScaleHeaders` is a module-level function and cannot host a hook,
19
+ * so the component reads the channel and passes `t` down — the same seam
20
+ * objectui#4513 opened for the resolved `locale` string, for the same reason.
21
+ */
22
+ export type TimelineTranslate = (key: string, params?: Record<string, unknown>) => string;
23
+ /**
24
+ * The English last resort for call sites that have no `t` to hand: the exported
25
+ * helper's default parameter, and nothing else.
26
+ *
27
+ * It is the same lookup `createSafeTranslation` serves on a provider-less host,
28
+ * spelled here because that one is a hook and this is a pure function. Both
29
+ * halves are deliberate mirrors of `useSafeTranslation.ts` and must stay that
30
+ * way — a divergence would only ever show up on hosts with no `I18nProvider`,
31
+ * where we are least likely to see it:
32
+ *
33
+ * - `||` (not `??`) for the chain, so an empty string falls through to the
34
+ * key exactly as the hook's `defaults[key] || …` chain does.
35
+ * - `split().join()` (not `replace`/`replaceAll`) for interpolation, which is
36
+ * literal on both sides and substitutes EVERY occurrence — i18next's own
37
+ * behaviour, and the objectui#3418 fix.
38
+ */
39
+ export declare const translateTimelineDefault: TimelineTranslate;
15
40
  /**
16
41
  * Was a local re-implementation that wrapped the hook in try/catch — a
17
42
  * rules-of-hooks violation (objectui#2879, same class as #2595/#2596).
@@ -1 +1 @@
1
- {"version":3,"file":"useTimelineTranslation.d.ts","sourceRoot":"","sources":["../src/useTimelineTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAchE,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;4BAlClC,CAAC;;;;;CAqCD,CAAC"}
1
+ {"version":3,"file":"useTimelineTranslation.d.ts","sourceRoot":"","sources":["../src/useTimelineTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuBhE,CAAC;AAIF;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;AAE1F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wBAAwB,EAAE,iBAIpC,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;4BA1ElC,CAAC;;;;;CA6ED,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-timeline",
3
- "version": "17.2.0",
3
+ "version": "17.5.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Timeline component plugin for Object UI",
@@ -24,28 +24,28 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@objectstack/spec": "^17.0.0-rc.1",
27
+ "@objectstack/spec": "^17.0.0-rc.6",
28
28
  "class-variance-authority": "^0.7.1",
29
29
  "zod": "^4.4.3",
30
- "@object-ui/components": "17.2.0",
31
- "@object-ui/core": "17.2.0",
32
- "@object-ui/i18n": "17.2.0",
33
- "@object-ui/mobile": "17.2.0",
34
- "@object-ui/react": "17.2.0",
35
- "@object-ui/types": "17.2.0"
30
+ "@object-ui/components": "17.5.0",
31
+ "@object-ui/core": "17.5.0",
32
+ "@object-ui/i18n": "17.5.0",
33
+ "@object-ui/mobile": "17.5.0",
34
+ "@object-ui/react": "17.5.0",
35
+ "@object-ui/types": "17.5.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "react": "^18.0.0 || ^19.0.0",
39
39
  "react-dom": "^18.0.0 || ^19.0.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@types/react": "19.2.17",
43
- "@types/react-dom": "19.2.3",
44
- "@vitejs/plugin-react": "^6.0.4",
42
+ "@types/react": "19.2.18",
43
+ "@types/react-dom": "19.2.4",
44
+ "@vitejs/plugin-react": "^6.0.5",
45
45
  "typescript": "^6.0.3",
46
- "vite": "^8.1.5",
46
+ "vite": "^8.2.1",
47
47
  "vite-plugin-dts": "^5.0.3",
48
- "@object-ui/data-objectstack": "17.2.0"
48
+ "@object-ui/data-objectstack": "17.5.0"
49
49
  },
50
50
  "keywords": [
51
51
  "objectui",