@cosmicdrift/kumiko-types 0.415.0 → 0.417.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.
@@ -1,3 +1,3 @@
1
1
  import type { IconKey } from "./nav-icon.ts";
2
2
  export declare const ACTION_ICON_BY_ID: Readonly<Partial<Record<string, IconKey>>>;
3
- export declare function resolveActionIcon(id: string, declared?: IconKey): IconKey | undefined;
3
+ export declare function resolveActionIcon(id: string, declared?: IconKey | false): IconKey | undefined;
@@ -43,6 +43,8 @@ function kebabFirstSegment(id) {
43
43
  // segment). `declared` is `undefined` for ToolbarAction, which has no
44
44
  // author-facing icon field.
45
45
  export function resolveActionIcon(id, declared) {
46
+ if (declared === false)
47
+ return undefined;
46
48
  if (declared !== undefined)
47
49
  return declared;
48
50
  return (ACTION_ICON_BY_ID[id] ??
package/dist/config.d.ts CHANGED
@@ -83,6 +83,12 @@ export type ConfigMask = {
83
83
  readonly description?: string;
84
84
  readonly icon?: NavIconKey;
85
85
  readonly order?: number;
86
+ /** Shows the value on the generated settings screen without an input; a read-only key cannot also be `required`. */
87
+ readonly readOnly?: boolean;
88
+ /** Draws the generated settings screen of this key compact (like `configEdit` `compact: true`: no origin icon or reset link, no accent bar, large section labels, no name-derived field icons). One key per screen is enough. */
89
+ readonly compact?: true;
90
+ /** i18n key of a section title: keys sharing it form their own titled section on the generated settings screen, after the untitled-by-mask keys. */
91
+ readonly section?: string;
86
92
  };
87
93
  export type ConfigDefinition = {
88
94
  readonly keys: Readonly<Record<string, ConfigKeyDefinition>>;
package/dist/fields.d.ts CHANGED
@@ -227,8 +227,8 @@ export type MultiSelectFieldDef<TOptions extends readonly string[] = readonly st
227
227
  readonly access?: FieldAccess;
228
228
  /** Renderer metadata: `"checkboxes"` renders every option as a visible
229
229
  * checkbox with a select-all toggle. Default (omitted) stays the combobox
230
- * dropdown. */
231
- readonly display?: "checkboxes" | "dropdown";
230
+ * dropdown; `"chips"` renders toggle chips with a check mark on the chosen ones. */
231
+ readonly display?: "checkboxes" | "chips" | "dropdown";
232
232
  /** Renderer metadata: column count for the `"checkboxes"` grid at the widest
233
233
  * breakpoint; narrow viewports always collapse to one column. Omitted =
234
234
  * the renderer picks a sensible count. Ignored unless
@@ -830,4 +830,10 @@ export type EntityDefinition<F extends FieldsMap = FieldsMap, T extends EntityTe
830
830
  /** Attached files are readable only through the record's detail query: the files feature's
831
831
  * privilegedRoles do not bypass it, the uploader check stays. */
832
832
  readonly attachedFileAccess?: "record-only";
833
+ /** Files of this entity may be read from another tenant when `query`, run with `{ id: <entityId> }`
834
+ * as the requesting user, returns the record with that id. Read only: delete stays with the owning tenant. */
835
+ readonly crossTenantFileRead?: {
836
+ readonly query: string;
837
+ readonly reason: string;
838
+ };
833
839
  };
@@ -46,6 +46,11 @@ export type HandlerEvents<TMap extends object = KumikoEventTypeMap> = {
46
46
  readonly asOf?: never;
47
47
  readonly includeArchived?: boolean;
48
48
  }) => Promise<readonly import("./event-store-types.ts").StoredEvent[]>;
49
+ readonly loadByTypes: (args: {
50
+ readonly aggregateIds: readonly string[];
51
+ readonly eventTypes: readonly string[];
52
+ readonly includeArchived?: boolean;
53
+ }) => Promise<readonly import("./event-store-types.ts").StoredEvent[]>;
49
54
  readonly archive: (aggregateId: string, args: {
50
55
  readonly aggregateType: string;
51
56
  readonly reason?: string;
@@ -1,9 +1,9 @@
1
- import type { FormFieldDefinition } from "./fields.ts";
1
+ import type { FormFieldDefinition, SelectOptionTone } from "./fields.ts";
2
2
  import type { AccessRule, AgentScreenHints } from "./handlers.ts";
3
3
  import type { IconKey } from "./nav-icon.ts";
4
4
  import type { ScreenNavSugar, ScreenSlots } from "./screen.ts";
5
5
  import type { ScreenVisibility } from "./screen-dashboard.ts";
6
- import type { EditLayout } from "./screen-entity-edit.ts";
6
+ import type { EditLayout, FieldTextRef } from "./screen-entity-edit.ts";
7
7
  import type { ScreenFallback } from "./screen-fallback.ts";
8
8
  /** A form field computed from other fields of the same form. `listSum` adds one
9
9
  * numeric cell over all rows of an embedded list field; its `whenEmpty`
@@ -70,7 +70,7 @@ export type ActionFormScreenDefinition = {
70
70
  readonly layout: EditLayout;
71
71
  /** Per-field label i18n key override, same type/semantics as
72
72
  * `EntityEditScreenDefinition.fieldLabels`. Falls back to the convention when absent. */
73
- readonly fieldLabels?: Readonly<Record<string, string>>;
73
+ readonly fieldLabels?: Readonly<Record<string, FieldTextRef>>;
74
74
  /** i18n key for the submit button. Default: the renderer's i18n default
75
75
  * (typically "actions.submit"). */
76
76
  readonly submitLabel?: string;
@@ -87,7 +87,22 @@ export type ActionFormScreenDefinition = {
87
87
  readonly title: string;
88
88
  readonly subtitle?: string;
89
89
  readonly params?: Readonly<Record<string, string>>;
90
+ /** Fields of the `load` result that fill `{name}` placeholders too (static `params` win). Needs `load`. */
91
+ readonly paramsFromLoad?: readonly string[];
90
92
  };
93
+ /** Help text under a field (field name -> i18n key). */
94
+ readonly fieldDescriptions?: Readonly<Record<string, FieldTextRef>>;
95
+ /** i18n key of a short note in a banner above the fields, with a sparkles icon (e.g. "the AI
96
+ * prepared everything, read the text, then send"). */
97
+ readonly infoBand?: string;
98
+ /** Badge next to a field's label (field name -> `{ label: i18n key, tone }`), e.g. "price
99
+ * source open" in `warn`. */
100
+ readonly fieldBadges?: Readonly<Record<string, {
101
+ readonly label: string;
102
+ readonly tone: SelectOptionTone;
103
+ }>>;
104
+ /** Shows a failed submit's error banner above the fields instead of below them. */
105
+ readonly formErrorOnTop?: boolean;
91
106
  /** Visual style of the submit button. "danger" renders it red — for a form
92
107
  * whose handler is destructive (terminate, revoke, delete), so the warning
93
108
  * isn't lost on the way from the calling screen to this one. Default "primary". */
@@ -181,11 +196,16 @@ export type ActionFormRedirect = {
181
196
  * Only used when the target screen type carries an id (`entityEdit`,
182
197
  * `projectionDetail`); a non-string or missing value navigates without
183
198
  * an id, same as a payload without `id` does today. */
184
- readonly idFrom: string;
199
+ readonly idFrom?: string;
185
200
  /** Section id to open on the target `projectionDetail` with `layout.mode:
186
201
  * "tabs"` (the `tab` search param, same as `ToolbarAction` navigate `tab`).
187
202
  * Boot rejects other targets and unknown section ids. */
188
203
  readonly tab?: string;
204
+ /** URL search params of the target, each read from a flat success-payload
205
+ * field (`{ cmd: "threadId" }` opens `?cmd=<threadId>`). Lets a redirect
206
+ * reach a custom screen that is driven by search params instead of a
207
+ * record id; a missing or non-string field leaves its param out. */
208
+ readonly searchParams?: Readonly<Record<string, string>>;
189
209
  };
190
210
  export type ActionFormLoad = {
191
211
  /** Query QN that returns the record. */
@@ -197,6 +217,10 @@ export type ActionFormLoad = {
197
217
  * (same semantics as `ProjectionDetailScreenDefinition.singleton`). Boot
198
218
  * rejects declaring `idParam` alongside it. */
199
219
  readonly singleton?: boolean;
220
+ /** Sends the values a drawer opens the form with (row-action params, e.g. `vehicleId`) in the
221
+ * load payload next to `idParam`, so the query can pre-fill for the chosen item. The query's
222
+ * schema must accept them. */
223
+ readonly passPrefill?: boolean;
200
224
  };
201
225
  /** One key figure of the success box, read from the handler's success payload. */
202
226
  export type ActionFormSuccessFact = {
@@ -217,7 +241,7 @@ export type ActionFormSuccessItems = {
217
241
  readonly link?: ActionFormSuccessLink;
218
242
  };
219
243
  /** A redirect target rendered as a link in the success box. */
220
- export type ActionFormSuccessLink = Omit<ActionFormRedirect, "idFrom"> & {
244
+ export type ActionFormSuccessLink = Omit<ActionFormRedirect, "idFrom" | "searchParams"> & {
221
245
  /** Success-payload field carrying the navigation id. Required for a record
222
246
  * target (`entityEdit`, `projectionDetail`); omit it for a list, dashboard
223
247
  * or form target, which opens without an id. */
@@ -101,6 +101,9 @@ export type ConfigEditScreenDefinition = {
101
101
  readonly requiredFields?: readonly string[];
102
102
  /** i18n key for the submit button. Default: "kumiko.actions.save". */
103
103
  readonly submitLabel?: string;
104
+ /** Compact rows: no origin icon, no reset link, no accent bar on changed fields; the form
105
+ * column is capped to a readable width. */
106
+ readonly compact?: true;
104
107
  /** Handler buttons drawn as their own row after `afterField` (settings-list layout). */
105
108
  readonly actions?: readonly ConfigEditAction[];
106
109
  readonly slots?: ScreenSlots;
@@ -59,11 +59,17 @@ export type DashboardPanelGate = {
59
59
  };
60
60
  /** Phone layout switch shared by every panel kind. */
61
61
  export type DashboardPanelNarrow = {
62
- /** Leaves the panel out below the `sm` breakpoint (phone). Not valid on a stat-group child: hide the group. */
62
+ /** Leaves the panel out below the `sm` breakpoint (phone). On a stat-group child it drops that stat from the group on a phone; not every child may hide. */
63
63
  readonly hideOnNarrow?: true;
64
64
  /** Position below `sm`, like CSS `order`: panels are laid out by ascending value, a panel without one counts as 0, equal values keep the declared order. Integer ≥ 0. Desktop keeps the declared order. */
65
65
  readonly narrowOrder?: number;
66
+ /** "side" puts the panel in the narrow right column of a `layout: "main-side"` dashboard, "top" in a full-width block above both columns; panels without it fill the main column. Not valid on a stat-group child or without that layout. */
67
+ readonly column?: DashboardPanelColumn;
66
68
  };
69
+ /** "top" spans both columns above the main and side column, in declared order. */
70
+ export type DashboardPanelColumn = "side" | "top";
71
+ /** "main-side": from `lg` up the main column (2/3) stacks every panel without `column`, the side column (1/3) every `column: "side"` panel, each with its own heights; `column: "top"` panels span both columns above them; below `lg` they stack, below `sm` by `narrowOrder`. Default: one 12-column grid. Panel `span` is ignored in this layout. */
72
+ export type DashboardLayout = "main-side";
67
73
  export type DashboardPanelSpan = "half" | "full" | "third" | "two-thirds";
68
74
  export type DashboardPanelEmptyState = {
69
75
  readonly span?: DashboardPanelSpan;
@@ -85,6 +91,8 @@ export type DashboardStatPanel = DashboardPanelQueryOptions & DashboardPanelGate
85
91
  readonly labelField?: string;
86
92
  /** i18n key shown instead of the label in the one-line phone strip of a titled stat-group ("2 requests"). Only used for stats inside a stat-group. */
87
93
  readonly narrowLabel?: string;
94
+ /** i18n key replacing `label` below the `sm` breakpoint wherever the stat draws its label (a dynamic `labelField` text still wins). */
95
+ readonly labelNarrow?: string;
88
96
  readonly subField?: string;
89
97
  readonly toneField?: string;
90
98
  /** Formats a numeric value as currency (minor units) or, with `relativeTime`, as
@@ -258,7 +266,8 @@ export type DashboardListNarrow = {
258
266
  };
259
267
  /** Link to a screen from a panel; `label` is an i18n key, `namedFilter` only for list screens. */
260
268
  export type DashboardListFooterLink = {
261
- readonly label: string;
269
+ /** i18n key of the link text. Without it the footer shows only the `moreText` count as muted text, no link; `screen` still has to resolve. */
270
+ readonly label?: string;
262
271
  /** i18n key of the text before the link when more rows exist than shown; `{count}` is the rest. Default "k more". */
263
272
  readonly moreText?: string;
264
273
  /** i18n key used instead of `moreText` below `sm`. */
@@ -306,12 +315,18 @@ export type DashboardFeedPanel = DashboardPanelQueryOptions & DashboardPanelEmpt
306
315
  readonly id: string;
307
316
  readonly label: string;
308
317
  readonly query: string;
318
+ /** Shows the count in the panel head, right-aligned like a list panel's `showTotal`: `{total}` is the query's `total`, else the rows returned. `text` is an i18n key with `{shown}` and `{total}`; without it "{shown} of {total}". */
319
+ readonly showTotal?: true | Pick<DashboardListShowTotal, "text">;
309
320
  };
310
321
  export type DashboardProgressTone = "default" | "danger";
311
322
  export type DashboardProgressListPanel = DashboardPanelQueryOptions & DashboardPanelEmptyState & DashboardPanelGate & DashboardPanelNarrow & {
312
323
  readonly kind: "progress-list";
313
324
  readonly id: string;
314
325
  readonly label: string;
326
+ /** Fills the translated `label` from the query answer: maps a label placeholder to a top-level answer field, e.g. `{ month: "monthName" }` for "Quota {month}" with `{ rows, monthName: "November" }`. Until the answer arrives the placeholders are empty. */
327
+ readonly labelParams?: Readonly<Record<string, string>>;
328
+ /** Top-level answer field holding a text shown muted at the right end of the panel head, e.g. the period ("November"). */
329
+ readonly subtitleField?: string;
315
330
  readonly query: string;
316
331
  };
317
332
  export type DashboardCustomPanel = DashboardPanelNarrow & {
@@ -356,6 +371,8 @@ export type DashboardTextPanel = DashboardPanelGate & DashboardPanelQueryOptions
356
371
  readonly id: string;
357
372
  /** Panel title (i18n key). */
358
373
  readonly label?: string;
374
+ /** Icon shown before the text blocks (resolved like `DashboardStatGroupPanel.icon`). */
375
+ readonly icon?: PlatformComponent;
359
376
  readonly span?: DashboardPanelSpan;
360
377
  /** Query answering `{ blocks: DashboardTextBlock[] }`; its blocks replace the static ones.
361
378
  * Static blocks show while it loads, on error and when it answers empty. It may add
@@ -459,6 +476,8 @@ export type DashboardScreenDefinition = {
459
476
  /** Same-feature short id or cross-feature QN `<feature>:screen:<id>` shown when `visibleWhen` is unmet (default: standard notice). */
460
477
  readonly fallback?: ScreenFallback;
461
478
  readonly panels: readonly DashboardPanelDefinition[];
479
+ /** Panel arrangement, see DashboardLayout. */
480
+ readonly layout?: DashboardLayout;
462
481
  /** Binds the dashboard to one record via a URL search param, see DashboardRecordBinding. */
463
482
  readonly record?: DashboardRecordBinding;
464
483
  /** Header actions on the bound record (writeHandler, navigate, clientAction).
@@ -44,6 +44,24 @@ export type EditFieldSpec = string | {
44
44
  * the value can only come from the suggestion. Only for single-line
45
45
  * text and number inputs; other kinds ignore it. */
46
46
  readonly fillAction?: FieldFillAction;
47
+ /** Helper under a `text` or `longText` input: stackable chips and an optional free
48
+ * instruction call a query and write its `resultField` into the field. */
49
+ readonly aiAssist?: FieldAiAssist;
50
+ /** Quick-pick chips under a `number`, `decimal`, `bigInt` or `money` input; a chip sets
51
+ * the field to its value. The values come from another field of the same form that
52
+ * holds an array of numbers (e.g. hidden and `submit: false`, seeded by prefill). */
53
+ readonly valueChips?: FieldValueChips;
54
+ /** Read-only display of a value the viewer may not see: the value (or the mask the query
55
+ * returns) shows muted with a lock icon instead of a replacement text. */
56
+ readonly concealed?: true;
57
+ /** Pill next to the label, e.g. "price source open" in `warn`. `label` is an i18n key; `field` names a
58
+ * value field of the form or record whose non-empty text is the pill text (no text: no pill). */
59
+ readonly badge?: FieldBadge;
60
+ /** Value field whose non-empty text shows as a muted small hint under the field
61
+ * (e.g. "From the buyer: Skoda Octavia"). */
62
+ readonly hintField?: string;
63
+ /** Leaves the field out below `sm`; its value is still submitted. */
64
+ readonly hideOnNarrow?: true;
47
65
  /** Marks this field as a reference lookup instead of a plain value —
48
66
  * for projectionDetail fields, which have no `EntityDefinition` to
49
67
  * carry a real `reference` field type. Same target convention as
@@ -66,9 +84,52 @@ export type EditFieldSpec = string | {
66
84
  * field `default`, it is not applied server-side. */
67
85
  readonly prefill?: EditFieldPrefill;
68
86
  };
87
+ /** Pill next to a field label: a fixed i18n `label`, or the text of another value `field`. */
88
+ export type FieldBadge = {
89
+ readonly label: string;
90
+ readonly tone: SelectOptionTone;
91
+ } | {
92
+ readonly field: string;
93
+ readonly tone: SelectOptionTone;
94
+ };
69
95
  export type FieldAffix = string | {
70
96
  readonly field: string;
71
97
  };
98
+ /** A label or help text: an i18n key, or a key whose `{placeholder}`s are filled from form values.
99
+ * `params` maps each placeholder to the name of a form field (hidden fields count). */
100
+ export type FieldTextRef = string | {
101
+ readonly key: string;
102
+ readonly params: Readonly<Record<string, string>>;
103
+ };
104
+ /** One toggle chip: while active, its `params` are merged into the query payload. */
105
+ export type FieldAiAssistChip = {
106
+ /** i18n key of the chip label. */
107
+ readonly label: string;
108
+ readonly params: Readonly<Record<string, string | number | boolean>>;
109
+ };
110
+ export type FieldAiAssist = {
111
+ /** Qualified query name, run with the form's context payload (the `load` id of an actionForm,
112
+ * else the drawer row's prefill values) plus the `params` of the active chips. */
113
+ readonly query: string;
114
+ /** Key in the query result written into the field; the value must be a string. */
115
+ readonly resultField: string;
116
+ /** Key in the query result with a short note for the user (e.g. "could not rewrite, draft unchanged"). Shown as a quiet line under the field until the next result without one. */
117
+ readonly noteField?: string;
118
+ /** Other fields of the same form whose current values are sent in the payload (under their
119
+ * field names). Changing one of them runs the query again and replaces the text. */
120
+ readonly contextFields?: readonly string[];
121
+ readonly chips?: readonly FieldAiAssistChip[];
122
+ /** Adds an input where the user types a free instruction; it is sent under `param`. */
123
+ readonly prompt?: {
124
+ readonly param: string;
125
+ /** i18n key of the input's placeholder. */
126
+ readonly placeholder?: string;
127
+ };
128
+ };
129
+ export type FieldValueChips = {
130
+ /** Name of a field of the same form whose value is an array of numbers. For `money`, major units. */
131
+ readonly from: string;
132
+ };
72
133
  export type FieldFillAction = {
73
134
  /** i18n key (falls back to the literal) of the button label. */
74
135
  readonly label: string;
@@ -96,11 +157,28 @@ export type EditFieldPrefill = {
96
157
  readonly kind: "currentUser";
97
158
  readonly property: "displayName" | "email" | "id";
98
159
  };
99
- export type EditSectionSpec = EditFieldsSection | EditExtensionSection | EditRelatedListSection | EditWriteFormSection;
100
- type EditFieldsSectionBase = {
160
+ /** Presentation options every section kind of a projectionDetail takes. */
161
+ export type EditSectionPresentation = {
162
+ /** i18n key of the tab name when the layout is in tabs mode; the section `title` stays the card heading. Without it the tab is named after the title of the first section with that tab id. */
163
+ readonly tabLabel?: string;
164
+ /** Component drawn directly under this section's card, in its column (also beside photos); same `{ react: { __component } }` form as `slots.afterForm`, receiving the same props. */
165
+ readonly after?: PlatformComponent;
166
+ /** Leaves the section out below `sm`. Exclusive with `showOnNarrowOnly`. */
167
+ readonly hideOnNarrow?: true;
168
+ /** Shows the section only below `sm` (e.g. a compact facts block for phones). */
169
+ readonly showOnNarrowOnly?: true;
170
+ /** `false` leaves the section title out below `sm` (phone); the title stays from `sm` up. */
171
+ readonly titleOnNarrow?: false;
172
+ };
173
+ export type EditSectionSpec = EditFieldsSection | EditExtensionSection | EditRelatedListSection | EditWriteFormSection | EditStepListSection;
174
+ type EditFieldsSectionBase = EditSectionPresentation & {
101
175
  /** Kebab-case tab id, used as the `?tab=` value. Required by the
102
176
  * boot-validator when the enclosing `EditLayout.mode` is "tabs". */
103
177
  readonly id?: string;
178
+ /** projectionDetail only: shows the section (and its tab) only while the loaded record matches,
179
+ * same `{ field, eq | ne | in | notIn }` syntax as a field's `visibleWhen`. `field` must be an
180
+ * output field of the detail query. */
181
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
104
182
  readonly kind?: "fields";
105
183
  /** Optional. Without a title the section only renders its fields (no h3
106
184
  * heading) — for flat forms (card title + fields directly, a single
@@ -112,6 +190,8 @@ type EditFieldsSectionBase = {
112
190
  * `subtitle` slot as `FormProps.subtitle`. Works without `title` too
113
191
  * (subtitle-only section). */
114
192
  readonly description?: string;
193
+ /** i18n key of a short text shown instead of `description` below `sm`. */
194
+ readonly descriptionNarrow?: string;
115
195
  readonly columns?: number;
116
196
  /** Rendered left of the section title, `text-muted-foreground` — closed
117
197
  * IconKey vocabulary into the ICONS registry (renderer/web), analogous
@@ -140,7 +220,8 @@ type EditFieldsSectionBase = {
140
220
  export type EditFieldGroup = {
141
221
  readonly title: string;
142
222
  readonly fields: readonly EditFieldSpec[];
143
- /** Default 2. */
223
+ /** Edit mode renders 2 columns by default. In read mode only a declared value turns the group
224
+ * into a label/value grid; without it the stacked layout stays. */
144
225
  readonly columns?: number;
145
226
  };
146
227
  /** Either a flat `fields` grid or titled `groups` cards, never both: the groups branch has no
@@ -152,10 +233,34 @@ export type EditFieldsSection = EditFieldsSectionBase & ({
152
233
  * here still need to exist. */
153
234
  readonly groups: readonly EditFieldGroup[];
154
235
  });
155
- export type EditExtensionSection = {
236
+ /** One step of an `EditStepListSection`; `status` renders as a pill in `statusTone`. */
237
+ export type StepListItem = {
238
+ readonly title: string;
239
+ readonly status?: string;
240
+ readonly statusTone?: SelectOptionTone;
241
+ readonly description?: string;
242
+ };
243
+ /** Vertical numbered step list (circles joined by a line), fed from one field of the detail
244
+ * query. Only supported on projectionDetail. Several sections sharing one `id` stack inside one
245
+ * tab, e.g. fields, relatedList and stepList under "Overview". */
246
+ export type EditStepListSection = EditSectionPresentation & {
247
+ readonly id?: string;
248
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
249
+ readonly kind: "stepList";
250
+ readonly title?: string;
251
+ /** Output field of the detail query holding a `StepListItem[]`. */
252
+ readonly field: string;
253
+ /** Present only so section-actions readers accept the union; a step list has no title-row actions. */
254
+ readonly actions?: undefined;
255
+ };
256
+ export type EditExtensionSection = EditSectionPresentation & {
156
257
  /** Kebab-case tab id, used as the `?tab=` value. Required by the
157
258
  * boot-validator when the enclosing `EditLayout.mode` is "tabs". */
158
259
  readonly id?: string;
260
+ /** projectionDetail only: shows the section (and its tab) only while the loaded record matches,
261
+ * same `{ field, eq | ne | in | notIn }` syntax as a field's `visibleWhen`. `field` must be an
262
+ * output field of the detail query. */
263
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
159
264
  readonly kind: "extension";
160
265
  readonly title: string;
161
266
  /** Wizard layouts only: intro text above the step, same slot as `EditFieldsSection.description`. */
@@ -208,10 +313,14 @@ export type ListEmptyStateSpec = {
208
313
  readonly description?: string;
209
314
  readonly action?: RowAction;
210
315
  };
211
- export type EditRelatedListSection = {
316
+ export type EditRelatedListSection = EditSectionPresentation & {
212
317
  /** Kebab-case tab id, used as the `?tab=` value. Required by the
213
318
  * boot-validator when the enclosing `EditLayout.mode` is "tabs". */
214
319
  readonly id?: string;
320
+ /** projectionDetail only: shows the section (and its tab) only while the loaded record matches,
321
+ * same `{ field, eq | ne | in | notIn }` syntax as a field's `visibleWhen`. `field` must be an
322
+ * output field of the detail query. */
323
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
215
324
  readonly kind: "relatedList";
216
325
  readonly title: string;
217
326
  /** Rows are aggregates or other values with no record of their own, so they lead nowhere on
@@ -322,6 +431,18 @@ export type EditRelatedListSection = {
322
431
  * ("kumiko.list.no-entries") applies. `action`'s icon must resolve, same
323
432
  * as `actions` above. */
324
433
  readonly emptyState?: RelatedListEmptyStateSpec;
434
+ /** Draws the rows as a tile grid of images instead of a table. Each tile shows the file in
435
+ * `imageField` and the row's `rowActions` underneath; `columns` only name the row fields. */
436
+ readonly photoGrid?: {
437
+ /** Row field holding a FileRef id (or an id array, the first shows). */
438
+ readonly imageField: string;
439
+ /** Row field printed under the image; without it the tile reads "Photo n". */
440
+ readonly captionField?: string;
441
+ /** Row field whose non-empty text shows as a warn badge on the image's top left. */
442
+ readonly badgeField?: string;
443
+ /** On a phone (below `sm`) tiles whose `badgeField` has text come first, the rest keep their order; from `sm` up the natural order stays. */
444
+ readonly badgeFirst?: true;
445
+ };
325
446
  };
326
447
  /** Empty-state text for one parent-record state, e.g. "still running" vs. "finished without rows". */
327
448
  export type RelatedListEmptyStateVariant = {
@@ -334,13 +455,19 @@ export type RelatedListEmptyStateVariant = {
334
455
  export type RelatedListEmptyStateSpec = ListEmptyStateSpec & {
335
456
  readonly variants?: readonly RelatedListEmptyStateVariant[];
336
457
  };
337
- export type EditWriteFormSection = {
458
+ export type EditWriteFormSection = EditSectionPresentation & {
338
459
  /** Kebab-case tab id, used as the `?tab=` value. Required by the
339
460
  * boot-validator when the enclosing `EditLayout.mode` is "tabs". */
340
461
  readonly id?: string;
462
+ /** projectionDetail only: shows the section (and its tab) only while the loaded record matches,
463
+ * same `{ field, eq | ne | in | notIn }` syntax as a field's `visibleWhen`. `field` must be an
464
+ * output field of the detail query. */
465
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
341
466
  readonly kind: "writeForm";
342
467
  readonly title?: string;
343
468
  readonly description?: string;
469
+ /** i18n key of a short text shown instead of `description` below `sm`. */
470
+ readonly descriptionNarrow?: string;
344
471
  readonly columns?: number;
345
472
  readonly icon?: IconKey;
346
473
  /** Field-type map for this section's own form — same shape as
@@ -359,6 +486,8 @@ export type EditWriteFormSection = {
359
486
  readonly handler: string;
360
487
  /** i18n-key for the submit button. Default: "kumiko.actions.save". */
361
488
  readonly submitLabel?: string;
489
+ /** Id of a writeHandler action in the screen's `actions`. The section then has no submit button of its own: the action sends its own payload plus this form's current values in one write to the action's handler, after the form validated (an invalid form sends nothing). A form field named like a payload key of the action is rejected at boot; `handler` is not dispatched. */
490
+ readonly submitWith?: string;
362
491
  /** Rendered top-right in the section's Card title row — same
363
492
  * navigate/drawer/writeHandler dispatch as `ProjectionDetailScreenDefinition.actions`,
364
493
  * evaluated against the same record. Every action must resolve an icon
@@ -380,6 +509,8 @@ export type EditLayout = {
380
509
  * boot-validator rejects it on entityEdit, see the check for the reason);
381
510
  * requires >= 2 sections, each with a title and an `id`. */
382
511
  readonly mode?: "single" | "wizard" | "tabs";
512
+ /** `false` (tabs mode): below `sm` there is no tab strip, the visible sections of every tab stand one under the other. */
513
+ readonly narrowTabs?: false;
383
514
  /** "settings-list" lays each section out as a band with a title column on
384
515
  * the left and one hairline-separated row per field (label + help left,
385
516
  * control right) — the familiar settings pattern, for screens that are a
@@ -388,6 +519,8 @@ export type EditLayout = {
388
519
  readonly variant?: "form" | "settings-list";
389
520
  /** Hides the asterisk after required field labels. Default false (shown). */
390
521
  readonly hideRequiredMarker?: boolean;
522
+ /** `false` switches off the "all fields are required" hint when every field is required; each label then carries its own asterisk. */
523
+ readonly allRequiredHint?: false;
391
524
  /** Persists in-progress wizard state as a resumable draft instead of
392
525
  * discarding it on navigation away. */
393
526
  readonly draft?: boolean;
@@ -509,7 +642,7 @@ export type EntityEditScreenDefinition = {
509
642
  * natural field namespace — the settings hub injects the config key's
510
643
  * `mask.title` label here. A missing entry falls back to the
511
644
  * convention. */
512
- readonly fieldLabels?: Readonly<Record<string, string>>;
645
+ readonly fieldLabels?: Readonly<Record<string, FieldTextRef>>;
513
646
  /** Record actions. Reuses `RowAction` — analogous to
514
647
  * `ProjectionDetailScreenDefinition.actions` (the loaded record stands
515
648
  * in for the "row"). `rowClick` has no target here and is rejected by
@@ -50,17 +50,34 @@ export type ListColumnSpec = string | {
50
50
  * header with tabular figures, like an entityList column of that field
51
51
  * type. Ignored on entityList columns, where the field's own type wins. */
52
52
  readonly valueType?: "number" | "decimal" | "bigInt" | "money";
53
- /** `false` leaves an empty cell blank instead of drawing the "—" placeholder. Not combinable with `hint`, whose empty sentence is `hint.emptyLabel`. */
54
- readonly emptyPlaceholder?: false;
53
+ /** An empty cell stays blank by default; a string (i18n key or literal) is shown muted in its place, e.g. "No vehicle". Not combinable with `hint`, whose empty sentence is `hint.emptyLabel`. */
54
+ readonly emptyPlaceholder?: string | false;
55
55
  /** Leaves the column out of the compact card layout used below the
56
- * `md` breakpoint (tables keep it). For columns that only make sense
56
+ * `md` breakpoint (phone viewport). For columns that only make sense
57
57
  * next to the others, like a sort key. */
58
58
  readonly hideOnNarrow?: boolean;
59
+ /** Leaves the column out of a table whose container is narrower than `md` (docked assistant panel); the viewport is not looked at,
60
+ * so the phone card still shows it. */
61
+ readonly hideWhenDocked?: true;
59
62
  /** Counterpart of `hideOnNarrow`: the column shows only in the compact card layout and not in the table.
60
63
  * Not combinable with `hideOnNarrow`, `hidden` or `pinned`. */
61
64
  readonly showOnNarrowOnly?: true;
62
65
  /** In the compact card, consecutive `narrowInline` columns stand side by side on one line (12px gap, no separator) instead of one line each. */
63
66
  readonly narrowInline?: true;
67
+ /** One line with a trailing ellipsis in the table; the full text is the cell's `title`. */
68
+ readonly ellipsis?: true;
69
+ /** Free text: the cell wraps instead of ending in "…", and a line break (`\n`) in the value starts a new line (table and phone card). */
70
+ readonly multiline?: true;
71
+ /** Phone card: the column's line stands above the title (muted, e.g. "date, channel") instead of below it. Consecutive `narrowInline` columns share the line. */
72
+ readonly cardAbove?: true;
73
+ /** Cell text in medium weight and foreground colour, like the title column of a board. */
74
+ readonly emphasis?: true;
75
+ /** `"muted"` draws every cell of the column in the muted text colour (e.g. a free-text message beside primary columns). */
76
+ readonly tone?: "muted";
77
+ /** The phone card shows this column as its badge: right of the title, as an outlined neutral pill (a `display: "badge"` column keeps its own pill). Without one the first select column is the badge. */
78
+ readonly cardBadge?: true;
79
+ /** Timestamp or relativeTime column: a value older than this many days shows the date only, without the time. */
80
+ readonly dateOnlyAfterDays?: number;
64
81
  /** Start state for the column picker: the column begins hidden and the
65
82
  * user can show it. Only valid together with `table.columnPicker`. */
66
83
  readonly hidden?: boolean;
@@ -81,10 +98,19 @@ export type ListColumnSpec = string | {
81
98
  * entityList or projectionList table is a rowAction with display "button" (boot-rejected
82
99
  * on columns there). Other list renderers ignore `display`. */
83
100
  readonly display?: ListColumnDisplay;
84
- /** Row field naming the badge tone; only with `display: "badge"`. */
101
+ /** `"primary"` draws a `display: "button"` link as a filled primary button instead of the outline default (dashboard list panels only). Needs `display: "button"`. */
102
+ readonly variant?: "primary";
103
+ /** Row field naming the badge tone: a `ListBadgeTone` word or a `SelectOptionTone` word (`ok`, `bad`, `critical`, `accent`); only with `display: "badge"`. */
85
104
  readonly badgeToneField?: string;
86
105
  /** `false` draws the badge pill without its leading dot; only with `display: "badge"`. */
87
106
  readonly badgeDot?: false;
107
+ /** `"sparkles"` marks an AI-prepared value: the dashboard list draws the badge as the soft blue AI pill with a sparkles icon, like an AI row action; only with `display: "badge"`. */
108
+ readonly badgeIcon?: "sparkles";
109
+ /** Row field holding a second label, drawn as a pill next to the cell's own value
110
+ * (e.g. a vehicle name with a "free" pill). Not combinable with `display` or `hint`. */
111
+ readonly pillField?: string;
112
+ /** Row field naming the tone of the `pillField` pill (a `ListBadgeTone`). Needs `pillField`. */
113
+ readonly pillToneField?: string;
88
114
  /** Row field holding a screen QN (`<feature>:screen:<id>`): the cell links
89
115
  * to that screen when the row sets it and the user may open it. For
90
116
  * query-backed lists (projectionList, relatedList), whose rows can point
@@ -149,9 +175,10 @@ export type RowFieldExtractor = {
149
175
  * `"link"` without one). `"responsive"` is a `"button"` with icon and label
150
176
  * from tablet width up and an icon-only button below it, the label staying the
151
177
  * accessible name (needs a resolved icon, falls back to `"button"` without
152
- * one). Unset: the renderer decides (primary action as link, the rest in the
178
+ * one). `"text"` is a closed state without an action: muted text, not
179
+ * clickable (the row click still applies). Unset: the renderer decides (primary action as link, the rest in the
153
180
  * kebab menu). */
154
- export type RowActionDisplay = "button" | "link" | "icon" | "responsive";
181
+ export type RowActionDisplay = "button" | "link" | "icon" | "responsive" | "text";
155
182
  /** Row-action column layout. `"adaptive"` (default): primary action as link,
156
183
  * the rest in a kebab menu — except actions with an explicit `display`, which
157
184
  * stay inline. `"inline"`: every action inline, no kebab. `"menu"`: every
@@ -159,7 +186,10 @@ export type RowActionDisplay = "button" | "link" | "icon" | "responsive";
159
186
  * (`rowClick: true`) included as an entry, so every row has a kebab; phone
160
187
  * cards draw no kebab when the row opens, a card without a row target keeps it. */
161
188
  export type RowActionMode = "adaptive" | "inline" | "menu";
162
- export type RowAction = RowActionWriteHandler | RowActionNavigate | RowActionDrawer | RowActionClientAction;
189
+ export type RowAction = (RowActionWriteHandler | RowActionNavigate | RowActionDrawer | RowActionClientAction) & {
190
+ /** projectionDetail `footerActions` only: "start" sets the button apart on the left of the footer. */
191
+ readonly align?: "start";
192
+ };
163
193
  export type RowActionWriteHandler = {
164
194
  /** Default for RowActions without an explicitly set `kind` —
165
195
  * backwards-compatible form. Can also be set explicitly. */
@@ -240,8 +270,9 @@ export type RowActionNavigateBase = {
240
270
  readonly rowClick?: boolean;
241
271
  /** Overrides the id-based default icon (see ACTION_ICON_BY_ID in
242
272
  * kumiko-renderer) — closed IconKey vocabulary into the ICONS registry
243
- * (renderer/web), analogous to EditFieldSpec.icon. */
244
- readonly icon?: IconKey;
273
+ * (renderer/web), analogous to EditFieldSpec.icon. `false` draws no icon at all, not even the
274
+ * id-derived default (a plain text button). */
275
+ readonly icon?: IconKey | false;
245
276
  /** Inline render form in the row-action column — see `RowActionDisplay`. */
246
277
  readonly display?: RowActionDisplay;
247
278
  };
@@ -322,8 +353,8 @@ export type RowActionClientAction = {
322
353
  /** Inline render form in the row-action column — see `RowActionDisplay`. */
323
354
  readonly display?: RowActionDisplay;
324
355
  /** i18n key of the toast shown after the handler reported `{ ok: true }`
325
- * (default `kumiko.clientAction.success`). */
326
- readonly successMessage?: string;
356
+ * (default `kumiko.clientAction.success`); `false` shows no toast. */
357
+ readonly successMessage?: string | false;
327
358
  };
328
359
  export type ToolbarAction = ({
329
360
  readonly kind: "navigate";
@@ -463,6 +494,8 @@ export type EntityListScreenDefinition = {
463
494
  readonly columns: readonly ListColumnSpec[];
464
495
  /** Row field holding a SelectOptionTone; the row is toned like relatedList `rowTone`, other values leave it untoned. */
465
496
  readonly rowToneField?: string;
497
+ /** Row field (boolean): a row with a true value is drawn entirely in the muted text colour. */
498
+ readonly mutedRowField?: string;
466
499
  /** Computed row fields from an app query, readable by `rowToneField`, column `hint`, `linkScreenField`/`linkParamsField` and rowAction `visible`/`params`/`payload`; a column may name a decoration field. */
467
500
  readonly rowDecoration?: ListRowDecoration;
468
501
  readonly rowRenderer?: PlatformComponent;
@@ -1,10 +1,11 @@
1
+ import type { FieldCondition } from "./field-state-conditions.ts";
1
2
  import type { SelectOptionTone } from "./fields.ts";
2
3
  import type { AccessRule, AgentScreenHints } from "./handlers.ts";
3
4
  import type { NamedFilterFacetOptions, NamedListFilterRef } from "./named-list-filters.ts";
4
5
  import type { NavIconKey } from "./nav-icon.ts";
5
6
  import type { FormatSpec, PlatformComponent, ScreenNavSugar, ScreenSlots } from "./screen.ts";
6
7
  import type { DashboardStatTone, ScreenVisibility } from "./screen-dashboard.ts";
7
- import type { EditLayout, ListEmptyStateSpec } from "./screen-entity-edit.ts";
8
+ import type { EditLayout, EntityEditAction, ListEmptyStateSpec } from "./screen-entity-edit.ts";
8
9
  import type { ListColumnSpec, ListPaginationMode, ListRowDecoration, ListSortOption, ListSortSpec, RowAction, RowActionMode, RowFieldExtractor, ScreenFilter, ToolbarAction } from "./screen-entity-list.ts";
9
10
  import type { ScreenFallback } from "./screen-fallback.ts";
10
11
  import type { ListBulkAction } from "./screen-list-bulk.ts";
@@ -80,6 +81,8 @@ export type ProjectionListScreenDefinition = {
80
81
  readonly columns: readonly ListColumnSpec[];
81
82
  /** Row field holding a SelectOptionTone; the row is toned like relatedList `rowTone`, other values leave it untoned. */
82
83
  readonly rowToneField?: string;
84
+ /** Row field (boolean): a row with a true value is drawn entirely in the muted text colour. */
85
+ readonly mutedRowField?: string;
83
86
  /** Computed row fields from an app query, merged into the query rows; see `ListRowDecoration`. */
84
87
  readonly rowDecoration?: ListRowDecoration;
85
88
  readonly rowRenderer?: PlatformComponent;
@@ -158,6 +161,8 @@ export type RecordHeaderSpec = {
158
161
  readonly subtitle?: string | readonly RecordHeaderSubtitlePart[];
159
162
  /** Field holding a plain-text subtitle shown instead of `subtitle` below `sm` (e.g. "Main St 12, Berlin · 3 rooms"). */
160
163
  readonly narrowSubtitle?: string;
164
+ /** i18n key of a short title for the phone top bar ("Approval") instead of the record title. */
165
+ readonly narrowTitle?: string;
161
166
  readonly status?: string;
162
167
  /** Formats the badge text (typically `enumOption` with a `keyPrefix`); tones still resolve on the raw value. Needs `status`. Without it, the `status` field's layout renderer is used when it is `enumOption` or `i18nText`. */
163
168
  readonly statusFormat?: FormatSpec;
@@ -204,6 +209,8 @@ export type MetricSpec = {
204
209
  readonly icon?: NavIconKey;
205
210
  /** Formats the displayed value (e.g. `date`, `enumOption`); the tone still resolves on the raw value. */
206
211
  readonly format?: FormatSpec;
212
+ /** Shows the metric only while the loaded record matches; same `{ field, eq | ne | in | notIn }` syntax as a section's `visibleWhen`. `field` must be an output field of the detail query. */
213
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
207
214
  };
208
215
  export type ProjectionDetailScreenDefinition = {
209
216
  readonly id: string;
@@ -261,10 +268,16 @@ export type ProjectionDetailScreenDefinition = {
261
268
  readonly metrics?: readonly MetricSpec[];
262
269
  /** "tiles" draws the metrics as the dashboard KPI tiles (StatCard) instead of the plain band. */
263
270
  readonly metricsStyle?: "band" | "tiles";
264
- /** `narrow: "after-guidance"` moves the metrics below the summary, banner and steps on screens under md, ahead of the tabs. Works with the page header and the head card; only the metric tiles move, the subtitle and status line stay under the title. */
271
+ /** On screens under md, `narrow: "after-guidance"` moves the metrics below the summary, banner and steps, ahead of the tabs; `"before-steps"` puts them below the summary and banner, ahead of the next step. Works with the page header and the head card; only the metric tiles move, the subtitle and status line stay under the title. */
265
272
  readonly metricsPlacement?: {
266
- readonly narrow?: "after-guidance";
273
+ readonly narrow?: "after-guidance" | "before-steps";
267
274
  };
275
+ /** Record field holding one line of text shown instead of the metrics below `sm`. The metrics stay on larger screens; an empty value keeps them on phones too. */
276
+ readonly mobileSummary?: string;
277
+ /** `false` leaves out the "On this page" navigation of a stacked (non-tabs) layout. */
278
+ readonly pageNavigation?: false;
279
+ /** A tab holding fields sections and a relatedList with `photoGrid` shows the fields left and the photos right from `lg` up. */
280
+ readonly photosBeside?: true;
268
281
  /** Path above the header (query column holding items). */
269
282
  readonly breadcrumb?: RecordBreadcrumbSpec;
270
283
  /** One emphasized sentence below the header. */
@@ -283,8 +296,10 @@ export type ProjectionDetailScreenDefinition = {
283
296
  * displayed record stands in for the "row", so `pick`/`map`, `visible`,
284
297
  * `confirm`/`confirmLabel` and `style` keep their meaning unchanged.
285
298
  * `rowClick` has no target here (there is no row to click) and is
286
- * rejected by the boot-validator. */
287
- readonly actions?: readonly RowAction[];
299
+ * rejected by the boot-validator. `placement: "menu"` puts the action
300
+ * into the header "…" menu instead of a button (without a header menu it
301
+ * falls back to inline). */
302
+ readonly actions?: readonly EntityEditAction[];
288
303
  /** Id of the action that stays the visible header button when the actions
289
304
  * collapse into a menu (and the one that keeps the phone icon slot when it
290
305
  * has an icon and no confirm). An `actions` id or `"edit"` (the default edit
@@ -295,9 +310,21 @@ export type ProjectionDetailScreenDefinition = {
295
310
  * collapses into the menu. Same id rules as `primaryAction`; the phone header keeps
296
311
  * its single icon button. */
297
312
  readonly inlineActions?: readonly string[];
313
+ /** Ids of `actions` shown in the pinned footer bar instead of the header, in declaration order.
314
+ * Style "primary" marks the main button. An id must not also be `primaryAction` or in `inlineActions`. */
315
+ readonly footerActions?: readonly string[];
316
+ /** i18n key of a note on the left of the footer bar ("Changes go out with the release"); hidden below `sm`. Needs `footerActions`. */
317
+ readonly footerHint?: string;
318
+ /** Tab that opens first when the URL names none: the first rule whose condition holds on the record wins, else the first visible tab. Needs `layout.mode: "tabs"`; every tab stays visible. */
319
+ readonly initialTab?: readonly ProjectionDetailInitialTab[];
298
320
  /** How head fields render. Default "text" — plain text instead of a
299
321
  * disabled Input, since every field on this screen type is forced
300
322
  * readOnly anyway (there is no write path, see the shim doc above).
301
323
  * Set "form" to opt back into the disabled-Input look. */
302
324
  readonly valueDisplay?: "form" | "text";
303
325
  };
326
+ /** One `initialTab` rule: `tab` is a section id of the layout. */
327
+ export type ProjectionDetailInitialTab = {
328
+ readonly when: Exclude<FieldCondition, boolean>;
329
+ readonly tab: string;
330
+ };
@@ -1,4 +1,6 @@
1
+ import type { FieldCondition } from "./field-state-conditions.ts";
1
2
  import type { SelectOptionTone } from "./fields.ts";
3
+ import type { IconKey } from "./nav-icon.ts";
2
4
  import type { RowAction } from "./screen-entity-list.ts";
3
5
  export type RecordBreadcrumbItem = {
4
6
  readonly label: string;
@@ -53,10 +55,14 @@ export type RecordSummarySpec = {
53
55
  readonly toneField?: string;
54
56
  /** Row field with a shorter sentence shown instead of `field` below `sm`. */
55
57
  readonly narrowField?: string;
58
+ /** Draws the sentence as plain text led by this icon (e.g. "sparkles" for an AI statement) instead of the bordered box. */
59
+ readonly icon?: IconKey;
56
60
  };
57
61
  export type RecordBannerSpec = {
58
62
  /** Holds `RecordNotice | null`; null shows no banner. */
59
63
  readonly field: string;
64
+ /** Draws the notice without the tone icon. */
65
+ readonly iconless?: true;
60
66
  readonly actions?: readonly RecordGuidanceAction[];
61
67
  };
62
68
  export type RecordStepsSpec = {
@@ -72,6 +78,10 @@ export type RecordStepsSpec = {
72
78
  readonly narrowLimit?: number;
73
79
  /** Plural base key for the toggle of the hidden rest: define `<key>.one` and `<key>.other` (the latter with `{count}`). Default `kumiko.detail.steps.more`. */
74
80
  readonly narrowMoreLabel?: string;
81
+ /** i18n key of a short label before each step's further actions ("Clarify first?"). */
82
+ readonly moreActionsLabel?: string;
83
+ /** The whole panel is drawn only while the condition holds on the record. Default: always. */
84
+ readonly visibleWhen?: Exclude<FieldCondition, boolean>;
75
85
  readonly actions?: readonly RecordGuidanceAction[];
76
86
  };
77
87
  export type RecordProgressStep = {
package/dist/screen.d.ts CHANGED
@@ -29,10 +29,23 @@ export interface FieldFormatRegistry {
29
29
  /** IANA zone id (e.g. "Europe/Berlin"). Default: the runtime's zone. */
30
30
  readonly timeZone?: string;
31
31
  };
32
+ /** Epoch ms or ISO timestamp, shown as "5 min. ago" at render time (a table cell does not tick).
33
+ * Defaults: `style: "short"`, `withTime: true` (clock time on "yesterday" and on the absolute date; `false` leaves it out),
34
+ * `absoluteAfterDays: 7` (from then on the absolute date, "29 Oct 2026", replaces the relative text); under a minute reads "just now". */
35
+ relativeTime: {
36
+ readonly locale?: string;
37
+ readonly style?: "long" | "short" | "narrow";
38
+ readonly absoluteAfterDays?: number;
39
+ readonly withTime?: boolean;
40
+ /** IANA zone id for the clock time and the day boundary. Default: the runtime's zone. */
41
+ readonly timeZone?: string;
42
+ };
32
43
  date: {
33
44
  readonly locale?: string;
34
45
  readonly dateStyle?: "full" | "long" | "medium" | "short";
35
46
  };
47
+ /** Telephone number shown as a `tel:` link in list cells, like a read-only `format: "phone"` field. */
48
+ phone: Record<never, never>;
36
49
  boolean: {
37
50
  readonly trueLabel?: string;
38
51
  readonly falseLabel?: string;
@@ -120,9 +133,9 @@ export type ScreenDefinition = EntityListScreenDefinition | ProjectionListScreen
120
133
  export type { NamedFilterFacetOptions } from "./named-list-filters.ts";
121
134
  export type { ActionFormFooterAction, ActionFormLoad, ActionFormRedirect, ActionFormScreenDefinition, ActionFormSuccessFact, ActionFormSuccessItems, ActionFormSuccessLink, FormFieldDerivation, FormFieldDerivationWithoutList, SecretMintConfirmStep, SecretMintScreenDefinition, SecretReveal, SecretRevealField, } from "./screen-action-form.ts";
122
135
  export type { ConfigEditAction, ConfigEditScreenDefinition, CustomScreenDefinition, CustomScreenRoute, SecretsEditScreenDefinition, SecretsEditSection, } from "./screen-custom-config.ts";
123
- export type { DashboardChartKind, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardChartTone, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListFooterLink, DashboardListNarrow, DashboardListPanel, DashboardListRowLink, DashboardListRowToneMarker, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelEmptyState, DashboardPanelGate, DashboardPanelNarrow, DashboardPanelQueryOptions, DashboardPanelSpan, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScopeDefinition, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupLayout, DashboardStatGroupLink, DashboardStatGroupNarrow, DashboardStatGroupPanel, DashboardStatPanel, DashboardStatTone, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardTimeRangeDefinition, DashboardValueFormat, ScreenVisibility, } from "./screen-dashboard.ts";
136
+ export type { DashboardChartKind, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardChartTone, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardLayout, DashboardListFooterLink, DashboardListNarrow, DashboardListPanel, DashboardListRowLink, DashboardListRowToneMarker, DashboardMoneyParam, DashboardPanelColumn, DashboardPanelDefinition, DashboardPanelEmptyState, DashboardPanelGate, DashboardPanelNarrow, DashboardPanelQueryOptions, DashboardPanelSpan, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScopeDefinition, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupLayout, DashboardStatGroupLink, DashboardStatGroupNarrow, DashboardStatGroupPanel, DashboardStatPanel, DashboardStatTone, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardTimeRangeDefinition, DashboardValueFormat, ScreenVisibility, } from "./screen-dashboard.ts";
124
137
  export { DASHBOARD_MIN_REFRESH_SECONDS, DASHBOARD_STAT_TONES } from "./screen-dashboard.ts";
125
- export type { EditExtensionSection, EditFieldGroup, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityWriteExcludedFields, FieldAffix, FieldFillAction, FormWidth, ListEmptyStateSpec, RelatedListEmptyStateSpec, RelatedListEmptyStateVariant, RelatedListRowTone, } from "./screen-entity-edit.ts";
138
+ export type { EditExtensionSection, EditFieldGroup, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditStepListSection, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityWriteExcludedFields, FieldAffix, FieldAiAssist, FieldAiAssistChip, FieldBadge, FieldFillAction, FieldTextRef, FieldValueChips, FormWidth, ListEmptyStateSpec, RelatedListEmptyStateSpec, RelatedListEmptyStateVariant, RelatedListRowTone, StepListItem, } from "./screen-entity-edit.ts";
126
139
  export { relatedListGroupHeaderLabel, relatedListGroupKey } from "./screen-entity-edit.ts";
127
140
  export type { EntityListFacetConfig, EntityListFacetExtraOption, EntityListScreenDefinition, ListBadgeTone, ListColumnDisplay, ListColumnHint, ListColumnSpec, ListPaginationMode, ListRowDecoration, ListSortDir, ListSortOption, ListSortSpec, RelatedListToolbarAction, RowAction, RowActionClientAction, RowActionDisplay, RowActionDrawer, RowActionMode, RowActionNavigate, RowActionNavigateBase, RowActionWriteHandler, RowFieldExtractor, ScreenFilter, ScreenFilterOp, ToolbarAction, } from "./screen-entity-list.ts";
128
141
  export type { EntityListExpandableRow, ExpandableRowGrouping } from "./screen-expandable-row.ts";
@@ -132,5 +145,5 @@ export type { ListBulkAction } from "./screen-list-bulk.ts";
132
145
  export { LIST_BULK_ACTION_KEYS, MAX_BULK_SELECTION } from "./screen-list-bulk.ts";
133
146
  export type { BundledListsOptions, ListColumnPin, ListNarrowFacets, ListPayloadCapabilities, ListTableDensity, ListTableExportOptions, ListTableFrame, ListTableGrouping, ListTableOptions, ListTableSummaryRow, ListTableTotal, ListToolbarActionsPlacement, } from "./screen-list-table.ts";
134
147
  export { DEFAULT_EXPORT_MAX_ROWS, entityHasFilterableFields, entityListDeclaresFilters, entityListDeclaresSearch, LIST_COLUMN_MAX_WIDTH_PX, LIST_COLUMN_PINS, LIST_NARROW_FACETS, LIST_TABLE_DENSITIES, LIST_TABLE_DENSITY_KEYS, LIST_TABLE_EXPORT_KEYS, LIST_TABLE_FRAMES, LIST_TABLE_GROUPING_KEYS, LIST_TABLE_OPTION_KEYS, LIST_TABLE_SUMMARY_ROW_KEYS, LIST_TABLE_TOTAL_KEYS, LIST_TOOLBAR_ACTIONS_PLACEMENTS, listPayloadKeysSent, MAX_EXPORT_MAX_ROWS, } from "./screen-list-table.ts";
135
- export type { ListFacetSpec, MetricNavigate, MetricSpec, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, RecordHeaderSpec, RecordHeaderSubtitlePart, } from "./screen-projection.ts";
148
+ export type { ListFacetSpec, MetricNavigate, MetricSpec, ProjectionDetailInitialTab, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, RecordHeaderSpec, RecordHeaderSubtitlePart, } from "./screen-projection.ts";
136
149
  export type { RecordBannerSpec, RecordBreadcrumbItem, RecordBreadcrumbSpec, RecordNotice, RecordProgress, RecordProgressSpec, RecordProgressStep, RecordStep, RecordStepsSpec, RecordSummarySpec, } from "./screen-record-guidance.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.415.0",
3
+ "version": "0.417.0",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "MIT",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",