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