@object-ui/plugin-timeline 17.3.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 +297 -0
- package/README.md +0 -11
- package/dist/ObjectTimeline.d.ts +35 -0
- package/dist/ObjectTimeline.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -131
- package/dist/index.umd.cjs +1 -1
- package/dist/renderer.d.ts +19 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/useTimelineTranslation.d.ts +25 -0
- package/dist/useTimelineTranslation.d.ts.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,297 @@
|
|
|
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
|
+
|
|
3
295
|
## 17.3.0
|
|
4
296
|
|
|
5
297
|
### Patch Changes
|
|
@@ -1078,6 +1370,7 @@
|
|
|
1078
1370
|
### Patch Changes
|
|
1079
1371
|
|
|
1080
1372
|
- 1b6dc64: fix: complete Tailwind v3→v4 migration cleanup
|
|
1373
|
+
|
|
1081
1374
|
- Rename deprecated `flex-shrink-0` → `shrink-0` and `flex-grow-N` →
|
|
1082
1375
|
`grow-N` (Tailwind v4 dropped the long-form aliases). Affects
|
|
1083
1376
|
data-table, fields/index, FileField, ChatbotEnhanced,
|
|
@@ -1140,6 +1433,7 @@
|
|
|
1140
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.
|
|
1141
1434
|
|
|
1142
1435
|
Specifically fixes:
|
|
1436
|
+
|
|
1143
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.
|
|
1144
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.
|
|
1145
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.
|
|
@@ -1198,15 +1492,18 @@
|
|
|
1198
1492
|
- b2be122: fix(mobile): round 2 — kanban readability, calendar default view, timeline dot clipping
|
|
1199
1493
|
|
|
1200
1494
|
**Kanban**
|
|
1495
|
+
|
|
1201
1496
|
- Remove `font-mono` from card titles, descriptions, column headers, and empty-state labels — CRM cards no longer render in a monospace font.
|
|
1202
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.
|
|
1203
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.
|
|
1204
1499
|
|
|
1205
1500
|
**Calendar**
|
|
1501
|
+
|
|
1206
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.
|
|
1207
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.
|
|
1208
1504
|
|
|
1209
1505
|
**Timeline**
|
|
1506
|
+
|
|
1210
1507
|
- Add `ml-3` to the `<Timeline>` `<ol>` so the `absolute -left-3` marker dots are no longer clipped at the scroll-container edge.
|
|
1211
1508
|
|
|
1212
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)
|
package/dist/ObjectTimeline.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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,69 +33,72 @@ var b = /* @__PURE__ */ new Set([
|
|
|
16
33
|
"quarter",
|
|
17
34
|
"year"
|
|
18
35
|
]);
|
|
19
|
-
function
|
|
36
|
+
function w(e) {
|
|
20
37
|
let t = e.scale ?? e.timeScale;
|
|
21
|
-
return typeof t == "string" &&
|
|
38
|
+
return typeof t == "string" && C.has(t) ? t : "month";
|
|
22
39
|
}
|
|
23
|
-
function
|
|
24
|
-
let
|
|
25
|
-
if (Number.isNaN(
|
|
26
|
-
let
|
|
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 (;
|
|
46
|
+
for (; c <= s;) a.push(c.toLocaleString(r, {
|
|
30
47
|
month: "short",
|
|
31
48
|
day: "numeric",
|
|
32
49
|
hour: "numeric"
|
|
33
|
-
})),
|
|
50
|
+
})), c.setHours(c.getHours() + 1);
|
|
34
51
|
break;
|
|
35
52
|
case "day":
|
|
36
|
-
for (;
|
|
53
|
+
for (; c <= s;) a.push(c.toLocaleDateString(r, {
|
|
37
54
|
month: "short",
|
|
38
55
|
day: "numeric"
|
|
39
|
-
})),
|
|
56
|
+
})), c.setDate(c.getDate() + 1);
|
|
40
57
|
break;
|
|
41
58
|
case "week": {
|
|
42
59
|
let e = 1;
|
|
43
|
-
for (;
|
|
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 (
|
|
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 (
|
|
70
|
+
for (c.setMonth(0, 1); c <= s;) a.push(String(c.getFullYear())), c.setFullYear(c.getFullYear() + 1);
|
|
51
71
|
break;
|
|
52
|
-
default: for (;
|
|
72
|
+
default: for (; c <= s;) a.push(c.toLocaleDateString(r, {
|
|
53
73
|
month: "short",
|
|
54
74
|
year: "numeric"
|
|
55
|
-
})),
|
|
75
|
+
})), c.setMonth(c.getMonth() + 1);
|
|
56
76
|
}
|
|
57
|
-
return
|
|
77
|
+
return a;
|
|
58
78
|
}
|
|
59
|
-
function
|
|
79
|
+
function E(e) {
|
|
60
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()));
|
|
61
81
|
return {
|
|
62
82
|
minDate: new Date(n).toISOString().split("T")[0],
|
|
63
83
|
maxDate: new Date(r).toISOString().split("T")[0]
|
|
64
84
|
};
|
|
65
85
|
}
|
|
66
|
-
function
|
|
86
|
+
function ae(e, t, n, r) {
|
|
67
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;
|
|
68
88
|
return {
|
|
69
89
|
start: c / s * 100,
|
|
70
90
|
width: l / s * 100
|
|
71
91
|
};
|
|
72
92
|
}
|
|
73
|
-
function
|
|
74
|
-
let
|
|
75
|
-
return t === "short" ?
|
|
93
|
+
function D(e, t, n) {
|
|
94
|
+
let r = new Date(e);
|
|
95
|
+
return t === "short" ? r.toLocaleDateString(n) : t === "long" ? r.toLocaleDateString(n, {
|
|
76
96
|
year: "numeric",
|
|
77
97
|
month: "long",
|
|
78
98
|
day: "numeric"
|
|
79
|
-
}) :
|
|
99
|
+
}) : r.toISOString().split("T")[0];
|
|
80
100
|
}
|
|
81
|
-
function
|
|
101
|
+
function O({ label: e, color: t }) {
|
|
82
102
|
let n = t ? {
|
|
83
103
|
backgroundColor: `${t}22`,
|
|
84
104
|
color: t,
|
|
@@ -90,7 +110,7 @@ function E({ label: e, color: t }) {
|
|
|
90
110
|
children: e
|
|
91
111
|
});
|
|
92
112
|
}
|
|
93
|
-
function
|
|
113
|
+
function k(e) {
|
|
94
114
|
let t = [];
|
|
95
115
|
for (let n of e) {
|
|
96
116
|
let e = n.group == null ? "" : String(n.group), r = t[t.length - 1];
|
|
@@ -101,14 +121,14 @@ function D(e) {
|
|
|
101
121
|
}
|
|
102
122
|
return t;
|
|
103
123
|
}
|
|
104
|
-
var
|
|
105
|
-
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();
|
|
106
126
|
if (r === "vertical") {
|
|
107
|
-
let e =
|
|
127
|
+
let e = k(i), r = e.some((e) => e.key !== ""), f = (e, t) => {
|
|
108
128
|
let n = e.color ? {
|
|
109
129
|
backgroundColor: `${e.color}33`,
|
|
110
130
|
borderColor: e.color
|
|
111
|
-
} : void 0, r = e.time ?
|
|
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 : [];
|
|
112
132
|
return /* @__PURE__ */ u(I, {
|
|
113
133
|
density: "compact",
|
|
114
134
|
className: o(e.className, s && "cursor-pointer"),
|
|
@@ -133,9 +153,9 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
133
153
|
className: "text-sm sm:text-base mb-1",
|
|
134
154
|
children: e.title
|
|
135
155
|
}),
|
|
136
|
-
|
|
156
|
+
f.length > 0 && /* @__PURE__ */ l("div", {
|
|
137
157
|
className: "flex flex-wrap gap-1.5 mt-1 mb-1",
|
|
138
|
-
children:
|
|
158
|
+
children: f.map((e) => /* @__PURE__ */ l(O, {
|
|
139
159
|
label: e.label,
|
|
140
160
|
color: e.color
|
|
141
161
|
}, e.key))
|
|
@@ -161,13 +181,13 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
161
181
|
})]
|
|
162
182
|
}), /* @__PURE__ */ l(P, {
|
|
163
183
|
className: "mt-3",
|
|
164
|
-
children: e.items.map((e, n) =>
|
|
184
|
+
children: e.items.map((e, n) => f(e, `${t}-${n}`))
|
|
165
185
|
})]
|
|
166
186
|
}, `${e.key}-${t}`))
|
|
167
187
|
}) : /* @__PURE__ */ l(P, {
|
|
168
188
|
className: t,
|
|
169
189
|
...n,
|
|
170
|
-
children: i.map((e, t) =>
|
|
190
|
+
children: i.map((e, t) => f(e, t))
|
|
171
191
|
});
|
|
172
192
|
}
|
|
173
193
|
if (r === "horizontal") return /* @__PURE__ */ l(U, {
|
|
@@ -189,7 +209,7 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
189
209
|
children: [
|
|
190
210
|
e.time && /* @__PURE__ */ l(V, {
|
|
191
211
|
dateTime: e.time,
|
|
192
|
-
children:
|
|
212
|
+
children: D(e.time, a, d)
|
|
193
213
|
}),
|
|
194
214
|
e.title && /* @__PURE__ */ l(B, { children: e.title }),
|
|
195
215
|
e.description && /* @__PURE__ */ l(H, {
|
|
@@ -203,7 +223,7 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
203
223
|
}, t))
|
|
204
224
|
});
|
|
205
225
|
if (r === "gantt") {
|
|
206
|
-
let r =
|
|
226
|
+
let r = E(i), c = e.minDate || r.minDate, p = e.maxDate || r.maxDate, m = T(w(e), c, p, d, f);
|
|
207
227
|
return /* @__PURE__ */ u(G, {
|
|
208
228
|
className: o("overflow-x-auto [-webkit-overflow-scrolling:touch]", t),
|
|
209
229
|
...n,
|
|
@@ -211,11 +231,11 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
211
231
|
className: "flex items-center px-2 sm:px-4 py-2 sm:py-3",
|
|
212
232
|
children: /* @__PURE__ */ l("span", {
|
|
213
233
|
className: "font-semibold text-xs sm:text-sm",
|
|
214
|
-
children: e.rowLabel || "
|
|
234
|
+
children: e.rowLabel || f("timeline.gantt.rowLabel")
|
|
215
235
|
})
|
|
216
236
|
}), /* @__PURE__ */ l(J, { children: /* @__PURE__ */ l("div", {
|
|
217
237
|
className: "flex h-full",
|
|
218
|
-
children:
|
|
238
|
+
children: m.map((e, t) => /* @__PURE__ */ l("div", {
|
|
219
239
|
className: "flex-1 px-1 sm:px-2 py-2 sm:py-3 border-r text-xs font-medium text-center",
|
|
220
240
|
children: e
|
|
221
241
|
}, t))
|
|
@@ -230,13 +250,13 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
230
250
|
children: i.map((e, t) => /* @__PURE__ */ l(Y, {
|
|
231
251
|
className: "relative",
|
|
232
252
|
children: (e.items || []).map((n, r) => {
|
|
233
|
-
let i =
|
|
253
|
+
let i = ae(n.startDate, n.endDate, c, p);
|
|
234
254
|
return /* @__PURE__ */ l(Z, {
|
|
235
255
|
start: i.start,
|
|
236
256
|
width: i.width,
|
|
237
257
|
variant: n.variant || "default",
|
|
238
258
|
onClick: () => s?.(n, e, t, r),
|
|
239
|
-
title: `${n.title || ""}\n${
|
|
259
|
+
title: `${n.title || ""}\n${D(n.startDate, a, d)} - ${D(n.endDate, a, d)}`,
|
|
240
260
|
children: /* @__PURE__ */ l(Q, { children: n.title })
|
|
241
261
|
}, r);
|
|
242
262
|
})
|
|
@@ -247,7 +267,7 @@ var O = ({ schema: e, className: t, ...n }) => {
|
|
|
247
267
|
}
|
|
248
268
|
return null;
|
|
249
269
|
};
|
|
250
|
-
d.register("timeline",
|
|
270
|
+
d.register("timeline", A, {
|
|
251
271
|
namespace: "plugin-timeline",
|
|
252
272
|
label: "Timeline",
|
|
253
273
|
category: "data-display",
|
|
@@ -442,34 +462,22 @@ d.register("timeline", O, {
|
|
|
442
462
|
}
|
|
443
463
|
}
|
|
444
464
|
});
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
"timeline.bucket.tomorrow": "Tomorrow",
|
|
449
|
-
"timeline.bucket.thisWeek": "This week",
|
|
450
|
-
"timeline.bucket.nextWeek": "Next week",
|
|
451
|
-
"timeline.bucket.later": "Later",
|
|
452
|
-
"timeline.bucket.noDate": "No date",
|
|
453
|
-
"timeline.bucket.unassigned": "Unassigned",
|
|
454
|
-
"timeline.relative.today": "Today",
|
|
455
|
-
"timeline.relative.tomorrow": "Tomorrow",
|
|
456
|
-
"timeline.relative.yesterday": "Yesterday",
|
|
457
|
-
"timeline.relative.inDays": "In {{n}} days",
|
|
458
|
-
"timeline.relative.daysAgo": "{{n}} days ago"
|
|
459
|
-
}, "timeline.bucket.today"), A = {
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region src/ObjectTimeline.tsx
|
|
467
|
+
var j = {
|
|
460
468
|
fieldOptionLabel: (e, t, n, r) => r,
|
|
461
469
|
translateOptions: (e, t, n) => n,
|
|
462
470
|
fieldLabel: (e, t, n) => n
|
|
463
471
|
};
|
|
464
|
-
function
|
|
465
|
-
return
|
|
472
|
+
function oe() {
|
|
473
|
+
return re() ?? j;
|
|
466
474
|
}
|
|
467
475
|
var M = v.object({
|
|
468
476
|
title: v.string().optional(),
|
|
469
477
|
date: v.string().optional(),
|
|
470
478
|
description: v.string().optional(),
|
|
471
479
|
variant: v.string().optional()
|
|
472
|
-
}),
|
|
480
|
+
}), se = v.object({
|
|
473
481
|
mapping: M.optional(),
|
|
474
482
|
objectName: v.string().optional(),
|
|
475
483
|
titleField: v.string().optional(),
|
|
@@ -487,65 +495,72 @@ var M = v.object({
|
|
|
487
495
|
"quarter",
|
|
488
496
|
"year"
|
|
489
497
|
]).optional()
|
|
490
|
-
}), N = ({ schema: e, dataSource: o, className: s, onRowClick: c, onItemClick: d, ...
|
|
491
|
-
let [
|
|
492
|
-
let t = Array.isArray(e.items) && e.items.length > 0, n = Array.isArray(
|
|
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;
|
|
493
501
|
return !t && !n && !!e.objectName;
|
|
494
|
-
}), [
|
|
502
|
+
}), [v, y] = i(null), [b, x] = i(0), [C, w] = i(null), T = e.timeline;
|
|
495
503
|
n(() => {
|
|
496
|
-
let t =
|
|
504
|
+
let t = se.safeParse(e);
|
|
497
505
|
t.success || console.warn("[ObjectTimeline] Invalid timeline configuration:", t.error.format());
|
|
498
506
|
}, [e]);
|
|
499
|
-
let
|
|
507
|
+
let E = te(e.bind);
|
|
500
508
|
n(() => {
|
|
501
509
|
let t = !0;
|
|
502
510
|
return (async () => {
|
|
503
511
|
if (!(!o || typeof o.getObjectSchema != "function" || !e.objectName)) try {
|
|
504
512
|
let n = await o.getObjectSchema(e.objectName);
|
|
505
|
-
t &&
|
|
513
|
+
t && w(n);
|
|
506
514
|
} catch (e) {
|
|
507
515
|
console.warn("Failed to fetch object def for ObjectTimeline", e);
|
|
508
516
|
}
|
|
509
517
|
})(), () => {
|
|
510
518
|
t = !1;
|
|
511
519
|
};
|
|
512
|
-
}, [e.objectName, o])
|
|
513
|
-
|
|
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 () => {
|
|
514
524
|
if (!o || typeof o.find != "function" || !e.objectName) {
|
|
515
|
-
|
|
525
|
+
_(!1);
|
|
516
526
|
return;
|
|
517
527
|
}
|
|
518
|
-
|
|
528
|
+
_(!0);
|
|
519
529
|
try {
|
|
520
|
-
let t = f(
|
|
521
|
-
|
|
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,
|
|
522
534
|
...t.length > 0 ? { $expand: t } : {}
|
|
523
|
-
}), r =
|
|
524
|
-
|
|
535
|
+
}), r = m(n);
|
|
536
|
+
ee(r);
|
|
525
537
|
} catch (e) {
|
|
526
|
-
console.error(e),
|
|
538
|
+
console.error(e), y(e);
|
|
527
539
|
} finally {
|
|
528
|
-
|
|
540
|
+
_(!1);
|
|
529
541
|
}
|
|
530
|
-
})() :
|
|
542
|
+
})() : _(!1);
|
|
531
543
|
}, [
|
|
532
544
|
e.objectName,
|
|
533
545
|
o,
|
|
534
|
-
|
|
546
|
+
E,
|
|
535
547
|
e.items,
|
|
536
|
-
|
|
548
|
+
h.data,
|
|
549
|
+
b,
|
|
537
550
|
C,
|
|
538
|
-
|
|
551
|
+
ae,
|
|
552
|
+
D,
|
|
553
|
+
e.limit
|
|
539
554
|
]);
|
|
540
|
-
let
|
|
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(() => {
|
|
541
556
|
if (e.items) return e.items;
|
|
542
|
-
if (!
|
|
543
|
-
let t =
|
|
557
|
+
if (!O || !Array.isArray(O)) return [];
|
|
558
|
+
let t = C?.fields ?? {}, n = e.objectName || "", r = (e) => {
|
|
544
559
|
if (!e || !t[e]?.options) return {};
|
|
545
560
|
let n = {};
|
|
546
561
|
for (let r of t[e].options) r && r.value != null && (n[String(r.value)] = r);
|
|
547
562
|
return n;
|
|
548
|
-
}, i = r(
|
|
563
|
+
}, i = r(R), a = Array.isArray(T?.metaFields) ? T.metaFields.filter((e) => typeof e == "string" && e) : ["status", "priority"].filter((e) => t[e]), o = {};
|
|
549
564
|
for (let e of a) o[e] = r(e);
|
|
550
565
|
let s = (e) => {
|
|
551
566
|
if (e == null || e === "") return;
|
|
@@ -557,11 +572,11 @@ var M = v.object({
|
|
|
557
572
|
if (t == null || t === "") return null;
|
|
558
573
|
let i = r[String(t)];
|
|
559
574
|
return {
|
|
560
|
-
label: i?.label ?
|
|
575
|
+
label: i?.label ? j(n, e, String(t), i.label) : String(t),
|
|
561
576
|
color: i?.color
|
|
562
577
|
};
|
|
563
|
-
}, l =
|
|
564
|
-
let t = e[
|
|
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 = [];
|
|
565
580
|
if (n) for (let t of a) {
|
|
566
581
|
let n = c(t, e[t], o[t] || {});
|
|
567
582
|
n && u.push({
|
|
@@ -571,12 +586,12 @@ var M = v.object({
|
|
|
571
586
|
});
|
|
572
587
|
}
|
|
573
588
|
return {
|
|
574
|
-
title: e[
|
|
589
|
+
title: e[M],
|
|
575
590
|
time: t,
|
|
576
591
|
startDate: t,
|
|
577
592
|
endDate: r,
|
|
578
|
-
description: e[
|
|
579
|
-
variant: e[
|
|
593
|
+
description: e[F],
|
|
594
|
+
variant: e[I] || "default",
|
|
580
595
|
color: s(i),
|
|
581
596
|
group: l,
|
|
582
597
|
meta: u,
|
|
@@ -585,17 +600,17 @@ var M = v.object({
|
|
|
585
600
|
});
|
|
586
601
|
l.sort((e, t) => (e.startDate ? new Date(e.startDate).getTime() : Infinity) - (t.startDate ? new Date(t.startDate).getTime() : Infinity));
|
|
587
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) => {
|
|
588
|
-
if (!e) return
|
|
603
|
+
if (!e) return k("timeline.bucket.noDate");
|
|
589
604
|
let t = d(new Date(e));
|
|
590
|
-
return Number.isNaN(t) ?
|
|
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");
|
|
591
606
|
};
|
|
592
|
-
if (
|
|
593
|
-
let e = r(
|
|
607
|
+
if (L && !l.every((e) => e.group == null || e.group === "")) {
|
|
608
|
+
let e = r(L);
|
|
594
609
|
return l.map((t) => {
|
|
595
|
-
let n = c(
|
|
610
|
+
let n = c(L, t.group, e);
|
|
596
611
|
return {
|
|
597
612
|
...t,
|
|
598
|
-
group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) :
|
|
613
|
+
group: n ? n.label : t.group != null && t.group !== "" ? String(t.group) : k("timeline.bucket.unassigned")
|
|
599
614
|
};
|
|
600
615
|
});
|
|
601
616
|
}
|
|
@@ -605,43 +620,43 @@ var M = v.object({
|
|
|
605
620
|
}));
|
|
606
621
|
}, [
|
|
607
622
|
e.items,
|
|
608
|
-
|
|
609
|
-
|
|
623
|
+
O,
|
|
624
|
+
C,
|
|
610
625
|
e.objectName,
|
|
626
|
+
M,
|
|
627
|
+
N,
|
|
628
|
+
P,
|
|
611
629
|
F,
|
|
612
630
|
I,
|
|
613
|
-
L,
|
|
614
631
|
R,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
]), U =
|
|
621
|
-
|
|
622
|
-
}, []), { ref: W, isRefreshing: G, pullDistance: K } = ee({
|
|
623
|
-
onRefresh: U,
|
|
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,
|
|
624
639
|
enabled: !!e.objectName && !!o
|
|
625
|
-
}),
|
|
640
|
+
}), W = ne({
|
|
626
641
|
navigation: e.navigation,
|
|
627
642
|
objectName: e.objectName,
|
|
628
643
|
onRowClick: c ?? d
|
|
629
|
-
}),
|
|
644
|
+
}), G = T?.scale ?? e.scale, K = {
|
|
630
645
|
...e,
|
|
631
|
-
items:
|
|
646
|
+
items: z || [],
|
|
632
647
|
className: s || e.className,
|
|
633
|
-
...
|
|
648
|
+
...G ? { timeScale: G } : {},
|
|
634
649
|
onItemClick: (e) => {
|
|
635
650
|
let t = e._data || e;
|
|
636
|
-
|
|
651
|
+
W.handleClick(t), d?.(t);
|
|
637
652
|
}
|
|
638
653
|
};
|
|
639
|
-
return
|
|
654
|
+
return v ? /* @__PURE__ */ u("div", {
|
|
640
655
|
className: "p-4 text-destructive",
|
|
641
656
|
"data-testid": "timeline-error",
|
|
642
657
|
role: "alert",
|
|
643
|
-
children: ["Error loading timeline: ",
|
|
644
|
-
}) :
|
|
658
|
+
children: ["Error loading timeline: ", v.message]
|
|
659
|
+
}) : re && (!z || z.length === 0) ? /* @__PURE__ */ u("div", {
|
|
645
660
|
className: "flex flex-col h-full min-h-[200px] p-4 gap-3",
|
|
646
661
|
"data-testid": "timeline-loading",
|
|
647
662
|
role: "status",
|
|
@@ -664,17 +679,17 @@ var M = v.object({
|
|
|
664
679
|
})]
|
|
665
680
|
}, e))]
|
|
666
681
|
}) : /* @__PURE__ */ u("div", {
|
|
667
|
-
ref:
|
|
682
|
+
ref: V,
|
|
668
683
|
className: "relative overflow-auto h-full min-w-0",
|
|
669
684
|
children: [
|
|
670
|
-
|
|
685
|
+
U > 0 && /* @__PURE__ */ l("div", {
|
|
671
686
|
className: "flex items-center justify-center text-xs text-muted-foreground",
|
|
672
|
-
style: { height:
|
|
673
|
-
children:
|
|
687
|
+
style: { height: U },
|
|
688
|
+
children: H ? "Refreshing…" : "Pull to refresh"
|
|
674
689
|
}),
|
|
675
|
-
/* @__PURE__ */ l(
|
|
676
|
-
|
|
677
|
-
...
|
|
690
|
+
/* @__PURE__ */ l(A, { schema: K }),
|
|
691
|
+
W.isOverlay && /* @__PURE__ */ l(a, {
|
|
692
|
+
...W,
|
|
678
693
|
title: "Timeline Item",
|
|
679
694
|
children: (e) => /* @__PURE__ */ l("div", {
|
|
680
695
|
className: "space-y-3",
|
|
@@ -823,12 +838,23 @@ var Q = e.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ l("div", {
|
|
|
823
838
|
...t
|
|
824
839
|
}));
|
|
825
840
|
Q.displayName = "TimelineGanttBarContent";
|
|
826
|
-
var
|
|
841
|
+
var ce = {
|
|
842
|
+
filter: !0,
|
|
843
|
+
sort: !0,
|
|
844
|
+
limit: "limit"
|
|
845
|
+
}, $ = ({ schema: e, ...t }) => {
|
|
827
846
|
let { dataSource: n } = _() || {};
|
|
828
|
-
return /* @__PURE__ */ l(
|
|
847
|
+
return /* @__PURE__ */ l(ee, {
|
|
829
848
|
schema: e,
|
|
849
|
+
mapping: ce,
|
|
830
850
|
dataSource: n,
|
|
831
|
-
|
|
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
|
+
})
|
|
832
858
|
});
|
|
833
859
|
};
|
|
834
860
|
d.register("object-timeline", $, {
|
|
@@ -871,4 +897,4 @@ d.register("object-timeline", $, {
|
|
|
871
897
|
}]
|
|
872
898
|
});
|
|
873
899
|
//#endregion
|
|
874
|
-
export { N as ObjectTimeline, $ as ObjectTimelineRenderer,
|
|
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 };
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/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||!m.call(e,`default`)?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)}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=await s.find(e.objectName,{options:{$top: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,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]),z=(0,t.useCallback)(async()=>{y(e=>e+1)},[]),{ref:B,isRefreshing:V,pullDistance:H}=(0,o.usePullToRefresh)({onRefresh:z,enabled:!!e.objectName&&!!s}),U=(0,a.useNavigationOverlay)({navigation:e.navigation,objectName:e.objectName,onRowClick:l??u}),W=S?.scale??e.scale,G={...e,items:R||[],className:c||e.className,...W?{timeScale:W}:{},onItemClick:e=>{let t=e._data||e;U.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:B,className:`relative overflow-auto h-full min-w-0`,children:[H>0&&(0,r.jsx)(`div`,{className:`flex items-center justify-center text-xs text-muted-foreground`,style:{height:H},children:V?`Refreshing…`:`Pull to refresh`}),(0,r.jsx)(w,{schema:G}),U.isOverlay&&(0,r.jsx)(n.NavigationOverlay,{...U,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});
|
package/dist/renderer.d.ts
CHANGED
|
@@ -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;
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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.
|
|
3
|
+
"version": "17.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Timeline component plugin for Object UI",
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@objectstack/spec": "^17.0.0-rc.
|
|
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.
|
|
31
|
-
"@object-ui/core": "17.
|
|
32
|
-
"@object-ui/i18n": "17.
|
|
33
|
-
"@object-ui/mobile": "17.
|
|
34
|
-
"@object-ui/react": "17.
|
|
35
|
-
"@object-ui/types": "17.
|
|
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",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"@types/react-dom": "19.2.4",
|
|
44
44
|
"@vitejs/plugin-react": "^6.0.5",
|
|
45
45
|
"typescript": "^6.0.3",
|
|
46
|
-
"vite": "^8.2.
|
|
46
|
+
"vite": "^8.2.1",
|
|
47
47
|
"vite-plugin-dts": "^5.0.3",
|
|
48
|
-
"@object-ui/data-objectstack": "17.
|
|
48
|
+
"@object-ui/data-objectstack": "17.5.0"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
51
51
|
"objectui",
|