@object-ui/plugin-detail 17.6.0 → 17.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6741 -0
- package/README.md +404 -71
- package/dist/ActivityTimeline.d.ts.map +1 -1
- package/dist/CommentAttachment.d.ts.map +1 -1
- package/dist/ConcurrentUpdateDialog.d.ts +17 -1
- package/dist/ConcurrentUpdateDialog.d.ts.map +1 -1
- package/dist/DetailSection.d.ts.map +1 -1
- package/dist/DetailSectionNode.d.ts +97 -0
- package/dist/DetailSectionNode.d.ts.map +1 -0
- package/dist/DetailView.d.ts.map +1 -1
- package/dist/HeaderHighlight.d.ts.map +1 -1
- package/dist/HistoryTimeline.d.ts +8 -1
- package/dist/HistoryTimeline.d.ts.map +1 -1
- package/dist/InlineEditSaveBar.d.ts +68 -0
- package/dist/InlineEditSaveBar.d.ts.map +1 -1
- package/dist/InlineFieldInput.d.ts +79 -6
- package/dist/InlineFieldInput.d.ts.map +1 -1
- package/dist/ReactionPicker.d.ts.map +1 -1
- package/dist/RecordActivityTimeline.d.ts +19 -4
- package/dist/RecordActivityTimeline.d.ts.map +1 -1
- package/dist/RecordChatterPanel.d.ts +6 -1
- package/dist/RecordChatterPanel.d.ts.map +1 -1
- package/dist/RecordComments.d.ts +1 -0
- package/dist/RecordComments.d.ts.map +1 -1
- package/dist/RecordDetailDrawer.d.ts +20 -6
- package/dist/RecordDetailDrawer.d.ts.map +1 -1
- package/dist/RecordDetailPanel.d.ts +101 -0
- package/dist/RecordDetailPanel.d.ts.map +1 -0
- package/dist/RecordMetaFooter.d.ts +1 -1
- package/dist/RecordMetaFooter.d.ts.map +1 -1
- package/dist/RelatedList.d.ts +83 -10
- package/dist/RelatedList.d.ts.map +1 -1
- package/dist/ThreadedReplies.d.ts +1 -1
- package/dist/ThreadedReplies.d.ts.map +1 -1
- package/dist/emptiness.d.ts +142 -0
- package/dist/emptiness.d.ts.map +1 -0
- package/dist/fieldEnrichment.d.ts +44 -4
- package/dist/fieldEnrichment.d.ts.map +1 -1
- package/dist/headerColor.d.ts +20 -0
- package/dist/headerColor.d.ts.map +1 -0
- package/dist/index.d.ts +94 -77
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4883 -5255
- package/dist/index.umd.cjs +2 -5
- package/dist/renderers/record-activity.d.ts.map +1 -1
- package/dist/renderers/record-alert.d.ts +23 -3
- package/dist/renderers/record-alert.d.ts.map +1 -1
- package/dist/renderers/record-alert.readProps.d.ts +40 -0
- package/dist/renderers/record-alert.readProps.d.ts.map +1 -0
- package/dist/renderers/record-chatter.d.ts.map +1 -1
- package/dist/renderers/record-details.d.ts +2 -0
- package/dist/renderers/record-details.d.ts.map +1 -1
- package/dist/renderers/record-highlights.d.ts.map +1 -1
- package/dist/renderers/record-history.d.ts +1 -1
- package/dist/renderers/record-history.d.ts.map +1 -1
- package/dist/renderers/record-path.d.ts.map +1 -1
- package/dist/renderers/record-quick-actions.d.ts +16 -6
- package/dist/renderers/record-quick-actions.d.ts.map +1 -1
- package/dist/renderers/record-reference-rail.d.ts +40 -0
- package/dist/renderers/record-reference-rail.d.ts.map +1 -1
- package/dist/renderers/record-related-list.d.ts +37 -3
- package/dist/renderers/record-related-list.d.ts.map +1 -1
- package/dist/renderers/recordActivityFeed.d.ts +272 -20
- package/dist/renderers/recordActivityFeed.d.ts.map +1 -1
- package/dist/renderers/recordComponentAria.d.ts +44 -0
- package/dist/renderers/recordComponentAria.d.ts.map +1 -0
- package/dist/renderers/relatedListActions.d.ts +102 -0
- package/dist/renderers/relatedListActions.d.ts.map +1 -0
- package/dist/summaryChipPercent.d.ts +83 -0
- package/dist/summaryChipPercent.d.ts.map +1 -0
- package/dist/summaryChipRenderers.d.ts +83 -0
- package/dist/summaryChipRenderers.d.ts.map +1 -0
- package/dist/synth/buildDefaultPageSchema.d.ts +98 -17
- package/dist/synth/buildDefaultPageSchema.d.ts.map +1 -1
- package/dist/useDetailTranslation.d.ts.map +1 -1
- package/dist/useRecordEditable.d.ts +1 -1
- package/dist/useRecordEditable.d.ts.map +1 -1
- package/package.json +19 -18
- package/dist/CommentInput.d.ts +0 -24
- package/dist/CommentInput.d.ts.map +0 -1
- package/dist/DiffView.d.ts +0 -24
- package/dist/DiffView.d.ts.map +0 -1
- package/dist/InlineCreateRelated.d.ts +0 -32
- package/dist/InlineCreateRelated.d.ts.map +0 -1
- package/dist/MentionAutocomplete.d.ts +0 -43
- package/dist/MentionAutocomplete.d.ts.map +0 -1
- package/dist/PointInTimeRestore.d.ts +0 -28
- package/dist/PointInTimeRestore.d.ts.map +0 -1
- package/dist/RecordNavigationEnhanced.d.ts +0 -18
- package/dist/RecordNavigationEnhanced.d.ts.map +0 -1
- package/dist/RelationshipGraph.d.ts +0 -23
- package/dist/RelationshipGraph.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FeedItem, FeedItemType } from '@object-ui/types';
|
|
2
|
-
import { FeedFilterMode } from '../RecordActivityTimeline';
|
|
2
|
+
import { FeedFilterMode } from '../RecordActivityTimeline.js';
|
|
3
3
|
/** Spec default for `RecordActivityProps.limit`. */
|
|
4
4
|
export declare const DEFAULT_ACTIVITY_LIMIT = 20;
|
|
5
5
|
/**
|
|
@@ -56,16 +56,134 @@ export declare const DEFAULT_ACTIVITY_LIMIT = 20;
|
|
|
56
56
|
* `showCompleted`; a not-yet-held meeting is `scheduled` → `event`, shown,
|
|
57
57
|
* because an upcoming meeting is the part of a timeline you still act on.
|
|
58
58
|
*
|
|
59
|
-
*
|
|
60
|
-
* this block's to make — filed as objectstack#11424. Until it is ruled, the
|
|
61
|
-
* honest statement of this table is the one the test now pins: the upstream
|
|
62
|
-
* declaration PLUS the values a shipped producer measurably writes.
|
|
59
|
+
* ## The vocabulary is OPEN — ruled. Do NOT restore set-equality.
|
|
63
60
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
61
|
+
* Maintainer ruling of 2026-08-24 (objectstack `88b9d749a`), **direction 4**:
|
|
62
|
+
* `sys_activity.type` is AUTHOR-EXTENSIBLE. The declared select options are the
|
|
63
|
+
* platform's BUILT-IN set, not the column's domain, and the two facts above are
|
|
64
|
+
* why — readonly fields are never validated on write, and ADR-0052 §5b.2
|
|
65
|
+
* forwards an author's `activityMilestones[].type` into the column verbatim.
|
|
66
|
+
*
|
|
67
|
+
* So the relation this table stands in is a SUPERSET, in one direction only:
|
|
68
|
+
*
|
|
69
|
+
* - **map ⊇ built-ins** — every value the platform declares has an entry here,
|
|
70
|
+
* either a feed type or a deliberate `undefined` exclusion. A new built-in
|
|
71
|
+
* with no entry is a gap, and objectui#5969's pin turns red for it.
|
|
72
|
+
* - **NOT built-ins ⊇ map**, and NOT set-equality in either spelling. An
|
|
73
|
+
* author-extended value legitimately exists outside the declaration, so a
|
|
74
|
+
* pin that required the two sets to match would be false by construction.
|
|
75
|
+
*
|
|
76
|
+
* ⛔ A reader who finds no equality check here is looking at a DECISION, not an
|
|
77
|
+
* omission: objectui#5840 removed the old set-equality pin on purpose, because
|
|
78
|
+
* pinning to the closed declaration meant dropping stored rows, and
|
|
79
|
+
* objectui#5969 replaced it with the two-directional pin under this ruling.
|
|
80
|
+
*
|
|
81
|
+
* (`scheduled` — the value #5840 was about — has since been declared upstream
|
|
82
|
+
* by objectstack#11522, superseding objectstack#11424. That is precisely the
|
|
83
|
+
* drift a hand-maintained equality pin cannot survive, and the reason the pin
|
|
84
|
+
* is a superset assertion plus a fallback rather than a census of two groups.)
|
|
85
|
+
*
|
|
86
|
+
* A value outside this table is NO LONGER DROPPED: it renders through
|
|
87
|
+
* {@link UNMAPPED_ACTIVITY_FEED_TYPE}. See {@link activityRowToFeedItem}.
|
|
67
88
|
*/
|
|
68
89
|
export declare const ACTIVITY_TYPE_TO_FEED_TYPE: Readonly<Record<string, FeedItemType | undefined>>;
|
|
90
|
+
/**
|
|
91
|
+
* The presentation an `sys_activity.type` value outside
|
|
92
|
+
* {@link ACTIVITY_TYPE_TO_FEED_TYPE} renders through.
|
|
93
|
+
*
|
|
94
|
+
* The second half of the direction-4 ruling (2026-08-24, objectstack `88b9d749a`): if
|
|
95
|
+
* the column is author-extensible, then a value this map has never heard of is
|
|
96
|
+
* REAL RECORD ACTIVITY that an author extended the platform with — not a
|
|
97
|
+
* mistake — and dropping it is the objectui#5840 failure mode reappearing for
|
|
98
|
+
* every author who ever writes one. Stored, queryable, invisible.
|
|
99
|
+
*
|
|
100
|
+
* `system` is the generic bucket rather than a new feed type because
|
|
101
|
+
* `FeedItemType` is a CLOSED spec enum owned by `@objectstack/spec` — minting a
|
|
102
|
+
* kind for "we don't know" is a platform change, not this block's.
|
|
103
|
+
*
|
|
104
|
+
* ⚠️ This is a FLOOR under the map, never a substitute for it. objectui#5840
|
|
105
|
+
* rejected a catch-all *offered as the fix* — an unmeasured type rendering as
|
|
106
|
+
* `system` is not the same data as a type someone read and mapped. What makes
|
|
107
|
+
* the catch-all safe here is that it does not stand alone: the superset pin
|
|
108
|
+
* above forces every built-in to keep its OWN presentation, so the fallback can
|
|
109
|
+
* only ever receive values nobody has ruled on yet, and the diagnostic below
|
|
110
|
+
* names each one so somebody can.
|
|
111
|
+
*/
|
|
112
|
+
export declare const UNMAPPED_ACTIVITY_FEED_TYPE: FeedItemType;
|
|
113
|
+
/**
|
|
114
|
+
* Feed kinds an ObjectUI surface produces WITHOUT going through
|
|
115
|
+
* {@link ACTIVITY_TYPE_TO_FEED_TYPE}.
|
|
116
|
+
*
|
|
117
|
+
* Exactly one today: `comment`, built from `sys_comment` rows by app-shell's
|
|
118
|
+
* `RecordDetailView` (the `sys_comment` read, and the two optimistic rows the
|
|
119
|
+
* composer writes) and handed to this block through `DiscussionContext`. It
|
|
120
|
+
* cannot be derived here — app-shell depends on this package, not the other way
|
|
121
|
+
* round — so it is DECLARED, and `feedTypeProducerCensus-5877.test.ts` re-runs
|
|
122
|
+
* the census over the repository so the declaration cannot go stale silently.
|
|
123
|
+
*
|
|
124
|
+
* ## Census, and the pathspec it was taken over (objectui#5877)
|
|
125
|
+
*
|
|
126
|
+
* Every `.ts` / `.tsx` file in the repository that is not a test, at every top
|
|
127
|
+
* level (`packages/`, `apps/`, `examples/`, `scripts/`, `e2e/`), narrowed to the
|
|
128
|
+
* files that mention `FeedItem` at all — you cannot construct one without
|
|
129
|
+
* naming the type — then read for `FeedItemType` literals. 1622 files scanned,
|
|
130
|
+
* 13 mention `FeedItem`, one produces a kind off this map. A census is only as
|
|
131
|
+
* wide as its pathspec, so the pathspec is stated rather than implied, and the
|
|
132
|
+
* test above holds it.
|
|
133
|
+
*
|
|
134
|
+
* ⛔ NOT counted, deliberately: app-shell's `sharedUserFeeds.ts` /
|
|
135
|
+
* `activityItemType.ts` read the same `sys_activity` rows but produce
|
|
136
|
+
* `ActivityItemType` (`create` / `update` / `delete` / `comment` / `system`), a
|
|
137
|
+
* DIFFERENT five-value vocabulary that is not a projection of this one in either
|
|
138
|
+
* direction (objectui#6730 records why converging them costs rows). A row it
|
|
139
|
+
* turns into an `ActivityItem` never becomes a `FeedItem`, so it produces
|
|
140
|
+
* nothing for this feed. `ActivityEntry` in `@object-ui/types` is a third
|
|
141
|
+
* vocabulary again, and has no producer at all.
|
|
142
|
+
*
|
|
143
|
+
* ⚠️ Also NOT counted, and the reason the diagnostic below names it: a HOST can
|
|
144
|
+
* hand this block a feed of its own (`items` on the node, or a
|
|
145
|
+
* `DiscussionContext` it mounts itself). Those items are produced outside this
|
|
146
|
+
* repository, so no census taken here can bound their kinds.
|
|
147
|
+
*/
|
|
148
|
+
export declare const FEED_TYPES_PRODUCED_OFF_MAP: readonly FeedItemType[];
|
|
149
|
+
/**
|
|
150
|
+
* Feed kinds this repository has decided NOT to adopt — as opposed to kinds
|
|
151
|
+
* nothing happens to produce.
|
|
152
|
+
*
|
|
153
|
+
* The distinction matters more than the diagnostic that uses it. Reporting a
|
|
154
|
+
* decision as a defect is how a warning channel gets trained out of an author's
|
|
155
|
+
* attention, and these three are decisions: `created` / `deleted` / `shared`
|
|
156
|
+
* rows are mapped to `field_change` ON PURPOSE, because `RecordDetailView` and
|
|
157
|
+
* this block must agree about what a `created` row IS before either can move to
|
|
158
|
+
* the richer kind. Adopting them is a change to that shared map, not to this
|
|
159
|
+
* block. The reasoning is written out at {@link ACTIVITY_TYPE_TO_FEED_TYPE}.
|
|
160
|
+
*
|
|
161
|
+
* ⚠️ This list is a TRANSCRIPTION of that prose, not a derivation, and there is
|
|
162
|
+
* no way to make it one: the decision exists as a comment, and a comment is not
|
|
163
|
+
* machine-readable. Two consequences, both load-bearing:
|
|
164
|
+
*
|
|
165
|
+
* 1. it is only as true as the prose it was copied from, so it is edited
|
|
166
|
+
* together with that prose and never on its own;
|
|
167
|
+
* 2. a kind that is NOT on this list is not thereby known to be an oversight.
|
|
168
|
+
* It is only known to have no producer. Whether somebody decided against it
|
|
169
|
+
* and did not write it down is not recorded anywhere this code can read, and
|
|
170
|
+
* the message below says so rather than guessing.
|
|
171
|
+
*
|
|
172
|
+
* ⛔ Do not extend it by inference. A kind belongs here when a decision about it
|
|
173
|
+
* is written down, not when its absence looks deliberate.
|
|
174
|
+
*/
|
|
175
|
+
export declare const DELIBERATELY_UNADOPTED_FEED_TYPES: readonly FeedItemType[];
|
|
176
|
+
/**
|
|
177
|
+
* Every feed kind some ObjectUI surface can put on a record feed.
|
|
178
|
+
*
|
|
179
|
+
* DERIVED from the producers themselves — the map's range, its fallback, and
|
|
180
|
+
* the declared off-map producer above — never a second hand-written list of
|
|
181
|
+
* kinds. Giving an unproduced kind a producer (one new entry in
|
|
182
|
+
* {@link ACTIVITY_TYPE_TO_FEED_TYPE}) therefore retires its diagnostic in the
|
|
183
|
+
* same edit, with nothing else to remember. A hand-kept copy would not, and
|
|
184
|
+
* that copy is exactly what this file's header records the cost of.
|
|
185
|
+
*/
|
|
186
|
+
export declare const PRODUCED_FEED_TYPES: ReadonlySet<FeedItemType>;
|
|
69
187
|
/** A row as `sys_activity` returns it. Loose on purpose: the block reads a
|
|
70
188
|
* system table it does not own, and an unknown column is not an error. */
|
|
71
189
|
export interface SysActivityRow {
|
|
@@ -80,6 +198,12 @@ export interface SysActivityRow {
|
|
|
80
198
|
source_id?: string | number | null;
|
|
81
199
|
[k: string]: unknown;
|
|
82
200
|
}
|
|
201
|
+
/** Test seam: forget which `types` entries have already been named. */
|
|
202
|
+
export declare function resetUnrecognisedFeedTypeWarnings(): void;
|
|
203
|
+
/** Test seam: forget which unproduced `types` entries have already been named. */
|
|
204
|
+
export declare function resetUnproducedFeedTypeWarnings(): void;
|
|
205
|
+
/** Test seam: forget which `filterMode` values have already been named. */
|
|
206
|
+
export declare function resetUnrecognisedFilterModeWarnings(): void;
|
|
83
207
|
/**
|
|
84
208
|
* Coerce an authored `filterMode` to a value the timeline understands.
|
|
85
209
|
*
|
|
@@ -87,10 +211,40 @@ export interface SysActivityRow {
|
|
|
87
211
|
* `<Select>` handed a value with no matching item renders blank and the
|
|
88
212
|
* dropdown reads as broken. Same posture as objectui#3151 — an unrecognised
|
|
89
213
|
* filter token is skipped, never turned into a filter that can't match.
|
|
214
|
+
*
|
|
215
|
+
* ## Why that fallback needs a diagnostic (objectui#5891)
|
|
216
|
+
*
|
|
217
|
+
* `'all'` is the WIDEST of the four declared modes — `filterItems` in
|
|
218
|
+
* `RecordActivityTimeline` narrows to ONE feed type for each of the other three
|
|
219
|
+
* and returns the feed untouched for `'all'` — so every unrecognised value
|
|
220
|
+
* lands on the one option that shows the author MORE than they asked for. A
|
|
221
|
+
* near-miss like `comments-only` or `commentsOnly` therefore opens the panel on
|
|
222
|
+
* the unfiltered stream, and the tell is a PLAUSIBLE result (a populated
|
|
223
|
+
* timeline) rather than an empty one that gets investigated. That is the same
|
|
224
|
+
* shape objectui#5841 removed from the sibling `types` sanitiser.
|
|
225
|
+
*
|
|
226
|
+
* The ruling on this card (triage, 2026-08-25) is that the defect is the
|
|
227
|
+
* INVISIBILITY, not the fallback: `filterMode` seeds a control the user can
|
|
228
|
+
* change, and there is no defensible narrower default to fall back to instead.
|
|
229
|
+
* So nothing that renders changes here — what changes is that the fold is now
|
|
230
|
+
* SAID OUT LOUD, once per distinct offending value on each block (see
|
|
231
|
+
* {@link warnOnce}).
|
|
232
|
+
*
|
|
233
|
+
* `block` is the registered name of the block the value was authored on
|
|
234
|
+
* (`record:activity`, `record:chatter`, `record:discussion`). It is REQUIRED,
|
|
235
|
+
* not defaulted: the message is addressed to that block's author, and a default
|
|
236
|
+
* would hand every caller that forgot it some other block's name — the defect
|
|
237
|
+
* objectui#9557 removed.
|
|
238
|
+
*
|
|
239
|
+
* Absent (`undefined` / `null`) is silent: no `filterMode` was authored, which
|
|
240
|
+
* is not a mistake, and a warning about a decision teaches authors to ignore
|
|
241
|
+
* the channel. Only a value the author actually wrote is reported.
|
|
242
|
+
*
|
|
243
|
+
* The declared modes named in the message are read from `@objectstack/spec`'s
|
|
244
|
+
* `FeedFilterMode` at runtime, never re-typed here — see the file header for
|
|
245
|
+
* what a hand copy of a spec enum cost.
|
|
90
246
|
*/
|
|
91
|
-
export declare function normalizeFilterMode(value: unknown): FeedFilterMode;
|
|
92
|
-
/** Test seam: forget which `types` entries have already been named. */
|
|
93
|
-
export declare function resetUnrecognisedFeedTypeWarnings(): void;
|
|
247
|
+
export declare function normalizeFilterMode(value: unknown, block: string): FeedFilterMode;
|
|
94
248
|
/**
|
|
95
249
|
* Sanitise an authored `types` allow-list. Narrowing or refusal, never widening.
|
|
96
250
|
*
|
|
@@ -103,6 +257,7 @@ export declare function resetUnrecognisedFeedTypeWarnings(): void;
|
|
|
103
257
|
* | `[]` | `[]` | nothing — the author said "no kinds" |
|
|
104
258
|
* | `['crm_task']` (none known) | `[]` | nothing, plus one diagnostic |
|
|
105
259
|
* | `['task', 'crm_task']` | `['task']` | the recognised members, plus one diagnostic |
|
|
260
|
+
* | `['approval']` (no producer) | `['approval']` | nothing, plus one diagnostic — the kind is declared and honoured, but nothing emits it (objectui#5877) |
|
|
106
261
|
*
|
|
107
262
|
* `undefined` now means "no `types` key was authored" and ONLY that. It used to
|
|
108
263
|
* mean that OR "everything you authored was dropped", and {@link applyFeedConfig}
|
|
@@ -121,13 +276,57 @@ export declare function resetUnrecognisedFeedTypeWarnings(): void;
|
|
|
121
276
|
* Membership is read from `@objectstack/spec`'s `FeedItemType` at runtime, never
|
|
122
277
|
* re-typed here — see the file header for what a hand copy of a spec enum cost.
|
|
123
278
|
*
|
|
124
|
-
* NOT pure
|
|
125
|
-
*
|
|
126
|
-
* the fix rather than a nicety
|
|
279
|
+
* NOT pure, on TWO independent channels (see {@link warnOnce}) — the failure
|
|
280
|
+
* being repaired is invisibility in both cases, so the diagnostics are the other
|
|
281
|
+
* half of the fix rather than a nicety:
|
|
282
|
+
*
|
|
283
|
+
* - an entry it cannot recognise logs once (no declared kind matches it);
|
|
284
|
+
* - a RECOGNISED entry that no producer emits logs once as well, on its own
|
|
285
|
+
* channel — see {@link warnUnproducedFeedTypes}. That one changes nothing
|
|
286
|
+
* about the return value: the kind is declared, so it is kept and honoured.
|
|
287
|
+
*
|
|
288
|
+
* Both channels name, and dedupe per, the REQUIRED `block` the list was
|
|
289
|
+
* authored on — see {@link normalizeFilterMode} for why it has no default.
|
|
290
|
+
*/
|
|
291
|
+
export declare function normalizeFeedTypes(value: unknown, block: string): FeedItemType[] | undefined;
|
|
292
|
+
/**
|
|
293
|
+
* The ONE resolver for this block's row cap (objectui#10096, objectui#10145).
|
|
294
|
+
*
|
|
295
|
+
* A refused value is dropped for this block's own default.
|
|
296
|
+
*
|
|
297
|
+
* ⛔ Not `Math.floor`, which objectui#10096 replaced: flooring REPAIRED an
|
|
298
|
+
* authored `2.5` into a two-row window and handed it back as a result, so the
|
|
299
|
+
* author got a silently different number than the one they wrote. Refusing and
|
|
300
|
+
* defaulting is the answer the sibling `record:history` gives through
|
|
301
|
+
* `normalizeHistoryLimit`, and the answer objectui#9925 landed at three further
|
|
302
|
+
* read points (all three test `typeof value === 'number'` first, as this does).
|
|
303
|
+
*
|
|
304
|
+
* `NaN` and both infinities are refused (not integers); `0` and negatives are
|
|
305
|
+
* refused (not positive); `undefined` is the unauthored case and resolves to
|
|
306
|
+
* the default without being a refusal.
|
|
307
|
+
*
|
|
308
|
+
* ⚠️ FAIL-SOFT on purpose: throwing would take out a record page over one
|
|
309
|
+
* declaration. It is NOT silent — the renderers that call this state every
|
|
310
|
+
* refusal through `describeRefusedFeedLimit` (objectui#10097 ruled "always
|
|
311
|
+
* warn" for the family; objectui#10145 extends the refused set to non-numbers).
|
|
312
|
+
* This function stays pure so it can run on every render.
|
|
313
|
+
*
|
|
314
|
+
* ⭐ Shared with `record:chatter` / `record:discussion`, which resolve
|
|
315
|
+
* `feed.limit` through this same function — `RecordChatterProps.feed` is
|
|
316
|
+
* `RecordActivityProps`, so it is the same declared member and the same
|
|
317
|
+
* refusal.
|
|
127
318
|
*/
|
|
128
|
-
export declare function normalizeFeedTypes(value: unknown): FeedItemType[] | undefined;
|
|
129
|
-
/** Coerce `limit` to a positive integer, falling back to the spec default. */
|
|
130
319
|
export declare function normalizeLimit(value: unknown): number;
|
|
320
|
+
/**
|
|
321
|
+
* The diagnostic half of the row-cap refusal for the blocks that resolve
|
|
322
|
+
* through `normalizeLimit` (`record:activity`, `record:chatter`,
|
|
323
|
+
* `record:discussion`). `null` means "nothing to say": an absent `limit`
|
|
324
|
+
* (`undefined` / `null`) is not a mistake, and a usable one is not either.
|
|
325
|
+
*
|
|
326
|
+
* Callers fire it from an effect keyed on the declaration — the channel
|
|
327
|
+
* objectui#9925 uses at its three read points — never from render.
|
|
328
|
+
*/
|
|
329
|
+
export declare function describeRefusedFeedLimit(block: string, authored: unknown): string | null;
|
|
131
330
|
/**
|
|
132
331
|
* Timestamp of a `sys_activity` row.
|
|
133
332
|
*
|
|
@@ -143,9 +342,18 @@ export declare function resetUnknownActivityTypeWarnings(): void;
|
|
|
143
342
|
* One `sys_activity` row → one {@link FeedItem}, or `null` when the row is not
|
|
144
343
|
* record activity (see {@link ACTIVITY_TYPE_TO_FEED_TYPE}).
|
|
145
344
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
345
|
+
* Three outcomes, and the difference between the last two is the whole of the
|
|
346
|
+
* direction-4 ruling (2026-08-24, objectstack `88b9d749a`):
|
|
347
|
+
*
|
|
348
|
+
* - a type mapped to a feed type renders with THAT presentation;
|
|
349
|
+
* - a type the table maps to `undefined` is a DELIBERATE exclusion — `null`,
|
|
350
|
+
* quietly, because a warning about a decision teaches authors to ignore the
|
|
351
|
+
* channel;
|
|
352
|
+
* - a type the table does not contain at all is an AUTHOR-EXTENDED value under
|
|
353
|
+
* the ruled open vocabulary. It renders through
|
|
354
|
+
* {@link UNMAPPED_ACTIVITY_FEED_TYPE} and says so once. It used to return
|
|
355
|
+
* `null` here, which made every extended value invisible — the same outcome
|
|
356
|
+
* objectui#5840 was filed for, reached by a different route.
|
|
149
357
|
*/
|
|
150
358
|
export declare function activityRowToFeedItem(row: SysActivityRow, systemActorLabel: string): FeedItem | null;
|
|
151
359
|
/** The subset of `RecordActivityProps` that decides which items survive. */
|
|
@@ -173,8 +381,52 @@ export interface AppliedFeed {
|
|
|
173
381
|
* `pageSize` is the effective window (`limit` on first render, grown by
|
|
174
382
|
* "Load more"); it is separate from `config.limit` so paging does not have to
|
|
175
383
|
* rewrite the authored config.
|
|
384
|
+
*
|
|
385
|
+
* `block` is the registered name of the block whose config this is; the
|
|
386
|
+
* `types` diagnostics are addressed to it (objectui#9557, see
|
|
387
|
+
* {@link normalizeFilterMode}).
|
|
176
388
|
*/
|
|
177
|
-
export declare function applyFeedConfig(items: readonly FeedItem[], config: FeedConfigFilters, pageSize: number): AppliedFeed;
|
|
389
|
+
export declare function applyFeedConfig(items: readonly FeedItem[], config: FeedConfigFilters, pageSize: number, block: string): AppliedFeed;
|
|
178
390
|
/** Sort a feed chronologically and de-duplicate by id (feeds are append-only). */
|
|
179
391
|
export declare function mergeFeedItems(...groups: readonly FeedItem[][]): FeedItem[];
|
|
392
|
+
/**
|
|
393
|
+
* Whether a rejected feed read — `sys_activity` or `sys_comment` — was REFUSED
|
|
394
|
+
* (objectui#11195): the server answered, and the answer was "not for you".
|
|
395
|
+
*
|
|
396
|
+
* A refused read and an empty read are different answers about the record, and
|
|
397
|
+
* the panel used to give both the same one. Every failure on the feed landed on
|
|
398
|
+
* `No activity recorded` / `No comments yet`, so a member the server refused
|
|
399
|
+
* read a permission wall as a record where nothing had happened. The panel now
|
|
400
|
+
* shows a no-permission state for a refused read instead, and keeps the empty
|
|
401
|
+
* state for a read that answered with zero rows.
|
|
402
|
+
*
|
|
403
|
+
* The verdict is `classifyLoadError`'s (`@object-ui/react`), the read
|
|
404
|
+
* classifier `ListView`'s error panel and `RecordAttachmentsPanel` already
|
|
405
|
+
* share. Nothing here reads a status or a code of its own. Refused means the
|
|
406
|
+
* two kinds that are about the caller:
|
|
407
|
+
*
|
|
408
|
+
* - `forbidden`: 403, or a `PERMISSION_DENIED` / `FORBIDDEN` envelope;
|
|
409
|
+
* - `unauthorized`: 401, or `UNAUTHORIZED` / `UNAUTHENTICATED`.
|
|
410
|
+
*
|
|
411
|
+
* ⚠️ The 401 half is a deliberate difference from `RecordAttachmentsPanel`,
|
|
412
|
+
* whose `denied` state does not claim a 401. The triage on objectui#11195 ruled
|
|
413
|
+
* it for this panel: any refused read (401 / 403, or a permission envelope)
|
|
414
|
+
* shows the no-permission state.
|
|
415
|
+
*
|
|
416
|
+
* NOT refused, so these keep today's empty state:
|
|
417
|
+
*
|
|
418
|
+
* - `api-disabled` (`OBJECT_API_DISABLED` 404 / `OBJECT_API_METHOD_NOT_ALLOWED`
|
|
419
|
+
* 405): a property of the object's metadata, not of the caller, and no
|
|
420
|
+
* permission grant changes it;
|
|
421
|
+
* - a bare 404 (`sys_activity` on a deployment without the audit plugin).
|
|
422
|
+
* The ObjectStack adapter already answers that as zero rows; another
|
|
423
|
+
* adapter's rejection classifies as `network` and lands here;
|
|
424
|
+
* - `rejected` (400) and `network` (a 5xx, an unreachable server). Those are
|
|
425
|
+
* failures, not refusals. The panel has no error state of its own, so they
|
|
426
|
+
* still render the empty state.
|
|
427
|
+
*
|
|
428
|
+
* ⛔ A refusal is not retried. A refused read is the same answer on every
|
|
429
|
+
* retry, so the callers write it into state and do not re-issue the read.
|
|
430
|
+
*/
|
|
431
|
+
export declare function isRefusedFeedRead(err: unknown): boolean;
|
|
180
432
|
//# sourceMappingURL=recordActivityFeed.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordActivityFeed.d.ts","sourceRoot":"","sources":["../../src/renderers/recordActivityFeed.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"recordActivityFeed.d.ts","sourceRoot":"","sources":["../../src/renderers/recordActivityFeed.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { RecordComponentAriaProps } from '@object-ui/types';
|
|
2
|
+
/**
|
|
3
|
+
* The authored `aria` bag as a renderer actually receives it: the declared
|
|
4
|
+
* face, plus the undeclared `label` spelling a stored document may still carry.
|
|
5
|
+
*/
|
|
6
|
+
export type AuthoredRecordAria = RecordComponentAriaProps & {
|
|
7
|
+
/**
|
|
8
|
+
* ⛔ Not a member of the contract. It is the shared ARIA shape's alias entry
|
|
9
|
+
* and is refused on parse. Declared on this type ONLY so the diagnostic can
|
|
10
|
+
* see it without an `as any` cast (a cast is how `record:path` once came to
|
|
11
|
+
* read this spelling and no other).
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ It is never read as a name. objectui#9945 retired the fold that did;
|
|
14
|
+
* a served value is reported, and only for a caller that names its `block`.
|
|
15
|
+
* See this module's header.
|
|
16
|
+
*/
|
|
17
|
+
label?: string;
|
|
18
|
+
};
|
|
19
|
+
/** What {@link useRecordAriaProps} spreads onto a block's container element. */
|
|
20
|
+
export interface RecordAriaDomProps {
|
|
21
|
+
'aria-label'?: string;
|
|
22
|
+
'aria-describedby'?: string;
|
|
23
|
+
role?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The ARIA DOM props for a `record:*` block's own container.
|
|
27
|
+
*
|
|
28
|
+
* @param aria - the authored bag, straight off the node's `aria` key.
|
|
29
|
+
* @param defaultRole - the role this block renders when the author declares
|
|
30
|
+
* none. Omit it and the container stays role-less until an author declares a
|
|
31
|
+
* name, a description or a role — at which point `'region'` carries the name,
|
|
32
|
+
* because an attribute on a `generic` element carries nothing.
|
|
33
|
+
* @param defaultLabel - the block's built-in accessible name, used when the
|
|
34
|
+
* author declared none (or declared an empty one).
|
|
35
|
+
* @param block - the block's registered type (`record:path`), named in the
|
|
36
|
+
* report of a served `aria.label`. Omit it and that spelling is still not
|
|
37
|
+
* read, just not reported. See this module's header for which blocks pass it.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useRecordAriaProps(aria: AuthoredRecordAria | undefined, { defaultRole, defaultLabel, block, }?: {
|
|
40
|
+
defaultRole?: string;
|
|
41
|
+
defaultLabel?: string;
|
|
42
|
+
block?: string;
|
|
43
|
+
}): RecordAriaDomProps;
|
|
44
|
+
//# sourceMappingURL=recordComponentAria.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordComponentAria.d.ts","sourceRoot":"","sources":["../../src/renderers/recordComponentAria.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AAKH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,GAAG;IAC1D;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAwCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,kBAAkB,GAAG,SAAS,EACpC,EACE,WAAW,EACX,YAAY,EACZ,KAAK,GACN,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACtE,kBAAkB,CAapB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
* `record:related_list.actions` — where an authored action id lands on the list,
|
|
9
|
+
* or why it is refused (objectui#11163; the maintainer's ENFORCE ruling on
|
|
10
|
+
* objectstack-ai/objectstack#20665).
|
|
11
|
+
*
|
|
12
|
+
* The contract declares the key as `z.array(z.string())`, "Action IDs available
|
|
13
|
+
* for related records". This module is the whole of its meaning, kept apart
|
|
14
|
+
* from the renderer so the file that draws the block keeps exporting
|
|
15
|
+
* components only:
|
|
16
|
+
*
|
|
17
|
+
* - RESOLUTION is `resolveDeclaredActionIds` — the one function
|
|
18
|
+
* `page:header`, `record:quick_actions` and `record:alert` resolve an
|
|
19
|
+
* authored action id through (objectui#7182, objectui#7382) — against the
|
|
20
|
+
* RELATED object's registered `actions`. ⛔ No second lookup: the caller
|
|
21
|
+
* reads that registry through `useMetadataItem('object', …)`, the same
|
|
22
|
+
* entry `record:quick_actions.actionNames` uses.
|
|
23
|
+
* - Only the IDS arm is this key's. The inline-object arm of the shared
|
|
24
|
+
* rule is `page:header`'s transition tolerance (objectstack#11592) and is
|
|
25
|
+
* not inherited here, the choice `record:alert` made for its CTA: an
|
|
26
|
+
* object in this array would widen what a related list can run past what
|
|
27
|
+
* the object declares.
|
|
28
|
+
* - PLACEMENT is each action's own `locations`, read by `actionRendersAt`
|
|
29
|
+
* — the platform's one placement rule, and the rule the host bridge
|
|
30
|
+
* (`RelatedRecordActionsBridge.deriveActions`) already applies to this
|
|
31
|
+
* list: `list_toolbar` draws a header button; `list_item` and
|
|
32
|
+
* `record_related` draw a row-menu item (objectui#11270). This block only
|
|
33
|
+
* ever renders inside a parent record, which is the scope `record_related`
|
|
34
|
+
* names (objectstack-ai/objectstack#20937, triage `5919625056`: row
|
|
35
|
+
* placement, inside a record only). Naming an action here does not bypass
|
|
36
|
+
* location filtering (only a list view's selection bar is placed by
|
|
37
|
+
* naming), so an id whose action declares none of the three is REFUSED
|
|
38
|
+
* rather than drawn somewhere or dropped.
|
|
39
|
+
* - ORDER is the author's, within each surface.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* An action definition as the registry holds it — the two members read here,
|
|
43
|
+
* typed `unknown` because the definitions arrive straight off the metadata
|
|
44
|
+
* wire (the reason `actionRendersAt` gives for its own parameter).
|
|
45
|
+
*/
|
|
46
|
+
export interface RegisteredRelatedAction {
|
|
47
|
+
readonly name?: unknown;
|
|
48
|
+
readonly locations?: unknown;
|
|
49
|
+
}
|
|
50
|
+
/** One reason an authored entry does not render, stated for the author. */
|
|
51
|
+
export type RelatedListActionRefusal =
|
|
52
|
+
/** The array itself is refused: not an array, or not all action ids. */
|
|
53
|
+
{
|
|
54
|
+
readonly kind: 'array';
|
|
55
|
+
readonly message: string;
|
|
56
|
+
}
|
|
57
|
+
/** An id that names no registered action of the related object. */
|
|
58
|
+
| {
|
|
59
|
+
readonly kind: 'unresolved';
|
|
60
|
+
readonly id: string;
|
|
61
|
+
}
|
|
62
|
+
/** An id that resolves, to an action declaring no location this list renders. */
|
|
63
|
+
| {
|
|
64
|
+
readonly kind: 'unplaced';
|
|
65
|
+
readonly id: string;
|
|
66
|
+
};
|
|
67
|
+
export interface PlacedRelatedListActions<T> {
|
|
68
|
+
/** `list_toolbar` actions, in authored order — the list's header buttons. */
|
|
69
|
+
readonly toolbar: T[];
|
|
70
|
+
/** `list_item` and `record_related` actions, in authored order — each row's menu. */
|
|
71
|
+
readonly row: T[];
|
|
72
|
+
/** Every authored entry that renders nowhere, and why. */
|
|
73
|
+
readonly refused: RelatedListActionRefusal[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether an authored value has any id to look up — the registry-independent
|
|
77
|
+
* half of the shared rule, so the caller requests the metadata read only when
|
|
78
|
+
* it can change the answer (a `[]`, an object array or a refused array is
|
|
79
|
+
* decided without it).
|
|
80
|
+
*/
|
|
81
|
+
export declare function relatedListActionsNeedLookup(authored: unknown): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Resolve and place an authored `record:related_list.actions` value.
|
|
84
|
+
*
|
|
85
|
+
* `registered` is the related object's `actions` once the metadata lookup has
|
|
86
|
+
* ANSWERED. The caller does not call this while the lookup is in flight: every
|
|
87
|
+
* id would come back unresolved and the list would refuse an id it is about to
|
|
88
|
+
* resolve.
|
|
89
|
+
*
|
|
90
|
+
* An id authored twice renders once, at its first position — it is drawn, so
|
|
91
|
+
* nothing the author asked for is dropped.
|
|
92
|
+
*/
|
|
93
|
+
export declare function placeAuthoredRelatedListActions<T extends RegisteredRelatedAction>(authored: unknown, registered: readonly T[] | null | undefined): PlacedRelatedListActions<T>;
|
|
94
|
+
/**
|
|
95
|
+
* The refusal notice's text — one sentence per refused entry, naming it and
|
|
96
|
+
* the related object, so the fix is a one-entry edit.
|
|
97
|
+
*
|
|
98
|
+
* `objectKnown` is whether the lookup found the related object at all: an id
|
|
99
|
+
* cannot be "not an action of" an object whose metadata never arrived.
|
|
100
|
+
*/
|
|
101
|
+
export declare function describeRelatedListActionRefusals(refused: readonly RelatedListActionRefusal[], objectName: string, objectKnown: boolean): string;
|
|
102
|
+
//# sourceMappingURL=relatedListActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relatedListActions.d.ts","sourceRoot":"","sources":["../../src/renderers/relatedListActions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,2EAA2E;AAC3E,MAAM,MAAM,wBAAwB;AAClC,wEAAwE;AACtE;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACtD,mEAAmE;GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AACtD,iFAAiF;GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,wBAAwB,EAAE,CAAC;CAC9C;AAQD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAIvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAAC,CAAC,SAAS,uBAAuB,EAC/E,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,GAC1C,wBAAwB,CAAC,CAAC,CAAC,CA6C7B;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,SAAS,wBAAwB,EAAE,EAC5C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,MAAM,CAeR"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { PercentScale } from '@object-ui/core';
|
|
2
|
+
/**
|
|
3
|
+
* The ONE rule the `summaryFields` chip scales a stored `percent` by — and it
|
|
4
|
+
* is the repo's, not this file's (objectui#9071).
|
|
5
|
+
*
|
|
6
|
+
* ⭐ Since objectui#9167 this is the chip's BAR path only. The chip's TEXT goes
|
|
7
|
+
* straight to `formatPercent` in `@object-ui/fields` — the list cell's own
|
|
8
|
+
* body, which applies {@link percentDisplayValue} itself and then the locale's
|
|
9
|
+
* percent affix at the field's precision. See "The half objectui#9071 did NOT
|
|
10
|
+
* take" below, which objectui#9167 closed.
|
|
11
|
+
*
|
|
12
|
+
* ## Why this function exists at all (objectui#8728)
|
|
13
|
+
*
|
|
14
|
+
* The chip beside the record H1 draws a percent TWICE — as its text and as a
|
|
15
|
+
* small bar — and the two halves scaled the same stored number by two
|
|
16
|
+
* different rules:
|
|
17
|
+
*
|
|
18
|
+
* display = `${num}%`; // the text: no scaling
|
|
19
|
+
* const normalized = num <= 1 ? num * 100 : num; // the bar: ratio, scaled
|
|
20
|
+
*
|
|
21
|
+
* so a stored `0.123` labelled itself `0.123%` beside a bar filled to 12.3%.
|
|
22
|
+
* One control, two percentages, and neither half told the reader which one was
|
|
23
|
+
* right. Both halves read this function — which is why it is a named function
|
|
24
|
+
* and not the same ternary written twice. The next reader cannot
|
|
25
|
+
* re-desynchronise them without deleting a call site.
|
|
26
|
+
*
|
|
27
|
+
* ## What objectui#9071 DELETED, and why aligning it would not have done
|
|
28
|
+
*
|
|
29
|
+
* objectui#8728 converged the chip's two halves onto the BAR's rule and
|
|
30
|
+
* recorded, rather than decided, that the rule was the chip's own. The census
|
|
31
|
+
* it asked for answered the question: the predicate that stood here —
|
|
32
|
+
* a pass-through spelled `if (raw > 1) return raw;`, i.e. the bar's original
|
|
33
|
+
* `num <= 1` written the other way round — was the only spelling of its kind on
|
|
34
|
+
* this side of the tree, and it disagreed with the declared single source of
|
|
35
|
+
* truth at EXACTLY 1 and at every value AT OR BELOW -1:
|
|
36
|
+
*
|
|
37
|
+
* | stored | the deleted local rule | `percentDisplayValue`, and every other band |
|
|
38
|
+
* |--------|------------------------|---------------------------------------------|
|
|
39
|
+
* | `0.25` | `25%` | `25%` (the band they always agreed on) |
|
|
40
|
+
* | `1` | `100%` | `1%` |
|
|
41
|
+
* | `-1` | `-100%` | `-1%` |
|
|
42
|
+
* | `-5` | `-500%` | `-5%` |
|
|
43
|
+
*
|
|
44
|
+
* ⛔ The repair is NOT to move the local predicate's boundary onto the shared
|
|
45
|
+
* one. That would leave two rules agreeing by coincidence — the same shape
|
|
46
|
+
* objectui#5607 removed one package over, and the shape that produced this
|
|
47
|
+
* drift in the first place. The predicate is gone; the authority is
|
|
48
|
+
* {@link percentDisplayValue} in `@object-ui/core`, whose own doc comment
|
|
49
|
+
* requires exactly this of a third surface, and which the list cell
|
|
50
|
+
* (`formatPercent` / `PercentCellRenderer`), the dashboard measure
|
|
51
|
+
* (`formatMeasure`) and the grid column summary already read.
|
|
52
|
+
*
|
|
53
|
+
* ## The half objectui#9071 did NOT take — closed by objectui#9167
|
|
54
|
+
*
|
|
55
|
+
* That doc comment asks a third surface for BOTH halves — the scaling AND the
|
|
56
|
+
* convention. objectui#9071 moved the SCALING only: the chip stated the full
|
|
57
|
+
* JavaScript number with a bare `%` while the list cell rendered through the
|
|
58
|
+
* locale's percent affix at the field's precision (`0` by default), so a stored
|
|
59
|
+
* `12.3` read `12.3%` beside the H1 and `12%` in the list — two spellings of
|
|
60
|
+
* one magnitude, with the two bars proving the magnitude was one. That card
|
|
61
|
+
* stopped because its acceptance forbade moving values the chip rendered
|
|
62
|
+
* correctly today, and the convention half moves several.
|
|
63
|
+
*
|
|
64
|
+
* objectui#9167 took it, value by value rather than by inspection: both
|
|
65
|
+
* surfaces were driven in the same run, on the same field, for every stored
|
|
66
|
+
* value below, and every row that MOVED moved onto the reading the list cell
|
|
67
|
+
* was already giving. The chip's text is now the cell's own `formatPercent`
|
|
68
|
+
* call, byte for byte, and this function is left
|
|
69
|
+
* holding the BAR alone. The table and its `de-DE` leg are pinned in
|
|
70
|
+
* `__tests__/summaryChip.percentConvention-9167.test.tsx`.
|
|
71
|
+
*
|
|
72
|
+
* ## The storage is the field's, stated by the caller (objectui#11475)
|
|
73
|
+
*
|
|
74
|
+
* `percentScale` is the storage the chip's field declares, which `DetailView`
|
|
75
|
+
* reads with `percentCellScale` (`@object-ui/fields`): the spec's
|
|
76
|
+
* `percentScaleOf`, the answer the list cell reads too. Until objectui#11475
|
|
77
|
+
* the shared source guessed the storage from the value's magnitude, so the
|
|
78
|
+
* table above, whose every row is that guess, no longer describes this
|
|
79
|
+
* function: a fraction-stored `1` now fills the bar to 100%, and a
|
|
80
|
+
* whole-stored `0.5` to half a percent.
|
|
81
|
+
*/
|
|
82
|
+
export declare function summaryChipPercentPoints(raw: number, percentScale: PercentScale): number;
|
|
83
|
+
//# sourceMappingURL=summaryChipPercent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summaryChipPercent.d.ts","sourceRoot":"","sources":["../src/summaryChipPercent.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAyBxF"}
|