@object-ui/core 17.5.0 → 17.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +7404 -0
  2. package/README.md +127 -26
  3. package/dist/actions/ActionEngine.d.ts +5 -3
  4. package/dist/actions/ActionEngine.js +14 -10
  5. package/dist/actions/ActionRunner.d.ts +363 -30
  6. package/dist/actions/ActionRunner.js +544 -58
  7. package/dist/actions/TransactionManager.d.ts +7 -2
  8. package/dist/actions/actionKeys.d.ts +75 -13
  9. package/dist/actions/actionKeys.js +131 -16
  10. package/dist/actions/actionResponse.js +3 -3
  11. package/dist/actions/index.d.ts +2 -0
  12. package/dist/actions/index.js +2 -0
  13. package/dist/actions/recordDelete.d.ts +118 -0
  14. package/dist/actions/recordDelete.js +112 -0
  15. package/dist/actions/recordIdParam.d.ts +77 -0
  16. package/dist/actions/recordIdParam.js +37 -0
  17. package/dist/actions/serverActionHandler.d.ts +1 -1
  18. package/dist/actions/serverActionHandler.js +1 -1
  19. package/dist/adapters/ValueDataSource.d.ts +6 -1
  20. package/dist/adapters/ValueDataSource.js +1090 -98
  21. package/dist/adapters/batchTransaction.d.ts +1 -1
  22. package/dist/adapters/batchTransaction.js +1 -1
  23. package/dist/builder/schema-builder.d.ts +38 -81
  24. package/dist/builder/schema-builder.js +33 -152
  25. package/dist/data-scope/ViewDataProvider.d.ts +1 -1
  26. package/dist/data-scope/ViewDataProvider.js +21 -1
  27. package/dist/data-scope/element-data-source.d.ts +261 -7
  28. package/dist/data-scope/element-data-source.js +342 -52
  29. package/dist/data-scope/index.d.ts +9 -4
  30. package/dist/data-scope/index.js +9 -4
  31. package/dist/evaluator/ExpressionEvaluator.d.ts +128 -1
  32. package/dist/evaluator/ExpressionEvaluator.js +226 -13
  33. package/dist/evaluator/FormulaFunctions.d.ts +0 -10
  34. package/dist/evaluator/FormulaFunctions.js +166 -27
  35. package/dist/evaluator/SafeExpressionParser.js +0 -4
  36. package/dist/evaluator/declaredPredicate.d.ts +93 -9
  37. package/dist/evaluator/declaredPredicate.js +118 -17
  38. package/dist/evaluator/fieldRules.d.ts +107 -4
  39. package/dist/evaluator/fieldRules.js +231 -35
  40. package/dist/evaluator/index.d.ts +2 -0
  41. package/dist/evaluator/index.js +2 -0
  42. package/dist/evaluator/listConditional.d.ts +125 -9
  43. package/dist/evaluator/listConditional.js +167 -26
  44. package/dist/evaluator/optionRules.d.ts +126 -0
  45. package/dist/evaluator/optionRules.js +141 -4
  46. package/dist/evaluator/predicateInput.d.ts +15 -4
  47. package/dist/evaluator/predicateInput.js +35 -2
  48. package/dist/evaluator/rowPredicateCanon.d.ts +56 -0
  49. package/dist/evaluator/rowPredicateCanon.js +158 -0
  50. package/dist/evaluator/subjectPermissions.d.ts +76 -0
  51. package/dist/evaluator/subjectPermissions.js +44 -0
  52. package/dist/evaluator/unevaluablePredicate.d.ts +57 -0
  53. package/dist/evaluator/unevaluablePredicate.js +70 -0
  54. package/dist/index.d.ts +18 -0
  55. package/dist/index.js +97 -2
  56. package/dist/protocols/index.d.ts +0 -1
  57. package/dist/protocols/index.js +9 -1
  58. package/dist/registry/Registry.d.ts +397 -48
  59. package/dist/registry/Registry.js +263 -11
  60. package/dist/registry/WidgetRegistry.js +7 -3
  61. package/dist/registry/html-tier-intrinsics.d.ts +90 -0
  62. package/dist/registry/html-tier-intrinsics.js +110 -0
  63. package/dist/registry/public-blocks.d.ts +8 -0
  64. package/dist/registry/public-blocks.js +57 -0
  65. package/dist/theme/ThemeEngine.js +1 -1
  66. package/dist/theme/index.d.ts +1 -1
  67. package/dist/theme/index.js +1 -1
  68. package/dist/types/index.d.ts +92 -13
  69. package/dist/utils/chart-category-key.d.ts +82 -0
  70. package/dist/utils/chart-category-key.js +84 -0
  71. package/dist/utils/chart-measure-key.d.ts +64 -0
  72. package/dist/utils/chart-measure-key.js +65 -0
  73. package/dist/utils/chart-presentation.d.ts +188 -0
  74. package/dist/utils/chart-presentation.js +345 -0
  75. package/dist/utils/chart-series.d.ts +271 -31
  76. package/dist/utils/chart-series.js +478 -55
  77. package/dist/utils/column-identity.d.ts +43 -0
  78. package/dist/utils/column-identity.js +47 -1
  79. package/dist/utils/column-sortability.d.ts +157 -0
  80. package/dist/utils/column-sortability.js +217 -0
  81. package/dist/utils/dashboard-filters.d.ts +38 -6
  82. package/dist/utils/dashboard-filters.js +107 -61
  83. package/dist/utils/dataset-format.d.ts +211 -30
  84. package/dist/utils/dataset-format.js +407 -52
  85. package/dist/utils/date-display.d.ts +354 -0
  86. package/dist/utils/date-display.js +463 -0
  87. package/dist/utils/date-macros.js +7 -0
  88. package/dist/utils/debug.js +7 -0
  89. package/dist/utils/drill-down.d.ts +78 -0
  90. package/dist/utils/drill-down.js +93 -0
  91. package/dist/utils/emptiness.d.ts +96 -0
  92. package/dist/utils/emptiness.js +101 -0
  93. package/dist/utils/expand-fields.d.ts +171 -11
  94. package/dist/utils/expand-fields.js +171 -11
  95. package/dist/utils/extract-records.d.ts +65 -5
  96. package/dist/utils/extract-records.js +65 -8
  97. package/dist/utils/filter-converter.d.ts +152 -4
  98. package/dist/utils/filter-converter.js +1092 -22
  99. package/dist/utils/filter-tokens.d.ts +49 -5
  100. package/dist/utils/filter-tokens.js +105 -34
  101. package/dist/utils/freeze-schema.d.ts +38 -1
  102. package/dist/utils/freeze-schema.js +10 -0
  103. package/dist/utils/grouping-fields.d.ts +61 -0
  104. package/dist/utils/grouping-fields.js +84 -0
  105. package/dist/utils/humanize-label.d.ts +60 -0
  106. package/dist/utils/humanize-label.js +62 -0
  107. package/dist/utils/managedBy.d.ts +30 -5
  108. package/dist/utils/managedBy.js +5 -5
  109. package/dist/utils/native-date-value.d.ts +48 -0
  110. package/dist/utils/native-date-value.js +167 -0
  111. package/dist/utils/non-grid-row-ceiling.d.ts +143 -0
  112. package/dist/utils/non-grid-row-ceiling.js +141 -0
  113. package/dist/utils/normalize-list-view.d.ts +131 -1
  114. package/dist/utils/normalize-list-view.js +248 -6
  115. package/dist/utils/number-display.d.ts +70 -17
  116. package/dist/utils/number-display.js +34 -12
  117. package/dist/utils/object-aggregate-query.d.ts +113 -0
  118. package/dist/utils/object-aggregate-query.js +50 -0
  119. package/dist/utils/parent-scope.d.ts +123 -0
  120. package/dist/utils/parent-scope.js +140 -0
  121. package/dist/utils/predicate-fields.d.ts +62 -4
  122. package/dist/utils/predicate-fields.js +169 -4
  123. package/dist/utils/record-color.d.ts +75 -0
  124. package/dist/utils/record-color.js +65 -0
  125. package/dist/utils/record-source.d.ts +298 -0
  126. package/dist/utils/record-source.js +331 -0
  127. package/dist/utils/record-title.d.ts +148 -8
  128. package/dist/utils/record-title.js +220 -26
  129. package/dist/utils/reference-keys.d.ts +21 -22
  130. package/dist/utils/reference-keys.js +532 -29
  131. package/dist/utils/retired-field-types.d.ts +90 -0
  132. package/dist/utils/retired-field-types.js +124 -0
  133. package/dist/utils/sort-query.d.ts +128 -26
  134. package/dist/utils/sort-query.js +240 -13
  135. package/dist/utils/text-comparand.d.ts +92 -0
  136. package/dist/utils/text-comparand.js +99 -0
  137. package/dist/utils/unmaterialized-fields.d.ts +52 -0
  138. package/dist/utils/unmaterialized-fields.js +57 -0
  139. package/dist/utils/without-denied-fields.d.ts +49 -0
  140. package/dist/utils/without-denied-fields.js +52 -0
  141. package/dist/validation/index.d.ts +9 -4
  142. package/dist/validation/index.js +9 -4
  143. package/dist/validation/schema-validator.d.ts +1 -1
  144. package/dist/validation/schema-validator.js +305 -82
  145. package/dist/validation/server-owned-value.d.ts +62 -0
  146. package/dist/validation/server-owned-value.js +99 -0
  147. package/dist/validation/validators/object-validation-engine.d.ts +1 -1
  148. package/dist/validation/validators/object-validation-engine.js +14 -5
  149. package/package.json +8 -9
  150. package/dist/__benchmarks__/core.bench.d.ts +0 -8
  151. package/dist/__benchmarks__/core.bench.js +0 -53
  152. package/dist/data-scope/DataScopeManager.d.ts +0 -127
  153. package/dist/data-scope/DataScopeManager.js +0 -229
  154. package/dist/protocols/ResponsiveProtocol.d.ts +0 -73
  155. package/dist/protocols/ResponsiveProtocol.js +0 -158
  156. package/dist/validation/validation-engine.d.ts +0 -88
  157. package/dist/validation/validation-engine.js +0 -434
@@ -0,0 +1,354 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * date-display - the ONE date/datetime display path behind every field cell,
10
+ * grid card, gantt tooltip and dataset measure in the console.
11
+ *
12
+ * These functions are unchanged; what changed is where they live. They were
13
+ * written in `@object-ui/fields`' barrel (`packages/fields/src/index.tsx`),
14
+ * which is a React package, so `@object-ui/core` could not reach them - and
15
+ * `core`'s `utils/dataset-format.ts` is exactly the caller that needed them:
16
+ * `formatMeasure` returned `String(v)` for any non-numeric value, so a `min` /
17
+ * `max` measure over a date field rendered its raw 24-character ISO string on
18
+ * the metric tile, in chart values, in dataset table cells and in the
19
+ * metadata-admin dataset preview (objectui#7178).
20
+ *
21
+ * The fix is the move, NOT a second formatter here. That choice is the whole
22
+ * point, and it is the lesson of objectui#4576: when the percent convention
23
+ * was duplicated across this same package boundary, a list cell and a
24
+ * dashboard measure drifted apart (`1.234,5 %` beside `1.234,5%` in a German
25
+ * session) while both were "correct". `dataset-format.ts`'s own header records
26
+ * that history, and `number-display.ts` next door is the same remedy applied
27
+ * to numbers: the pure function moves DOWN into the React-free engine and the
28
+ * upper package re-exports it, so there is one home and nothing to drift.
29
+ *
30
+ * `@object-ui/fields` re-exports the formatting symbols below under their
31
+ * original names, so `formatDate` / `formatDateTime` /
32
+ * `formatDateTimeCompactParts` / `formatRelativeDate` / `DateDisplayOptions`
33
+ * keep working unchanged for `ObjectGrid`, `ObjectGantt`,
34
+ * `plugin-dashboard`'s `recordFields` and the `date` cell renderer.
35
+ * `toDisplayDate` is exported from `@object-ui/core` alone (objectui#10183),
36
+ * and so are `toDisplayEndDate` / `toInclusiveEndDay`, the end read and its
37
+ * inverse both gantt surfaces share (objectui#11141).
38
+ *
39
+ * The `datetime` CELL face joined this file in objectui#7443. It used to be a
40
+ * second convention inlined in `DateTimeCellRenderer`: two `Intl` option bags
41
+ * for one field type, kept in step by nothing, while `date` had exactly one.
42
+ * It is `formatDateTime`'s `'compact'` style now, byte-identical to what the
43
+ * cell rendered before.
44
+ *
45
+ * Pure by construction (no React, no i18n): the only ambient inputs are `Intl`
46
+ * and the clock, and the one phrase `Intl` cannot produce ("Overdue Nd") comes
47
+ * in through the INJECTED `options.t`, the same way `buildDatasetFieldHelpers`
48
+ * in `dataset-format.ts` takes `fieldLabel`.
49
+ *
50
+ * ⚠️ There is a third ambient input, and it is the one this module has to
51
+ * decide about rather than pass on: the VIEWER's timezone. A value carrying a
52
+ * time is an instant and renders in that zone; a DATE-ONLY value names a
53
+ * calendar day, carries no instant, and must render as that day everywhere.
54
+ * `toDisplayDate` below is the single parse step that tells the two apart —
55
+ * every function here goes through it (objectui#10110), and so does every
56
+ * caller elsewhere that needs a face or a day comparison none of these
57
+ * functions produce (objectui#10183).
58
+ */
59
+ /**
60
+ * Options shared by {@link formatDate} / {@link formatRelativeDate} /
61
+ * {@link formatDateTime}. One bag, and each function reads the keys it needs:
62
+ * `dueLike` and `t` only matter on the relative path, `style` is read by
63
+ * `formatDateTime` and by `formatDate` (see below).
64
+ */
65
+ export interface DateDisplayOptions {
66
+ dueLike?: boolean;
67
+ /** BCP-47 display locale (ADR-0053 tenant default); falls back to the runtime locale. */
68
+ locale?: string;
69
+ /** i18n translate fn for phrases `Intl` can't produce (the "Overdue Nd" wording). */
70
+ t?: (key: string, params?: Record<string, unknown>) => string;
71
+ /**
72
+ * Named face, read by {@link formatDateTime} and {@link formatDate}. Each
73
+ * reads its own vocabulary: `'compact'` is `formatDateTime`'s dense grid
74
+ * cell face (objectui#7443), `'short'` and `'relative'` are `formatDate`'s;
75
+ * anything else, or absent, is that function's default face.
76
+ *
77
+ * It rides here rather than in a second positional parameter because
78
+ * `formatDateTime(value, options?)` is a PUBLISHED signature with `options`
79
+ * in position two (objectui#4272). A positional `style` would have displaced
80
+ * it: TypeScript would reject the old call, but a JavaScript caller would
81
+ * silently hand its options bag to the style slot and lose its locale —
82
+ * the #4272 defect again.
83
+ *
84
+ * ⚠️ On {@link formatDate} this key COLLIDES with a positional parameter of
85
+ * the same name, so the precedence is PINNED, not left to implementation
86
+ * order: **the positional argument wins**, and this key is consulted only
87
+ * when the positional slot is `undefined` (objectui#7745). See
88
+ * {@link formatDate}'s own note for why that direction and not the other.
89
+ *
90
+ * ⚠️ {@link formatRelativeDate} still does NOT read this key — the
91
+ * maintainer's long-run ruling on objectui#7443 names `formatDate` only, and
92
+ * whether the relative path's out-of-window fallback should honour it is a
93
+ * separate, deliberate call (objectui#7745's report).
94
+ */
95
+ style?: string;
96
+ }
97
+ /**
98
+ * A date that exists — the pattern alone would accept `2024-02-31`.
99
+ *
100
+ * `true` only for a date-only ISO string (`YYYY-MM-DD`, the shape
101
+ * {@link ISO_DATE_ONLY_RE} names) whose year, month and day read back
102
+ * unchanged from the calendar. Anything else — another shape, a time part, an
103
+ * out-of-range month, or a day its month does not have — is `false`.
104
+ *
105
+ * ## Why this lives here (objectui#10026)
106
+ *
107
+ * It used to be module-private in `@object-ui/components`' filter builder,
108
+ * which refused `2026-02-30` at the AUTHORING boundary, while this module — a
109
+ * package below it, unable to import it — ROLLED the same value into March 2nd
110
+ * on every display face. One concept, two answers. It moved down, exactly as
111
+ * `formatDate` itself moved into this package (see the header), so the filter
112
+ * builder and {@link toDisplayDate} now ask the one function. ⛔ A move, not a
113
+ * copy: `@object-ui/components` imports it from here.
114
+ *
115
+ * ## Why the engine cannot answer this on its own
116
+ *
117
+ * ECMAScript's date-string parse accepts a DAY of `01`-`31` for every month
118
+ * and rolls the surplus forward: `Date.parse('2026-02-30')` is March 2nd, not
119
+ * `NaN`. It rejects an out-of-range MONTH (`2026-13-01`), which is why a
120
+ * bad month was always a dash on the display path and a bad day never was.
121
+ * So the day is read back instead: build the date in UTC (no zone, so no DST
122
+ * gap can move it) and require all three parts to survive.
123
+ *
124
+ * `setUTCFullYear` rather than `Date.UTC(year, …)`: the latter maps years
125
+ * 0-99 onto 1900+y, so it answered `false` for `0026-08-01` — a real day,
126
+ * and one {@link toDisplayDate} renders (it undoes the same legacy mapping for
127
+ * the same reason). The move had to fix that, or refusing through this
128
+ * function would have dashed every year below 100.
129
+ */
130
+ export declare function isRealCalendarDate(dateOnly: string): boolean;
131
+ /**
132
+ * The ONE `value -> Date` step behind every function below.
133
+ *
134
+ * ## The defect (objectui#10110)
135
+ *
136
+ * ECMAScript parses the two ISO shapes into two different zones: a DATE-ONLY
137
+ * form is UTC, while a date-TIME form without an offset is local. So
138
+ * `new Date('2026-08-01')` is UTC midnight, and every getter this module then
139
+ * uses — `getFullYear`, `getMonth`, `getDate`, and `toLocaleDateString`'s own
140
+ * internal ones — reads it back in the VIEWER's zone. West of UTC that lands
141
+ * on the previous calendar day: `2026-08-01` rendered `Jul 31` for a UTC-7
142
+ * viewer while the stored value, the API response and a UTC+8 viewer all said
143
+ * August 1st. The relative branch shifted with it, one day per day
144
+ * (`2026-08-31` read `4 days ago` on the 3rd instead of `3 days ago`),
145
+ * because it compares two LOCAL start-of-days.
146
+ *
147
+ * ## The repair, and why it is not an offset
148
+ *
149
+ * A date-only value names a CALENDAR DAY and carries no instant, so there is
150
+ * no conversion to perform: this rebuilds it at LOCAL midnight of the day it
151
+ * names, and every local getter downstream then reports that same day in
152
+ * every zone. ⛔ Nothing here adds or subtracts hours. An offset that
153
+ * cancels the shift would be wrong again at the next DST boundary and wrong
154
+ * in the opposite direction for a viewer EAST of UTC, where the UTC-midnight
155
+ * parse already lands on the right day — the co-located suite drives both.
156
+ * `GridField`'s sub-grid cell already parsed its own date-only values this
157
+ * way before reaching `formatDate`; this is that treatment, moved to the one
158
+ * place every caller passes through (the sub-grid reads it from here since
159
+ * objectui#10301).
160
+ *
161
+ * A value with a time part is not rebuilt, in both spellings: it HAS an
162
+ * instant, and rendering an instant in the viewer's zone is the whole point
163
+ * of a `datetime`. The regex is what separates them, so the split is the
164
+ * VALUE's shape and never the field's declared type, which this module (pure,
165
+ * no schema) cannot see.
166
+ *
167
+ * ## What it refuses (objectui#10026)
168
+ *
169
+ * The engine's own parse still decides what is a date at all (`2026-13-01`
170
+ * is an Invalid Date, and so every face below renders `—`), with ONE
171
+ * addition: a date-only value naming a day its month does not have. The
172
+ * engine accepts `2026-02-30` and rolls it into March 2nd, so before this
173
+ * card every date face showed a real day nobody wrote, with nothing to say
174
+ * so. This step hands back an Invalid Date for it instead — the same answer
175
+ * the engine gives a bad month — so every caller renders the face it already
176
+ * renders for an unparsable value: `—` from the functions below, `EmptyValue`
177
+ * from the field carriers that read validity here, the raw stored string from
178
+ * a caller whose unparsable face is the raw string. ⛔ No new marker.
179
+ *
180
+ * The maintainer's ruling on objectui#10026 (option A) placed the refusal on
181
+ * the SHARED path, in this step and not in any one consumer: refusing in a
182
+ * single face would re-create the list-cell-versus-measure split
183
+ * objectui#4576 recorded. {@link isRealCalendarDate} is the one judgement,
184
+ * shared with the filter builder's authoring boundary.
185
+ *
186
+ * A value that carries a TIME is refused the same way when the day it is
187
+ * written on does not exist (objectui#10301): `2026-02-30T10:00:00Z` parses
188
+ * too, and rendered `Mar 2, 2026, 10:00 AM` on every datetime face. Triage
189
+ * graded that an inherited branch of the same ruling. The judgement reads the
190
+ * value's leading `YYYY-MM-DD` AS WRITTEN, never the day its instant lands on
191
+ * in some zone: a parsed `Date` always names a real day, so a check made after
192
+ * any conversion could only miss the refusal, and a real day written with an
193
+ * offset (`2026-02-28T23:30:00-05:00`, March 1st in UTC) is kept. A real
194
+ * date-time is otherwise untouched — no rebuild, the engine's instant.
195
+ *
196
+ * ## Why it is exported (objectui#10183)
197
+ *
198
+ * A caller that formats with its own `Intl` options — a face none of the
199
+ * functions below produce, such as the record summary chip's
200
+ * `dateStyle: 'medium'` — or that compares a value against "today" needs the
201
+ * `Date` itself, not a string. Such callers used to parse the value on their
202
+ * own (`new Date(value)`, or `Date.parse` and then a `Date` handed to
203
+ * `formatDate`, which this step then leaves alone), so the objectui#10110
204
+ * repair never reached them and each still read a date-only value one day
205
+ * early west of UTC. They take the `Date` from here instead.
206
+ *
207
+ * ⛔ Read the result with LOCAL getters or local-zone `Intl` formatting only.
208
+ * For a date-only value it is local midnight of the named day, so its
209
+ * `toISOString()` / UTC getters name the previous day east of UTC — hand
210
+ * those the stored value, never this.
211
+ */
212
+ export declare function toDisplayDate(value: string | Date | number): Date;
213
+ /**
214
+ * THE ONE READ of a stored END, where a bar or span is drawn to
215
+ * (objectui#11141): {@link toDisplayDate}'s read, and then, for a date-only
216
+ * value only, the next day's local midnight.
217
+ *
218
+ * ## The rule (objectui#11112's ruling, one home since objectui#11141)
219
+ *
220
+ * A date-only end is INCLUSIVE: `2024-01-01` to `2024-01-15` runs through
221
+ * January 15th, so the span is drawn to the start of the 16th, and a
222
+ * successor starting `2024-01-16` begins exactly where it ends. A span whose
223
+ * date-only start and end name the same day is one day long, across a DST
224
+ * change too: the step is a calendar day (`setDate`), never 24 hours, so it
225
+ * lands on the next local midnight, or on that day's first hour where its
226
+ * midnight does not exist. That is how a project plan and the schema
227
+ * catalog's gantt plans author an end.
228
+ *
229
+ * The result is the EXCLUSIVE end instant of a half-open span `[start, end)`,
230
+ * the form every gantt surface draws and schedules with. Date-only is decided
231
+ * by the value's own shape, with {@link isRealCalendarDate}, exactly as
232
+ * {@link toDisplayDate} decides it, so an end reads its day as a start does and
233
+ * then runs to that day's end. A value with a time part, a number or a `Date`
234
+ * is an instant: the span ends at it, and it is handed back as
235
+ * {@link toDisplayDate} hands it back.
236
+ *
237
+ * {@link toInclusiveEndDay} is the exact inverse: it names the day a span
238
+ * ending here runs through, so a read and a write of a date-only end agree.
239
+ *
240
+ * ⛔ One rule, one place: `plugin-timeline`'s gantt variant and
241
+ * `plugin-gantt` both read their ends here. A second copy of the step in a
242
+ * consumer is how the two gantt surfaces came to draw one plan a day apart.
243
+ * ⛔ Read the result with LOCAL getters only, as {@link toDisplayDate}'s is.
244
+ */
245
+ export declare function toDisplayEndDate(value: string | Date | number): Date;
246
+ /**
247
+ * The day a span ending at `end` runs through: local midnight of the day that
248
+ * holds the last instant before `end` (objectui#11141).
249
+ *
250
+ * This is the exact inverse of {@link toDisplayEndDate} on a date-only end:
251
+ * the instant it reads `2024-01-15` as, local midnight of the 16th, names the
252
+ * 15th here, so a read, a drag and a write of a stored date-only end leave it
253
+ * the day it was, and a bar dragged to end at a day's local midnight names the
254
+ * day BEFORE it. An end inside a day (a `datetime` end, or a shift band's
255
+ * edge) names that day, the last one the span reaches into.
256
+ *
257
+ * It names a day for display and for a date-only write. ⛔ It is not a read of
258
+ * a stored value, and a `datetime` end still keeps its own instant: hand this
259
+ * only to a face that names a day, or to a field that stores one. Read the
260
+ * result with LOCAL getters only; an Invalid Date stays invalid.
261
+ */
262
+ export declare function toInclusiveEndDay(end: Date): Date;
263
+ /**
264
+ * Format date as relative time (e.g., "3 days ago", "Today", "Overdue 3d"),
265
+ * localized via `Intl.RelativeTimeFormat` (objectstack-ai/objectstack#3040).
266
+ *
267
+ * `dueLike` gates the "Overdue" wording — a past `start_date`/`created_at`
268
+ * isn't overdue, only a past due/deadline-semantic field is. Non-due-like
269
+ * past dates render as plain "N days ago" instead. The overdue phrase has no
270
+ * `Intl` equivalent, so it resolves through `options.t` (key
271
+ * `fields.relativeDate.overdue`) with an English fallback.
272
+ */
273
+ export declare function formatRelativeDate(value: string | Date | number, options?: DateDisplayOptions): string;
274
+ /**
275
+ * Format date value.
276
+ *
277
+ * The named face comes from EITHER spelling — the positional `style`
278
+ * parameter or `options.style` — and the precedence between them is pinned
279
+ * (objectui#7745):
280
+ *
281
+ * > **The positional argument wins. `options.style` is consulted only when the
282
+ * > positional slot is `undefined`.**
283
+ *
284
+ * Before #7745 only the positional spelling was read here, while
285
+ * {@link formatDateTime} read only the `options` one — one shared bag, two
286
+ * spellings for one concept, and on THIS function the options spelling did
287
+ * nothing at all: `formatDate(v, undefined, { style: 'short' })` silently
288
+ * rendered the default face with no diagnostic. Reading the key is the
289
+ * additive half of the maintainer's long-run ruling on objectui#7443.
290
+ *
291
+ * Why the positional wins, and not the newer key:
292
+ *
293
+ * - It is the ONLY direction that is purely additive. It fires exactly on
294
+ * the input that is a silent no-op today (positional absent, key present);
295
+ * every call that renders a face today renders the same face after.
296
+ * - The bag is SHARED across three functions, so it can legitimately carry a
297
+ * key meant for a sibling — that is this module's convention (`dueLike`
298
+ * and `t` are read by `formatRelativeDate` alone). A caller that built
299
+ * `{ style: 'compact', locale }` for `formatDateTime` and reused the bag
300
+ * for `formatDate(v, 'short', bag)` must keep its short face. A key aimed
301
+ * at a sibling function must not outrank an argument written for THIS
302
+ * call — that is objectui#7694's shape (an alias overwriting the canonical
303
+ * key), and the silent-override half of objectui#4272.
304
+ *
305
+ * `??`, not `||`, is what "absent" means here: `formatDate(v, '', bag)`
306
+ * renders the default face today and must keep doing so, so an empty string
307
+ * counts as GIVEN and does not fall through to the key.
308
+ */
309
+ export declare function formatDate(value: string | Date | number, style?: string, options?: DateDisplayOptions): string;
310
+ /**
311
+ * The `'compact'` datetime face as the two halves a grid cell paints
312
+ * separately — `7/4/2024` and `7:00 am` for `2024-07-04T07:00:00Z` in `en-US`.
313
+ *
314
+ * `formatDateTime(value, { style: 'compact', ...options })` is exactly
315
+ * `date + ' ' + time` of what this returns, so a caller that wants the face
316
+ * as ONE string and a caller that wants to style the halves differently
317
+ * cannot drift apart. That drift is what objectui#7443 recorded:
318
+ * `DateTimeCellRenderer` inlined these two option bags and never called this
319
+ * module, so `datetime` had two display conventions while `date` had one —
320
+ * the same shape as objectui#4576, which this repo has already paid for once.
321
+ *
322
+ * `null` for a value this module renders as `'—'`; the cell renders its own
323
+ * empty state for those, so it never sees the dash.
324
+ */
325
+ export declare function formatDateTimeCompactParts(value: string | Date | number, options?: DateDisplayOptions): {
326
+ date: string;
327
+ time: string;
328
+ } | null;
329
+ /**
330
+ * Format datetime value.
331
+ *
332
+ * `options.style` selects a named face:
333
+ *
334
+ * - `'compact'` — the dense grid face, `7/4/2024 7:00 am` in `en-US`. It is
335
+ * what every `datetime` CELL renders, and what `DateTimeCellRenderer`
336
+ * used to build from its own inlined `Intl` bags (objectui#7443).
337
+ * - anything else, including absent — the verbose default,
338
+ * `Jul 4, 2024, 07:00 AM` in `en-US`. Unchanged, and still what a
339
+ * non-cell caller (dataset measure, gantt tooltip, data-table) gets.
340
+ *
341
+ * The signature is `(value, options?)`, unchanged: `style` is a key of
342
+ * `options`, not a positional parameter, so every existing call —
343
+ * `formatDateTime(v, { locale })` included — keeps meaning exactly what it
344
+ * meant (see the note on `DateDisplayOptions.style` for why the positional
345
+ * shape `formatDate` uses was refused here).
346
+ *
347
+ * `options` is optional, so a caller that passes nothing keeps the exact
348
+ * runtime-default behavior it had. Before objectui#4272 the parameter did not
349
+ * exist at all, which meant no caller could localize this function however
350
+ * hard it tried — it always handed `Intl` an `undefined` tag, i.e. the
351
+ * MACHINE's locale, which is neither of the repo's two locale channels.
352
+ * Callers should pass the tag from `useDisplayLocale()`.
353
+ */
354
+ export declare function formatDateTime(value: string | Date | number, options?: DateDisplayOptions): string;