@cosmicdrift/kumiko-renderer 0.385.0 → 0.387.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/LICENSE +21 -57
- package/dist/app/action-form-body.d.ts +2 -2
- package/dist/app/action-form-body.js +2 -2
- package/dist/app/action-form-shim.d.ts +8 -8
- package/dist/app/action-form-shim.js +20 -22
- package/dist/app/app-features-context.js +4 -4
- package/dist/app/column-renderers.d.ts +7 -9
- package/dist/app/column-renderers.js +15 -18
- package/dist/app/config-edit-body.js +1 -1
- package/dist/app/config-edit-shim.d.ts +7 -8
- package/dist/app/config-edit-shim.js +18 -20
- package/dist/app/custom-screens.d.ts +3 -3
- package/dist/app/custom-screens.js +8 -8
- package/dist/app/dashboard-body.d.ts +2 -2
- package/dist/app/dashboard-body.js +2 -2
- package/dist/app/entity-edit-prefill.js +9 -9
- package/dist/app/entity-edit-screen.js +4 -4
- package/dist/app/entity-list-screen.js +3 -3
- package/dist/app/extension-form-submit.d.ts +1 -1
- package/dist/app/extension-form-submit.js +14 -15
- package/dist/app/extension-sections.d.ts +24 -25
- package/dist/app/extension-sections.js +10 -10
- package/dist/app/feature-schema.js +11 -11
- package/dist/app/form-schema.js +1 -1
- package/dist/app/header-actions-bar.js +1 -1
- package/dist/app/kumiko-screen.js +8 -10
- package/dist/app/layout-fields.js +1 -1
- package/dist/app/list-facets.js +3 -3
- package/dist/app/nav.d.ts +10 -10
- package/dist/app/nav.js +13 -13
- package/dist/app/projection-detail-body.js +4 -4
- package/dist/app/projection-detail-shim.d.ts +6 -5
- package/dist/app/projection-detail-shim.js +23 -22
- package/dist/app/projection-list-body.js +10 -10
- package/dist/app/projection-list-shim.d.ts +5 -5
- package/dist/app/projection-list-shim.js +17 -18
- package/dist/app/qn.js +10 -12
- package/dist/app/qualify-screen-id.js +1 -1
- package/dist/app/screen-access.js +2 -2
- package/dist/app/screen-shared.js +1 -1
- package/dist/app/secret-mint-body.js +4 -4
- package/dist/app/write-failed-error.js +8 -7
- package/dist/components/embedded-list-field.js +4 -4
- package/dist/components/grid-cell-for-field.d.ts +1 -1
- package/dist/components/reference-create-dialog.js +3 -3
- package/dist/components/related-list-section.d.ts +1 -1
- package/dist/components/related-list-section.js +28 -5
- package/dist/components/render-edit-logic.js +1 -1
- package/dist/components/render-edit-types.d.ts +6 -6
- package/dist/components/render-edit.js +63 -65
- package/dist/components/render-field.d.ts +7 -7
- package/dist/components/render-field.js +57 -59
- package/dist/components/render-list.d.ts +43 -44
- package/dist/components/render-list.js +63 -67
- package/dist/components/use-wizard-form-draft.js +10 -10
- package/dist/context/dispatcher-context.js +5 -5
- package/dist/context/user-roles-context.js +2 -2
- package/dist/headless/apex/index.d.ts +1 -2
- package/dist/headless/apex/index.js +5 -6
- package/dist/headless/form/form-controller.js +6 -6
- package/dist/headless/form/zod-bridge.js +2 -2
- package/dist/headless/format/money.js +1 -1
- package/dist/headless/index.js +2 -2
- package/dist/headless/view-model/edit.js +2 -2
- package/dist/headless/view-model/list.js +3 -4
- package/dist/headless/view-model/types.d.ts +3 -3
- package/dist/hooks/reference-limits.js +11 -12
- package/dist/hooks/use-list-url-state.d.ts +13 -13
- package/dist/hooks/use-list-url-state.js +21 -22
- package/dist/hooks/use-query.js +3 -3
- package/dist/hooks/use-reference-lookup.js +16 -17
- package/dist/hooks/use-store.js +18 -22
- package/dist/hooks/use-stream-handler.js +4 -2
- package/dist/i18n-defaults.js +2 -8
- package/dist/i18n.d.ts +10 -10
- package/dist/i18n.js +25 -25
- package/dist/index.js +5 -4
- package/dist/live/dispatcher-live.js +2 -2
- package/dist/primitives.d.ts +225 -221
- package/dist/primitives.js +1 -1
- package/dist/sse/live-events.d.ts +5 -5
- package/dist/sse/live-events.js +17 -17
- package/dist/tokens.d.ts +8 -8
- package/dist/tokens.js +16 -17
- package/dist/web/app/browser-locale.d.ts +9 -9
- package/dist/web/app/browser-locale.js +19 -19
- package/dist/web/app/client-plugin.d.ts +44 -52
- package/dist/web/app/client-plugin.js +4 -5
- package/dist/web/app/create-app.d.ts +28 -31
- package/dist/web/app/create-app.js +21 -22
- package/dist/web/app/document-lang-sync.js +1 -1
- package/dist/web/app/draft-storage.js +1 -1
- package/dist/web/app/nav-providers-context.d.ts +3 -3
- package/dist/web/app/nav-providers-context.js +3 -3
- package/dist/web/app/nav.d.ts +18 -17
- package/dist/web/app/nav.js +66 -64
- package/dist/web/app/rich-content-editor.js +1 -1
- package/dist/web/components/config-cascade.js +17 -18
- package/dist/web/components/config-source-badge.js +4 -4
- package/dist/web/layout/app-layout.d.ts +9 -9
- package/dist/web/layout/app-layout.js +2 -2
- package/dist/web/layout/avatar.d.ts +4 -3
- package/dist/web/layout/avatar.js +15 -17
- package/dist/web/layout/default-app-shell.d.ts +22 -23
- package/dist/web/layout/editor-panel.js +3 -3
- package/dist/web/layout/nav-tree.js +86 -84
- package/dist/web/layout/profile-menu.d.ts +1 -1
- package/dist/web/layout/sidebar-brand.d.ts +7 -7
- package/dist/web/layout/sidebar-user.d.ts +1 -1
- package/dist/web/layout/sidebar-user.js +4 -4
- package/dist/web/layout/sidebar.d.ts +8 -8
- package/dist/web/layout/sidebar.js +7 -7
- package/dist/web/layout/target-resolver-stub.d.ts +5 -5
- package/dist/web/layout/target-resolver-stub.js +20 -20
- package/dist/web/layout/target-url.d.ts +7 -7
- package/dist/web/layout/target-url.js +22 -22
- package/dist/web/layout/theme-toggle.js +4 -5
- package/dist/web/layout/workspace-shell.d.ts +21 -21
- package/dist/web/layout/workspace-shell.js +29 -30
- package/dist/web/lib/cn.d.ts +4 -4
- package/dist/web/lib/cn.js +4 -4
- package/dist/web/primitives/action-menu.d.ts +8 -8
- package/dist/web/primitives/action-menu.js +14 -13
- package/dist/web/primitives/calendar-popover.d.ts +1 -1
- package/dist/web/primitives/calendar-popover.js +10 -10
- package/dist/web/primitives/card-styles.js +1 -1
- package/dist/web/primitives/card.js +2 -2
- package/dist/web/primitives/combobox.d.ts +12 -12
- package/dist/web/primitives/combobox.js +34 -35
- package/dist/web/primitives/data-table-cell.js +2 -2
- package/dist/web/primitives/data-table.js +2 -3
- package/dist/web/primitives/date-field.js +2 -2
- package/dist/web/primitives/date-input.js +4 -4
- package/dist/web/primitives/default-form.js +2 -2
- package/dist/web/primitives/dropdown-menu.js +14 -15
- package/dist/web/primitives/embedded-list-input.js +3 -3
- package/dist/web/primitives/facet-filter.js +1 -1
- package/dist/web/primitives/field.js +9 -8
- package/dist/web/primitives/form.d.ts +1 -1
- package/dist/web/primitives/form.js +6 -6
- package/dist/web/primitives/input.js +2 -2
- package/dist/web/primitives/layout-elements.js +1 -1
- package/dist/web/primitives/layout.js +2 -2
- package/dist/web/primitives/located-timestamp-input.js +4 -4
- package/dist/web/primitives/money-input.js +13 -17
- package/dist/web/primitives/pager.js +1 -1
- package/dist/web/primitives/row-actions.js +3 -4
- package/dist/web/primitives/secret-reveal.js +1 -1
- package/dist/web/primitives/timestamp-input.d.ts +9 -9
- package/dist/web/primitives/timestamp-input.js +21 -21
- package/dist/web/primitives/toast.js +12 -13
- package/dist/web/sse/live-events.d.ts +6 -6
- package/dist/web/sse/live-events.js +3 -3
- package/dist/web/tokens.d.ts +11 -12
- package/dist/web/tokens.js +35 -37
- package/dist/web/version/update-checker.js +14 -13
- package/dist/web/widgets/ai-text-field.js +1 -1
- package/dist/web/widgets/charts.d.ts +10 -10
- package/dist/web/widgets/charts.js +8 -8
- package/dist/web/widgets/collapsible-section.d.ts +3 -3
- package/dist/web/widgets/collapsible-section.js +6 -6
- package/dist/web/widgets/detail-list.d.ts +1 -3
- package/dist/web/widgets/detail-list.js +1 -3
- package/dist/web/widgets/feed-list.d.ts +2 -2
- package/dist/web/widgets/feed-list.js +2 -2
- package/dist/web/widgets/form-fields.d.ts +14 -14
- package/dist/web/widgets/form-fields.js +14 -13
- package/dist/web/widgets/index.js +4 -4
- package/dist/web/widgets/infinity-list.js +3 -3
- package/dist/web/widgets/mode-switch.d.ts +2 -2
- package/dist/web/widgets/mode-switch.js +2 -2
- package/dist/web/widgets/progress-list.d.ts +1 -2
- package/dist/web/widgets/progress-list.js +1 -2
- package/dist/web/widgets/query-table.d.ts +6 -6
- package/dist/web/widgets/result-panel.d.ts +16 -16
- package/dist/web/widgets/result-panel.js +10 -10
- package/dist/web/widgets/section-card.d.ts +3 -3
- package/dist/web/widgets/section-card.js +3 -3
- package/dist/web/widgets/stat.d.ts +4 -4
- package/dist/web/widgets/stat.js +6 -6
- package/dist/web/widgets/states.d.ts +4 -4
- package/dist/web/widgets/states.js +4 -4
- package/dist/web/widgets/use-draft.d.ts +7 -7
- package/dist/web/widgets/use-draft.js +7 -7
- package/package.json +6 -6
package/dist/primitives.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type { RuntimeRenderer };
|
|
|
8
8
|
* element. */
|
|
9
9
|
export type DataAttributes = Readonly<Record<`data-${string}`, string>>;
|
|
10
10
|
/** Structural marker a top-level `actions` node can carry so DefaultForm's
|
|
11
|
-
* sticky-footer split
|
|
11
|
+
* sticky-footer split treats it as the pinned primary action even
|
|
12
12
|
* though it isn't a `Button` with `type="submit"` — e.g. RenderEdit's
|
|
13
13
|
* footer-slot mount, whose actual rendered button is opaque app code the
|
|
14
14
|
* split can't inspect (see `ScreenSlots.footerPrimary`). */
|
|
@@ -24,10 +24,10 @@ export type FooterActionMarker = {
|
|
|
24
24
|
readonly [FOOTER_ACTION_ROLE_PROP]?: FooterActionRole;
|
|
25
25
|
readonly [NARROW_LABEL_PROP]?: string;
|
|
26
26
|
};
|
|
27
|
-
/** Standard
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
/** Standard button. `loading` displays a spinner instead of the children and
|
|
28
|
+
* should be combined with `disabled` when the action must remain blocked until
|
|
29
|
+
* loading finishes (for example, during an async submit). Native
|
|
30
|
+
* implementations may render the spinner as an activity indicator. */
|
|
31
31
|
export type ButtonProps = ButtonBaseProps & ({
|
|
32
32
|
readonly children: ReactNode;
|
|
33
33
|
} | {
|
|
@@ -39,9 +39,9 @@ type ButtonBaseProps = {
|
|
|
39
39
|
readonly type?: "button" | "submit";
|
|
40
40
|
readonly onClick?: () => void | Promise<void>;
|
|
41
41
|
readonly disabled?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
/** Render a spinner instead of the children. Callers should also set
|
|
43
|
+
* `disabled` when the action is blocked until loading completes, preventing
|
|
44
|
+
* double submission. */
|
|
45
45
|
readonly loading?: boolean;
|
|
46
46
|
/** Semantic class — default="primary". Custom impls decide what this
|
|
47
47
|
* becomes visually; the renderers use "primary" for Save, "danger" for
|
|
@@ -50,11 +50,11 @@ type ButtonBaseProps = {
|
|
|
50
50
|
* destructive action as red text instead of a red fill, "ghost" for a
|
|
51
51
|
* low-emphasis primary-colored text action beside a filled primary. */
|
|
52
52
|
readonly variant?: "primary" | "secondary" | "danger" | "link" | "danger-ghost" | "ghost";
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
53
|
+
/** Size—default="md". "sm" is for compact inline actions (toolbars,
|
|
54
|
+
* list rows); "icon" is for square icon-only buttons. */
|
|
55
55
|
readonly size?: "sm" | "md" | "icon";
|
|
56
|
-
/**
|
|
57
|
-
*
|
|
56
|
+
/** Accessible label—required for icon-only buttons (when children contain
|
|
57
|
+
* only an icon or character), otherwise the button has no accessible name. */
|
|
58
58
|
readonly ariaLabel?: string;
|
|
59
59
|
/** Tooltip — rendered as the `title` attribute. */
|
|
60
60
|
readonly title?: string;
|
|
@@ -62,9 +62,9 @@ type ButtonBaseProps = {
|
|
|
62
62
|
readonly pressed?: boolean;
|
|
63
63
|
/** Disclosure state for buttons that open a menu or panel — web sets `aria-expanded`. */
|
|
64
64
|
readonly expanded?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
/** Width—default="auto" (content width). "full" stretches CTA buttons to
|
|
66
|
+
* the container width (cards/panels). Other widths belong to the container's
|
|
67
|
+
* layout, not to a button prop; the kit excludes arbitrary sizing here. */
|
|
68
68
|
readonly width?: "full" | "auto";
|
|
69
69
|
readonly testId?: string;
|
|
70
70
|
/** Layout extras, merged via cn(). */
|
|
@@ -78,10 +78,10 @@ type ButtonBaseProps = {
|
|
|
78
78
|
readonly iconEnd?: NavIconKey;
|
|
79
79
|
readonly dataAttributes?: DataAttributes;
|
|
80
80
|
};
|
|
81
|
-
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
81
|
+
/** Navigation link. `variant="button"` applies button styling to a semantic
|
|
82
|
+
* anchor (for example, “Zum Login" after reset success); `muted` makes it a
|
|
83
|
+
* subtle secondary link. Internal SPA navigation uses the browser default;
|
|
84
|
+
* history integration belongs to the navigation layer, not this primitive. */
|
|
85
85
|
export type LinkProps = {
|
|
86
86
|
readonly href: string;
|
|
87
87
|
readonly variant?: "default" | "button" | "muted";
|
|
@@ -98,10 +98,10 @@ export type LinkProps = {
|
|
|
98
98
|
readonly testId?: string;
|
|
99
99
|
readonly dataAttributes?: DataAttributes;
|
|
100
100
|
};
|
|
101
|
-
/** Banner
|
|
102
|
-
* "Screen not found"). `padded`
|
|
103
|
-
*
|
|
104
|
-
*
|
|
101
|
+
/** Banner for an inline message or page state (for example, "Loading…" or
|
|
102
|
+
* "Screen not found"). `padded` adds outer spacing so the banner does not
|
|
103
|
+
* touch the main border edge to edge, which matters because `<main>` no
|
|
104
|
+
* longer provides its own padding. */
|
|
105
105
|
export type BannerProps = {
|
|
106
106
|
/** "error" for alerts (conflict, network error), "info" for neutral
|
|
107
107
|
* placeholders (not-found, loading), "loading" for load states, "warning"
|
|
@@ -113,17 +113,17 @@ export type BannerProps = {
|
|
|
113
113
|
readonly title?: ReactNode;
|
|
114
114
|
readonly titleTestId?: string;
|
|
115
115
|
readonly children: ReactNode;
|
|
116
|
-
/** Optional
|
|
117
|
-
* laden"). Inline,
|
|
116
|
+
/** Optional—additional buttons or elements to the right of the text (for
|
|
117
|
+
* example, "Neu laden"). Inline, not a separate block. */
|
|
118
118
|
readonly actions?: ReactNode;
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
119
|
+
/** Adds outer spacing around the banner for page states where it renders
|
|
120
|
+
* alone in the main area (KumikoScreen "not-found", "loading", etc.). The
|
|
121
|
+
* web implementation adds p-6 as margin around the banner. */
|
|
122
122
|
readonly padded?: boolean;
|
|
123
123
|
readonly testId?: string;
|
|
124
124
|
/** Set when a `<Field>` wraps this Banner as its control (no actual
|
|
125
125
|
* input exists for the label to target — see render-field.tsx's
|
|
126
|
-
* unsupported-field-type fallback
|
|
126
|
+
* unsupported-field-type fallback). The web implementation uses
|
|
127
127
|
* it to derive `role="group"` + `aria-labelledby`, not `htmlFor`: a
|
|
128
128
|
* `<label for>` on a non-labelable element like a `<div>` is inert for
|
|
129
129
|
* screen readers. */
|
|
@@ -150,9 +150,9 @@ export type FieldProps = {
|
|
|
150
150
|
readonly testId?: string;
|
|
151
151
|
};
|
|
152
152
|
readonly children: ReactNode;
|
|
153
|
-
/** Label
|
|
154
|
-
*
|
|
155
|
-
*
|
|
153
|
+
/** Label layout. `stacked` (default) places the label above the control.
|
|
154
|
+
* `inline` places the control and label beside each other (box left, label
|
|
155
|
+
* right), for checkbox/switch fields (boolean), following the shadcn pattern. */
|
|
156
156
|
readonly layout?: "stacked" | "inline" | "row";
|
|
157
157
|
/** Marks a field whose value is set at this level (differs from the
|
|
158
158
|
* inherited one). Only `layout="row"` draws it: a 2px primary line on the
|
|
@@ -168,9 +168,10 @@ export type FieldProps = {
|
|
|
168
168
|
readonly changed?: boolean;
|
|
169
169
|
readonly testId?: string;
|
|
170
170
|
};
|
|
171
|
-
/** Discriminated union
|
|
172
|
-
*
|
|
173
|
-
*
|
|
171
|
+
/** Discriminated union: each input kind has its own value/onChange
|
|
172
|
+
* signature. Custom implementations can dispatch internally, render a
|
|
173
|
+
* different control (toggle instead of checkbox), or customize individual
|
|
174
|
+
* kinds. */
|
|
174
175
|
/** Button beside a single-line text/number input that fills it with a
|
|
175
176
|
* suggestion. Stays usable on a `disabled` input (the readOnly+fill case). */
|
|
176
177
|
export type InputFillAction = {
|
|
@@ -205,17 +206,17 @@ export type InputProps = {
|
|
|
205
206
|
readonly disabled?: boolean;
|
|
206
207
|
readonly required?: boolean;
|
|
207
208
|
readonly hasError?: boolean;
|
|
208
|
-
/** Hint
|
|
209
|
-
*
|
|
209
|
+
/** Hint text shown when the field is empty. Used for search inputs in
|
|
210
|
+
* toolbars ("Suchen…") where no label is practical. */
|
|
210
211
|
readonly placeholder?: string;
|
|
211
|
-
/** Browser
|
|
212
|
-
* `<input autocomplete
|
|
212
|
+
/** Browser autofill / native keyboard hint. Web applies this to
|
|
213
|
+
* `<input autocomplete=...>`; native applies it to `textContentType`. */
|
|
213
214
|
readonly autoComplete?: string;
|
|
214
|
-
/** `data-testid`
|
|
215
|
-
*
|
|
215
|
+
/** Sets `data-testid` on the actual `<input>` so app tests can address the
|
|
216
|
+
* element directly (getByTestId + readOnly/disabled assertions). */
|
|
216
217
|
readonly testId?: string;
|
|
217
|
-
/** Read-only
|
|
218
|
-
*
|
|
218
|
+
/** Read-only input (for example, a generated free-tier slug). Not
|
|
219
|
+
* `disabled`, so it remains focusable and copyable. */
|
|
219
220
|
readonly readOnly?: boolean;
|
|
220
221
|
/** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer/web). */
|
|
221
222
|
readonly icon?: FieldIconKey;
|
|
@@ -237,8 +238,8 @@ export type InputProps = {
|
|
|
237
238
|
readonly required?: boolean;
|
|
238
239
|
readonly hasError?: boolean;
|
|
239
240
|
readonly placeholder?: string;
|
|
240
|
-
/** Default "email". Apps
|
|
241
|
-
*
|
|
241
|
+
/** Default "email". Apps that need "username" (a username-or-email login
|
|
242
|
+
* form) pass that value through. */
|
|
242
243
|
readonly autoComplete?: string;
|
|
243
244
|
readonly testId?: string;
|
|
244
245
|
} | {
|
|
@@ -263,9 +264,9 @@ export type InputProps = {
|
|
|
263
264
|
readonly hasError?: boolean;
|
|
264
265
|
/** Hint text shown when the field is empty (analog to kind:"text"). */
|
|
265
266
|
readonly placeholder?: string;
|
|
266
|
-
/** "current-password"
|
|
267
|
-
*
|
|
268
|
-
* Native
|
|
267
|
+
/** "current-password" for login, "new-password" for reset/signup—browser
|
|
268
|
+
* password managers use this to decide whether to save the value.
|
|
269
|
+
* Native uses textContentType="password" / "newPassword". */
|
|
269
270
|
readonly autoComplete?: "current-password" | "new-password";
|
|
270
271
|
/** Icon button inside the field's trailing edge (clear a stored value,
|
|
271
272
|
* undo a pending removal). `label` is its accessible name + tooltip. */
|
|
@@ -326,7 +327,7 @@ export type InputProps = {
|
|
|
326
327
|
readonly kind: "file" | "image";
|
|
327
328
|
readonly id: string;
|
|
328
329
|
readonly name: string;
|
|
329
|
-
/** FileRef
|
|
330
|
+
/** FileRef UUID (stored file) or null (no upload). */
|
|
330
331
|
readonly value: string | null;
|
|
331
332
|
/** Implementations must offer their own remove control that calls
|
|
332
333
|
* `onChange(null)`: FileListField relies on it to drop a file from an
|
|
@@ -338,8 +339,8 @@ export type InputProps = {
|
|
|
338
339
|
/** Erlaubte Extensions/MIME (z.B. ["jpg","png"]) → `accept`-Attribut. */
|
|
339
340
|
readonly accept?: readonly string[];
|
|
340
341
|
readonly maxSize?: string;
|
|
341
|
-
/**
|
|
342
|
-
*
|
|
342
|
+
/** For the upload POST `/api/files`: the endpoint validates maxSize/accept
|
|
343
|
+
* against the field definition for (entityType, fieldName). */
|
|
343
344
|
readonly entityType?: string;
|
|
344
345
|
/** Screen QN of the actionForm the field belongs to; sent as `actionForm` instead of
|
|
345
346
|
* `entityType`, so the upload stays pending for that form's field. */
|
|
@@ -388,9 +389,9 @@ export type InputProps = {
|
|
|
388
389
|
readonly name: string;
|
|
389
390
|
readonly value: string;
|
|
390
391
|
readonly onChange: (v: string | undefined) => void;
|
|
391
|
-
/** Locale
|
|
392
|
-
*
|
|
393
|
-
*
|
|
392
|
+
/** Locale for display and input parsing. Default = browser locale via
|
|
393
|
+
* navigator.language. Apps with their own LocaleResolver can pass through
|
|
394
|
+
* their current locale. */
|
|
394
395
|
readonly locale?: string;
|
|
395
396
|
/** Datumsgrenzen als ISO `yyyy-mm-dd` — begrenzen Picker (Jahres-
|
|
396
397
|
* Dropdown-Range + ausgegraute Tage). */
|
|
@@ -405,10 +406,10 @@ export type InputProps = {
|
|
|
405
406
|
readonly name: string;
|
|
406
407
|
readonly value: string;
|
|
407
408
|
readonly onChange: (v: string) => void;
|
|
408
|
-
/**
|
|
409
|
-
* required
|
|
410
|
-
*
|
|
411
|
-
* {value,label}
|
|
409
|
+
/** Allowed values. An empty array produces a dropdown with no options, so a
|
|
410
|
+
* required field cannot be satisfied (an author warning, not an end-user
|
|
411
|
+
* message). The string form is for static lists (value == label); the
|
|
412
|
+
* {value,label} form is for database-backed references. */
|
|
412
413
|
readonly options: readonly string[] | readonly {
|
|
413
414
|
readonly value: string;
|
|
414
415
|
readonly label: string;
|
|
@@ -450,14 +451,14 @@ export type InputProps = {
|
|
|
450
451
|
readonly placeholder?: string;
|
|
451
452
|
readonly searchPlaceholder?: string;
|
|
452
453
|
readonly emptyText?: string;
|
|
453
|
-
/**
|
|
454
|
-
*
|
|
455
|
-
* debounced
|
|
454
|
+
/** Remote search: when set, the combobox uses remote mode (local cmdk
|
|
455
|
+
* filtering is disabled and the search input calls the caller's
|
|
456
|
+
* debounced onSearchChange). */
|
|
456
457
|
readonly onSearchChange?: (q: string) => void;
|
|
457
458
|
readonly loading?: boolean;
|
|
458
459
|
/** Fixed "+ createLabel" footer row that fires instead of
|
|
459
460
|
* selecting an option — omit for the plain select-existing
|
|
460
|
-
* combobox
|
|
461
|
+
* combobox. */
|
|
461
462
|
readonly onCreate?: () => void;
|
|
462
463
|
readonly createLabel?: string;
|
|
463
464
|
} & ({
|
|
@@ -472,18 +473,18 @@ export type InputProps = {
|
|
|
472
473
|
readonly kind: "money";
|
|
473
474
|
readonly id: string;
|
|
474
475
|
readonly name: string;
|
|
475
|
-
/** Internal
|
|
476
|
-
* 12,99 EUR).
|
|
477
|
-
*
|
|
476
|
+
/** Internal format: cents/minor units as an integer (for example, 1299 for
|
|
477
|
+
* 12,99 EUR). The renderer converts this to major units for the UI with
|
|
478
|
+
* locale-formatted decimal places. Empty state = `""`. */
|
|
478
479
|
readonly value: number | "";
|
|
479
480
|
readonly onChange: (v: number | undefined) => void;
|
|
480
|
-
/** ISO-4217
|
|
481
|
-
* "EUR".
|
|
482
|
-
*
|
|
481
|
+
/** ISO-4217 currency code, for example "EUR" / "USD" / "CHF". Default
|
|
482
|
+
* "EUR". The renderer displays the symbol as a suffix and formats the
|
|
483
|
+
* decimal places accordingly (EUR/USD/CHF use 2; JPY uses 0). */
|
|
483
484
|
readonly currency?: string;
|
|
484
|
-
/** Locale
|
|
485
|
-
*
|
|
486
|
-
* current locale
|
|
485
|
+
/** Locale for number formatting. Default "de-DE" (comma as the decimal
|
|
486
|
+
* separator). Apps with their own LocaleResolver can pass through their
|
|
487
|
+
* current locale. */
|
|
487
488
|
readonly locale?: string;
|
|
488
489
|
readonly disabled?: boolean;
|
|
489
490
|
readonly required?: boolean;
|
|
@@ -492,22 +493,22 @@ export type InputProps = {
|
|
|
492
493
|
readonly kind: "timestamp";
|
|
493
494
|
readonly id: string;
|
|
494
495
|
readonly name: string;
|
|
495
|
-
/** ISO-8601
|
|
496
|
-
* ("2026-04-25T13:45:00Z")
|
|
497
|
-
* ("2026-04-25T13:45",
|
|
498
|
-
* Web
|
|
499
|
-
*
|
|
496
|
+
/** ISO-8601 datetime string. A UTC instant uses `Z`
|
|
497
|
+
* ("2026-04-25T13:45:00Z"); a wall-clock value has no offset
|
|
498
|
+
* ("2026-04-25T13:45", only with wallClock). Empty state = `""`.
|
|
499
|
+
* Web renders separate date (typable + calendar) and time inputs and
|
|
500
|
+
* converts the result. */
|
|
500
501
|
readonly value: string;
|
|
501
502
|
readonly onChange: (v: string | undefined) => void;
|
|
502
|
-
/** true = locatedTimestamp (
|
|
503
|
-
*
|
|
504
|
-
*
|
|
503
|
+
/** true = locatedTimestamp (wall-clock without an offset; the server
|
|
504
|
+
* validates z.iso.datetime({local:true})). false/undefined = a UTC
|
|
505
|
+
* instant; onChange MUST emit a `Z` suffix. */
|
|
505
506
|
readonly wallClock?: boolean;
|
|
506
|
-
/** Locale
|
|
507
|
-
*
|
|
507
|
+
/** Locale for displaying and parsing the date portion. Default = browser
|
|
508
|
+
* locale. */
|
|
508
509
|
readonly locale?: string;
|
|
509
|
-
/**
|
|
510
|
-
*
|
|
510
|
+
/** Date bounds as ISO datetimes; they constrain the calendar to day-level
|
|
511
|
+
* granularity. */
|
|
511
512
|
readonly min?: string;
|
|
512
513
|
readonly max?: string;
|
|
513
514
|
readonly disabled?: boolean;
|
|
@@ -517,9 +518,9 @@ export type InputProps = {
|
|
|
517
518
|
readonly kind: "locatedTimestamp";
|
|
518
519
|
readonly id: string;
|
|
519
520
|
readonly name: string;
|
|
520
|
-
/** Located-
|
|
521
|
-
* `utc`
|
|
522
|
-
*
|
|
521
|
+
/** Located-timestamp value: wall-clock `at` (without an offset) plus an IANA
|
|
522
|
+
* `tz`. `utc` is present when reading (computed by the server) and ignored
|
|
523
|
+
* when writing. Empty state = `""`. onChange emits `{ at, tz }`. */
|
|
523
524
|
readonly value: {
|
|
524
525
|
readonly at: string;
|
|
525
526
|
readonly tz: string;
|
|
@@ -529,9 +530,9 @@ export type InputProps = {
|
|
|
529
530
|
readonly at: string;
|
|
530
531
|
readonly tz: string;
|
|
531
532
|
} | undefined) => void;
|
|
532
|
-
/** Locale
|
|
533
|
+
/** Locale for the date portion. Default = browser locale. */
|
|
533
534
|
readonly locale?: string;
|
|
534
|
-
/**
|
|
535
|
+
/** Date bounds as ISO datetimes; they constrain the calendar. */
|
|
535
536
|
readonly min?: string;
|
|
536
537
|
readonly max?: string;
|
|
537
538
|
readonly disabled?: boolean;
|
|
@@ -555,15 +556,15 @@ export type InputProps = {
|
|
|
555
556
|
readonly onChange: (v: string) => void;
|
|
556
557
|
/** Visible rows. Acts as a minimum height — the field starts this tall
|
|
557
558
|
* and still grows with its content. Omitted, the default primitive
|
|
558
|
-
* falls back to its own floor
|
|
559
|
+
* falls back to its own floor. */
|
|
559
560
|
readonly rows?: number;
|
|
560
561
|
readonly disabled?: boolean;
|
|
561
562
|
readonly required?: boolean;
|
|
562
563
|
readonly hasError?: boolean;
|
|
563
564
|
/** Hint text shown when the field is empty (analog to kind:"text"). */
|
|
564
565
|
readonly placeholder?: string;
|
|
565
|
-
/** Read-only Textarea.
|
|
566
|
-
*
|
|
566
|
+
/** Read-only Textarea. Not `disabled` — remains focusable and
|
|
567
|
+
* copyable (analogous to kind:"text"). */
|
|
567
568
|
readonly readOnly?: boolean;
|
|
568
569
|
/** Ctrl/Cmd+Enter submits instead of inserting a newline. Plain
|
|
569
570
|
* Enter still inserts a newline. */
|
|
@@ -582,7 +583,7 @@ export type DataTableSort = {
|
|
|
582
583
|
};
|
|
583
584
|
export type DataTableRowActionMode = "adaptive" | "inline";
|
|
584
585
|
export type DataTableRowAction = {
|
|
585
|
-
/** Stable
|
|
586
|
+
/** Stable ID for aria-labels and data-testids. */
|
|
586
587
|
readonly id: string;
|
|
587
588
|
/** Translated Label. */
|
|
588
589
|
readonly label: string;
|
|
@@ -590,22 +591,22 @@ export type DataTableRowAction = {
|
|
|
590
591
|
* primitive. Whether it also forces a confirm dialog is governed by
|
|
591
592
|
* `confirmRequired` (falls back to `style === "danger"` when unset). */
|
|
592
593
|
readonly style?: "primary" | "secondary" | "danger";
|
|
593
|
-
/** Translated
|
|
594
|
-
*
|
|
595
|
-
*
|
|
594
|
+
/** Translated confirmation prompt (dialog description). When set, a modal
|
|
595
|
+
* opens before execution. For style=danger without an explicit confirm,
|
|
596
|
+
* the renderer should show a generic default. */
|
|
596
597
|
readonly confirm?: string;
|
|
597
|
-
/** Translated
|
|
598
|
-
* (
|
|
598
|
+
/** Translated confirm-button label in the dialog. Defaults to `label`
|
|
599
|
+
* (the action label is reused). */
|
|
599
600
|
readonly confirmLabel?: string;
|
|
600
601
|
/** Overrides the default "danger implies a confirm dialog" rule. Schema-driven
|
|
601
602
|
* navigate/drawer actions set it to false: the colour marks the action as
|
|
602
603
|
* destructive, but the target form is the confirmation. */
|
|
603
604
|
readonly confirmRequired?: boolean;
|
|
604
|
-
/**
|
|
605
|
-
*
|
|
606
|
-
* Loading-State auf dem Button zeigen. */
|
|
605
|
+
/** Called with the clicked row's `ListRowViewModel`. May be async, allowing
|
|
606
|
+
* the renderer to show a loading state on the button while the promise resolves. */
|
|
607
607
|
readonly onTrigger: (row: ListRowViewModel) => Promise<void> | void;
|
|
608
|
-
/**
|
|
608
|
+
/** Controls per-row visibility (e.g. show "Start" only when
|
|
609
|
+
* `status==="scheduled"`). */
|
|
609
610
|
readonly isVisible?: (row: ListRowViewModel) => boolean;
|
|
610
611
|
/** This action is what a click on the row does. With `onRowClick` the table
|
|
611
612
|
* (except `"inline"` mode or editable cells) and the card layout drop it
|
|
@@ -632,8 +633,8 @@ export type DataTableFacet = {
|
|
|
632
633
|
readonly field: string;
|
|
633
634
|
/** Translated Button-Label ("Status", "Active"). */
|
|
634
635
|
readonly label: string;
|
|
635
|
-
/**
|
|
636
|
-
* (select
|
|
636
|
+
/** Selectable values with display labels. `value` is the raw filter value
|
|
637
|
+
* (a select option or `"true"`/`"false"`), transported as a string. */
|
|
637
638
|
readonly options: readonly {
|
|
638
639
|
readonly value: string;
|
|
639
640
|
readonly label: string;
|
|
@@ -679,20 +680,20 @@ export type DataTableProps = {
|
|
|
679
680
|
/** Tints a row. Renderers without row tinting ignore it. */
|
|
680
681
|
readonly rowTone?: (row: ListRowViewModel) => SelectOptionTone | undefined;
|
|
681
682
|
readonly onRowClick?: (row: ListRowViewModel) => void;
|
|
682
|
-
/**
|
|
683
|
-
* `sortable: true
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
683
|
+
/** Current sorting, or null when unsorted. If columns contain a
|
|
684
|
+
* `sortable: true` field and `onSortChange` is set, the renderer makes
|
|
685
|
+
* headers clickable and shows ascending/descending indicators. Without
|
|
686
|
+
* `onSortChange`, header clicks remain disabled and `columns.sortable` is
|
|
687
|
+
* only semantic metadata. */
|
|
687
688
|
readonly sort?: DataTableSort | null;
|
|
688
|
-
/**
|
|
689
|
-
*
|
|
690
|
-
*
|
|
689
|
+
/** Called with the next sort state after a header click.
|
|
690
|
+
* The conventional three-state cycle is asc → desc → null. The caller
|
|
691
|
+
* uses it to update URL state or a query parameter and refetch. */
|
|
691
692
|
readonly onSortChange?: (next: DataTableSort | null) => void;
|
|
692
|
-
/**
|
|
693
|
-
* (≤2
|
|
694
|
-
*
|
|
695
|
-
*
|
|
693
|
+
/** Per-row actions rendered in a right-hand column as inline buttons
|
|
694
|
+
* (≤2 actions) or a kebab dropdown (>2). The caller supplies the resolved
|
|
695
|
+
* form, with translated labels and wired `onTrigger`; DataTable handles
|
|
696
|
+
* only rendering and the confirmation dialog. */
|
|
696
697
|
readonly rowActions?: readonly DataTableRowAction[];
|
|
697
698
|
/** How the row-action column renders:
|
|
698
699
|
* - `"adaptive"` (default): with `onRowClick` all actions except the
|
|
@@ -703,45 +704,46 @@ export type DataTableProps = {
|
|
|
703
704
|
* kebab). Actions then sit at the same x-position across all rows
|
|
704
705
|
* (no drifting with label width) and all lists in an app look alike. */
|
|
705
706
|
readonly rowActionMode?: DataTableRowActionMode;
|
|
706
|
-
/** Custom
|
|
707
|
-
*
|
|
707
|
+
/** Custom empty-state content (e.g. Icon + Heading + CTA-Button).
|
|
708
|
+
* The default renderer wraps it in a dashed-border box. */
|
|
708
709
|
readonly emptyState?: ReactNode;
|
|
709
|
-
/**
|
|
710
|
-
* ("Items", "Bestellungen").
|
|
710
|
+
/** Optional title slot at the left of the toolbar, typically the screen
|
|
711
|
+
* title ("Items", "Bestellungen"). The web renderer uses a medium-weight heading. */
|
|
711
712
|
readonly toolbarTitle?: ReactNode;
|
|
712
|
-
/** Toolbar
|
|
713
|
-
*
|
|
714
|
-
*
|
|
713
|
+
/** Toolbar slot in the middle, typically a search input. The renderer
|
|
714
|
+
* controls the layout; the web implementation gives it `flex-1` with a
|
|
715
|
+
* maximum width, while native implementations may use a header search bar. */
|
|
715
716
|
readonly toolbarStart?: ReactNode;
|
|
716
|
-
/** Toolbar
|
|
717
|
-
*
|
|
717
|
+
/** Toolbar slot on the right, typically for a + New button, filters, or a
|
|
718
|
+
* view switch. The web implementation moves the cluster to the right edge
|
|
719
|
+
* with `ml-auto`. */
|
|
718
720
|
readonly toolbarEnd?: ReactNode;
|
|
719
|
-
/** Faceted
|
|
720
|
-
*
|
|
721
|
+
/** Faceted filter dropdowns for select/boolean fields. The renderer places
|
|
722
|
+
* them beside the search input; an empty or undefined value renders no filters. */
|
|
721
723
|
readonly filterFacets?: readonly DataTableFacet[];
|
|
722
|
-
/**
|
|
724
|
+
/** Currently selected values for each facet field, supplied by URL state. */
|
|
723
725
|
readonly filterValues?: Readonly<Record<string, readonly string[]>>;
|
|
724
|
-
/**
|
|
726
|
+
/** Toggling a facet value: the caller updates URL state and refetches. */
|
|
725
727
|
readonly onFilterChange?: (field: string, values: readonly string[]) => void;
|
|
726
|
-
/**
|
|
727
|
-
*
|
|
728
|
+
/** Clears all active facets. The renderer shows the reset button only when
|
|
729
|
+
* at least one facet is active. */
|
|
728
730
|
readonly onFilterReset?: () => void;
|
|
729
|
-
/** Time-range filters beside the facet dropdowns
|
|
731
|
+
/** Time-range filters beside the facet dropdowns. */
|
|
730
732
|
readonly dateRangeFacets?: readonly DataTableDateRangeFacet[];
|
|
731
733
|
/** One bound changed ("" clears it) → caller writes URL state + refetch. */
|
|
732
734
|
readonly onDateRangeChange?: (field: string, bound: "from" | "to", value: string) => void;
|
|
733
|
-
/** Pagination
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
735
|
+
/** Pagination state and callback. When set, the renderer shows a pager below
|
|
736
|
+
* the table (web: a footer bar with ← 1 ... N →). `total`, `limit`, and
|
|
737
|
+
* `page` are one-based for the UI; the caller translates them to
|
|
738
|
+
* `offset = (page-1)*limit` for the server. The caller should clamp a page
|
|
739
|
+
* greater than `total/limit` beforehand. */
|
|
738
740
|
readonly pager?: {
|
|
739
741
|
readonly page: number;
|
|
740
742
|
readonly limit: number;
|
|
741
743
|
readonly total: number;
|
|
742
744
|
readonly onPageChange: (next: number) => void;
|
|
743
745
|
/** Offered page sizes; with `onPageSizeChange` the footer shows a
|
|
744
|
-
* "N
|
|
746
|
+
* "N per page" select. */
|
|
745
747
|
readonly pageSizeOptions?: readonly number[];
|
|
746
748
|
readonly onPageSizeChange?: (next: number) => void;
|
|
747
749
|
};
|
|
@@ -750,16 +752,16 @@ export type DataTableProps = {
|
|
|
750
752
|
/** Noun for the footer count ("1–19 of 19 leases", "1 position"),
|
|
751
753
|
* resolved for the given count. Omitted = generic "entries" wording. */
|
|
752
754
|
readonly itemNoun?: (count: number) => string;
|
|
753
|
-
/** Infinite-
|
|
754
|
-
*
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
755
|
+
/** Infinite-scroll callback. When set, the renderer adds a bottom sentinel
|
|
756
|
+
* and calls `onReachEnd` when it enters the viewport (web:
|
|
757
|
+
* `IntersectionObserver`). The caller manages accumulation, the cursor, and
|
|
758
|
+
* `hasMore`. `loadingMore=true` shows a spinner below the table while the
|
|
759
|
+
* next page loads. Incompatible with `pager`: use either pagination or
|
|
760
|
+
* infinite scrolling, not both. */
|
|
759
761
|
readonly onReachEnd?: () => void;
|
|
760
762
|
readonly loadingMore?: boolean;
|
|
761
|
-
/**
|
|
762
|
-
*
|
|
763
|
+
/** When false and `onReachEnd` is set, the renderer shows an end-of-list
|
|
764
|
+
* message instead of the sentinel. Defaults to true. */
|
|
763
765
|
readonly hasMore?: boolean;
|
|
764
766
|
readonly testId?: string;
|
|
765
767
|
/** Wires an edit path into a component column-renderer: `DataTableCell`
|
|
@@ -775,14 +777,14 @@ export type DataTableProps = {
|
|
|
775
777
|
/** Overrides the cell `data-testid` (default `cell-${row.id}-${field}`). */
|
|
776
778
|
readonly getCellTestId?: (row: ListRowViewModel, field: string) => string;
|
|
777
779
|
/** Drops the table's own rounded/border/card background — for a host
|
|
778
|
-
* that already provides the surrounding boundary (a tab panel
|
|
780
|
+
* that already provides the surrounding boundary (a tab panel)
|
|
779
781
|
* and would otherwise show a card nested inside that boundary. Default
|
|
780
782
|
* false: unchanged card-framed table. */
|
|
781
783
|
readonly chromeless?: boolean;
|
|
782
784
|
/** Fills the available height of its flex container and scrolls rows
|
|
783
785
|
* internally instead of growing with row count — for a host that would
|
|
784
786
|
* otherwise have a long table stretch the whole page, or a short table
|
|
785
|
-
* leave dead space below it (a tab panel
|
|
787
|
+
* leave dead space below it (a tab panel). Requires the same
|
|
786
788
|
* flex-fill chain FormProps.fillHeight sets up above it; without that
|
|
787
789
|
* ancestor chain this collapses to zero height (Web: `flex-1 min-h-0`
|
|
788
790
|
* has no effect outside a sized flex-col ancestor). When true the table
|
|
@@ -795,7 +797,7 @@ export type DataTableProps = {
|
|
|
795
797
|
/** Uses the shared screen padding (wider bottom inset) instead of the
|
|
796
798
|
* table's symmetric embedded inset — for a table that IS the screen body
|
|
797
799
|
* (entityList/projectionList), so a list screen ends at the same footer
|
|
798
|
-
* distance as a form or custom screen
|
|
800
|
+
* distance as a form or custom screen. Ignored when
|
|
799
801
|
* `scrollBody` is true: the wider bottom inset would compete with
|
|
800
802
|
* `scrollBody`'s flex-fill height budget.
|
|
801
803
|
* Default false: unchanged symmetric inset for an embedded table. */
|
|
@@ -921,8 +923,9 @@ export type FormProps = {
|
|
|
921
923
|
readonly focusFirstErrorKey?: number;
|
|
922
924
|
readonly children: ReactNode;
|
|
923
925
|
readonly title?: ReactNode;
|
|
924
|
-
/**
|
|
925
|
-
* your catalog")
|
|
926
|
+
/** Optional muted subtitle below the title (e.g. "Add a new item to
|
|
927
|
+
* your catalog"), providing context in the form header rather than only
|
|
928
|
+
* a label. */
|
|
926
929
|
readonly subtitle?: ReactNode;
|
|
927
930
|
readonly actions?: ReactNode;
|
|
928
931
|
/** Secondary, record-related actions — rendered on the left on desktop,
|
|
@@ -934,7 +937,7 @@ export type FormProps = {
|
|
|
934
937
|
readonly width?: FormWidth;
|
|
935
938
|
/** Pins `actions` to the viewport bottom on narrow screens (`<640px`)
|
|
936
939
|
* instead of normal document flow, so it stays reachable when a virtual
|
|
937
|
-
* keyboard shrinks the visible viewport
|
|
940
|
+
* keyboard shrinks the visible viewport. Desktop/tablet
|
|
938
941
|
* unaffected. */
|
|
939
942
|
readonly stickyActions?: boolean;
|
|
940
943
|
/** Extra content rendered above the card, inside the same page padding
|
|
@@ -948,7 +951,7 @@ export type FormProps = {
|
|
|
948
951
|
/** Sizes the form to fill its container's height (instead of the page's
|
|
949
952
|
* natural content height) so a single scrolling child — a lone
|
|
950
953
|
* relatedList tab's table — can scroll internally instead of stretching
|
|
951
|
-
* the whole page
|
|
954
|
+
* the whole page. Set by RenderEdit for a lone relatedList tab
|
|
952
955
|
* section and for screens that fill the shell height (together with
|
|
953
956
|
* `stickyActions`: sections scroll, footer stays pinned without
|
|
954
957
|
* `position: fixed`); every other caller leaves it unset and keeps normal
|
|
@@ -982,18 +985,18 @@ export type FormProps = {
|
|
|
982
985
|
* navigation). */
|
|
983
986
|
readonly sideRail?: ReactNode;
|
|
984
987
|
};
|
|
985
|
-
/** Titled
|
|
986
|
-
* View
|
|
987
|
-
*
|
|
988
|
+
/** Titled group of fields. Web: `<fieldset>` + `<legend>`; native
|
|
989
|
+
* implementations use a `View` with header text and may render the title as
|
|
990
|
+
* an accordion or collapsible section. */
|
|
988
991
|
export type SectionProps = {
|
|
989
992
|
/** DOM id — the scroll target of a form's "on this page" navigation. */
|
|
990
993
|
readonly id?: string;
|
|
991
|
-
/** Optional
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
+
/** Optional; without a title, the Section renders only the grouping and no
|
|
995
|
+
* header. RenderEdit omits it when it would exactly repeat the screen title
|
|
996
|
+
* in the action bar. */
|
|
994
997
|
readonly title?: string;
|
|
995
|
-
/**
|
|
996
|
-
*
|
|
998
|
+
/** Optional muted subtitle below the title, providing section context rather
|
|
999
|
+
* than only a label (analogous to `FormProps.subtitle`). */
|
|
997
1000
|
readonly subtitle?: ReactNode;
|
|
998
1001
|
readonly children: ReactNode;
|
|
999
1002
|
/** Rendered top-right in the title row — never a footer. A
|
|
@@ -1016,7 +1019,7 @@ export type SectionProps = {
|
|
|
1016
1019
|
/** Chromeless flex-fill layout host — no title, no card frame, no padding,
|
|
1017
1020
|
* just a container that sizes to its content and, once the ancestor chain
|
|
1018
1021
|
* is height-constrained, shrinks so one scrolling child can scroll
|
|
1019
|
-
* internally instead of the page growing
|
|
1022
|
+
* internally instead of the page growing. Web:
|
|
1020
1023
|
* `<div className="flex min-h-0 flex-col">`. Native: Views are
|
|
1021
1024
|
* already flex-column and the parent is already a bounded viewport there,
|
|
1022
1025
|
* so a native impl may render this as a bare Fragment. Used only as the
|
|
@@ -1033,15 +1036,15 @@ export type FillContainerProps = {
|
|
|
1033
1036
|
* height. */
|
|
1034
1037
|
readonly grow?: boolean;
|
|
1035
1038
|
};
|
|
1036
|
-
/**
|
|
1037
|
-
*
|
|
1038
|
-
* `GridCell
|
|
1039
|
+
/** Column-based layout. Web uses CSS grid; native implementations use
|
|
1040
|
+
* flex-wrap with percentages or react-native-grid. Direct children can be
|
|
1041
|
+
* wrapped in `GridCell` to control their span.
|
|
1039
1042
|
*
|
|
1040
|
-
* `columns: "auto"`
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1043
|
+
* `columns: "auto"` disables the N-column stretch layout: children retain
|
|
1044
|
+
* their content width and wrap onto new lines (for example, self-sized
|
|
1045
|
+
* metric tiles or an inline label-and-badge row) instead of stretching into
|
|
1046
|
+
* equal-width tracks. `GridCell` span wrapping is meaningless in this mode
|
|
1047
|
+
* and should be skipped. */
|
|
1045
1048
|
export type GridProps = {
|
|
1046
1049
|
readonly columns: number | "auto";
|
|
1047
1050
|
readonly children: ReactNode;
|
|
@@ -1063,19 +1066,19 @@ export type GridProps = {
|
|
|
1063
1066
|
};
|
|
1064
1067
|
/** Width class of a field cell inside a `flow` grid: sized by what the field holds. */
|
|
1065
1068
|
export type FieldCellWidth = "text" | "number" | "money" | "date" | "timestamp" | "select" | "full" | "toggle";
|
|
1066
|
-
/** Span
|
|
1067
|
-
*
|
|
1069
|
+
/** Span wrapper for a child within a grid. Web: `style={{gridColumn: span N}}`;
|
|
1070
|
+
* native implementations calculate the width themselves. */
|
|
1068
1071
|
export type GridCellProps = {
|
|
1069
1072
|
readonly span?: number;
|
|
1070
1073
|
/** Only read inside a `flow` grid. */
|
|
1071
1074
|
readonly width?: FieldCellWidth;
|
|
1072
1075
|
readonly children: ReactNode;
|
|
1073
1076
|
};
|
|
1074
|
-
/**
|
|
1075
|
-
*
|
|
1076
|
-
*
|
|
1077
|
-
*
|
|
1078
|
-
*
|
|
1077
|
+
/** Semantic text. Variants map to standard typography roles: `body` is
|
|
1078
|
+
* the default, `small` for secondary labels, `code` for inline monospace
|
|
1079
|
+
* (entityId, screen-id), `required-mark` for the asterisk after labels,
|
|
1080
|
+
* `muted` for dimmed body text (text-sm muted-foreground). Custom impls map
|
|
1081
|
+
* these to their own type scale. */
|
|
1079
1082
|
export type TextProps = {
|
|
1080
1083
|
readonly variant?: "body" | "small" | "code" | "required-mark" | "muted";
|
|
1081
1084
|
/** Pure ornament (e.g. a separator glyph): hidden from assistive tech. */
|
|
@@ -1083,30 +1086,31 @@ export type TextProps = {
|
|
|
1083
1086
|
readonly children: ReactNode;
|
|
1084
1087
|
readonly testId?: string;
|
|
1085
1088
|
};
|
|
1086
|
-
/** Heading
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1089
|
+
/** Heading with two roles: `page` is a page title (web: h1), while `section`
|
|
1090
|
+
* is a group subheading (web: h2 with uppercase and muted styling). Native
|
|
1091
|
+
* implementations map these to `<Text>` with the corresponding font weight
|
|
1092
|
+
* and size. */
|
|
1089
1093
|
export type HeadingProps = {
|
|
1090
1094
|
readonly variant?: "page" | "section";
|
|
1091
1095
|
readonly children: ReactNode;
|
|
1092
1096
|
readonly testId?: string;
|
|
1093
1097
|
};
|
|
1094
|
-
/** Modal
|
|
1095
|
-
* Radix
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
1098
|
+
/** Modal dialog for confirmations or compact sub-forms. The web renderer
|
|
1099
|
+
* uses Radix Dialog with focus trapping, Escape-to-close, and overlay-click
|
|
1100
|
+
* handling; native implementations may use a native modal. Apps control it
|
|
1101
|
+
* through external state (`open` + `onOpenChange`); confirmation runs through
|
|
1102
|
+
* `onConfirm`, while cancellation closes it via `onOpenChange(false)`.
|
|
1099
1103
|
*
|
|
1100
|
-
* Variant `danger`
|
|
1101
|
-
*
|
|
1104
|
+
* Variant `danger` visually marks destructive confirmations with a red
|
|
1105
|
+
* confirm-button class; `default` is for neutral dialogs. */
|
|
1102
1106
|
export type DialogProps = {
|
|
1103
1107
|
readonly open: boolean;
|
|
1104
1108
|
readonly onOpenChange: (open: boolean) => void;
|
|
1105
1109
|
readonly title: string;
|
|
1106
|
-
/** Optional
|
|
1107
|
-
*
|
|
1110
|
+
/** Optional description, typically a sentence explaining the consequence
|
|
1111
|
+
* ("This action cannot be undone."). */
|
|
1108
1112
|
readonly description?: string;
|
|
1109
|
-
/** Confirm-
|
|
1113
|
+
/** Confirm-button label. Defaults to the i18n value
|
|
1110
1114
|
* (`kumiko.dialog.confirm`). */
|
|
1111
1115
|
readonly confirmLabel?: string;
|
|
1112
1116
|
/** Cancel-Button-Label. Default `kumiko.dialog.cancel`. */
|
|
@@ -1118,12 +1122,11 @@ export type DialogProps = {
|
|
|
1118
1122
|
* `children` are present. `"cancel"` for
|
|
1119
1123
|
* dialogs where the safe choice must be the one Enter triggers. */
|
|
1120
1124
|
readonly initialFocus?: "confirm" | "cancel";
|
|
1121
|
-
/**
|
|
1122
|
-
*
|
|
1123
|
-
* onOpenChange(false). */
|
|
1125
|
+
/** Called when the user confirms. Async functions are supported; the dialog
|
|
1126
|
+
* automatically sets a loading state and then calls `onOpenChange(false)`. */
|
|
1124
1127
|
readonly onConfirm: () => void | Promise<void>;
|
|
1125
|
-
/** Optional
|
|
1126
|
-
*
|
|
1128
|
+
/** Optional additional content between the description and buttons, such as
|
|
1129
|
+
* an input when the dialog also collects data. */
|
|
1127
1130
|
readonly children?: ReactNode;
|
|
1128
1131
|
readonly testId?: string;
|
|
1129
1132
|
};
|
|
@@ -1144,7 +1147,7 @@ export type ModalProps = {
|
|
|
1144
1147
|
/** Side panel for hosting an existing self-contained form/widget (own
|
|
1145
1148
|
* submit/cancel buttons) without leaving the underlying screen — e.g. a
|
|
1146
1149
|
* toolbar action's `kind: "drawer"` mounts an actionForm here instead of
|
|
1147
|
-
* navigating to a full page
|
|
1150
|
+
* navigating to a full page. Same "bare content shell, no
|
|
1148
1151
|
* footer buttons of its own" contract as `Modal`, slide-in instead of
|
|
1149
1152
|
* centered overlay. */
|
|
1150
1153
|
export type DrawerProps = {
|
|
@@ -1209,10 +1212,10 @@ export type ConfigCascadeViewProps = {
|
|
|
1209
1212
|
* value). Absent = the raw value; a missing value keeps the no-value text. */
|
|
1210
1213
|
readonly renderValue?: (value: string | number | boolean) => ReactNode;
|
|
1211
1214
|
};
|
|
1212
|
-
/** Card
|
|
1213
|
-
*
|
|
1214
|
-
*
|
|
1215
|
-
*
|
|
1215
|
+
/** Card slots are named content regions, all optional. Adding slots is
|
|
1216
|
+
* additive, so consumers do not need migration. `header` is an escape hatch:
|
|
1217
|
+
* a raw node replaces the default header (`title`/`subtitle`/`headerActions`)
|
|
1218
|
+
* when the convenience slots are insufficient. */
|
|
1216
1219
|
export type CardSlots = {
|
|
1217
1220
|
readonly header?: ReactNode;
|
|
1218
1221
|
readonly title?: ReactNode;
|
|
@@ -1221,9 +1224,9 @@ export type CardSlots = {
|
|
|
1221
1224
|
* title/subtitle/`headerActions` row, within the same header block — for a
|
|
1222
1225
|
* host-supplied header (projectionDetail `slots.header`). */
|
|
1223
1226
|
readonly headerContent?: ReactNode;
|
|
1224
|
-
/**
|
|
1227
|
+
/** Right-aligned header slot, for example a range switcher, filter, or badge. */
|
|
1225
1228
|
readonly headerActions?: ReactNode;
|
|
1226
|
-
/** Footer
|
|
1229
|
+
/** Footer content, separated by a top border; aligned to the right by default. */
|
|
1227
1230
|
readonly footer?: ReactNode;
|
|
1228
1231
|
};
|
|
1229
1232
|
/** Card-Options — Verhalten/Optik, ebenfalls additiv erweiterbar. */
|
|
@@ -1232,12 +1235,12 @@ export type CardOptions = {
|
|
|
1232
1235
|
readonly padded?: boolean;
|
|
1233
1236
|
/** Eckenradius. Default "xl" (= Entity-Card). */
|
|
1234
1237
|
readonly radius?: "lg" | "xl";
|
|
1235
|
-
/**
|
|
1238
|
+
/** Separates the footer with `border-t` and `bg-muted/30`. Defaults to true. */
|
|
1236
1239
|
readonly footerBordered?: boolean;
|
|
1237
1240
|
/** Footer horizontal padding. false = none, so footer content aligns with the card edge. Default true. */
|
|
1238
1241
|
readonly footerInset?: boolean;
|
|
1239
|
-
/** Joins the ancestor fillHeight flex chain
|
|
1240
|
-
* relatedList table sizing to the panel instead of the page
|
|
1242
|
+
/** Joins the ancestor fillHeight flex chain — a tabs-mode
|
|
1243
|
+
* relatedList table sizing to the panel instead of the page — instead of
|
|
1241
1244
|
* normal document-flow height. Default false. */
|
|
1242
1245
|
readonly fillHeight?: boolean;
|
|
1243
1246
|
/** false drops border, background, shadow and radius but keeps padding and
|
|
@@ -1249,13 +1252,15 @@ export type CardOptions = {
|
|
|
1249
1252
|
* shell edge. Default false. */
|
|
1250
1253
|
readonly screenBody?: boolean;
|
|
1251
1254
|
};
|
|
1252
|
-
/**
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
+
/** Generic card chrome (border/background/radius/shadow plus
|
|
1256
|
+
* header/body/footer) as a primitive, providing one implementation for all
|
|
1257
|
+
* card surfaces. It is slot- and option-based so the contract can evolve
|
|
1258
|
+
* additively. */
|
|
1255
1259
|
export type CardProps = {
|
|
1256
1260
|
readonly slots?: CardSlots;
|
|
1257
1261
|
readonly options?: CardOptions;
|
|
1258
|
-
/** Body
|
|
1262
|
+
/** Body content in the normal case; header and footer are supplied through
|
|
1263
|
+
* `slots`. */
|
|
1259
1264
|
readonly children?: ReactNode;
|
|
1260
1265
|
readonly className?: string;
|
|
1261
1266
|
readonly testId?: string;
|
|
@@ -1320,8 +1325,8 @@ export type StepBarProps = {
|
|
|
1320
1325
|
* native constraint-validation concept (web: `<fieldset disabled>`, spec-
|
|
1321
1326
|
* guaranteed to also bar descendants from participating) must bar it too,
|
|
1322
1327
|
* or a `type="submit"` step-advance button triggers the browser's
|
|
1323
|
-
* full-form check against fields on unvisited, unfocusable steps
|
|
1324
|
-
*
|
|
1328
|
+
* full-form check against fields on unvisited, unfocusable steps.
|
|
1329
|
+
* Implementations without that concept can gate
|
|
1325
1330
|
* on `hidden` alone. */
|
|
1326
1331
|
export type WizardStepGroupProps = {
|
|
1327
1332
|
readonly hidden: boolean;
|
|
@@ -1409,7 +1414,7 @@ export type PageHeaderProps = {
|
|
|
1409
1414
|
* the route names, for a locked screen's fallback. Wins over `hideBreadcrumb`. */
|
|
1410
1415
|
readonly breadcrumbScreenId?: string;
|
|
1411
1416
|
};
|
|
1412
|
-
/** One item in an `ActionOverflowMenu` (
|
|
1417
|
+
/** One item in an `ActionOverflowMenu` (header/row actions beyond the
|
|
1413
1418
|
* primary one collapse into this menu instead of a wall of buttons). */
|
|
1414
1419
|
export type ActionMenuItemSpec = {
|
|
1415
1420
|
readonly id: string;
|
|
@@ -1427,7 +1432,7 @@ export type ActionOverflowMenuProps = {
|
|
|
1427
1432
|
readonly label: string;
|
|
1428
1433
|
readonly testId?: string;
|
|
1429
1434
|
};
|
|
1430
|
-
/** One revealed value on a `secretMint` screen's confirm phase
|
|
1435
|
+
/** One revealed value on a `secretMint` screen's confirm phase. */
|
|
1431
1436
|
export type SecretRevealValue = {
|
|
1432
1437
|
readonly label: string;
|
|
1433
1438
|
readonly value: string;
|
|
@@ -1577,7 +1582,7 @@ export type CorePrimitives = {
|
|
|
1577
1582
|
/** Optional — additive rollout, see StickyActionBar. */
|
|
1578
1583
|
readonly MetricBand?: ComponentType<MetricBandProps>;
|
|
1579
1584
|
/** Optional: without an implementation, callers with >2 header/row
|
|
1580
|
-
* actions fall back to today's all-buttons-inline rendering
|
|
1585
|
+
* actions fall back to today's all-buttons-inline rendering. */
|
|
1581
1586
|
readonly ActionOverflowMenu?: ComponentType<ActionOverflowMenuProps>;
|
|
1582
1587
|
/** Optional (unlike the other Core-Primitives) so existing partial
|
|
1583
1588
|
* CorePrimitives mocks in tests keep compiling — additive rollout of
|
|
@@ -1594,8 +1599,8 @@ export type CorePrimitives = {
|
|
|
1594
1599
|
/** Optional — additive rollout, see StickyActionBar. */
|
|
1595
1600
|
readonly PromoPanel?: ComponentType<PromoPanelProps>;
|
|
1596
1601
|
};
|
|
1597
|
-
/**
|
|
1598
|
-
*
|
|
1602
|
+
/** Extension point for app-owned primitives. Developers extend this
|
|
1603
|
+
* interface through TypeScript module augmentation:
|
|
1599
1604
|
*
|
|
1600
1605
|
* declare module "@cosmicdrift/kumiko-renderer" {
|
|
1601
1606
|
* interface AppPrimitives {
|
|
@@ -1604,12 +1609,11 @@ export type CorePrimitives = {
|
|
|
1604
1609
|
* }
|
|
1605
1610
|
* }
|
|
1606
1611
|
*
|
|
1607
|
-
*
|
|
1608
|
-
* `createKumikoApp({ primitives: { Chip, Accordion } })`,
|
|
1609
|
-
* `usePrimitives().Chip`
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1612
|
-
* Components). */
|
|
1612
|
+
* After augmentation, the keys appear in `PrimitivesRegistry`,
|
|
1613
|
+
* `createKumikoApp({ primitives: { Chip, Accordion } })`, and
|
|
1614
|
+
* `usePrimitives().Chip` with TypeScript support. Kumiko's own components
|
|
1615
|
+
* use only `CorePrimitives`; app primitives are exclusively for developer
|
|
1616
|
+
* code such as custom screens, shells, and app-owned components. */
|
|
1613
1617
|
export interface AppPrimitives {
|
|
1614
1618
|
}
|
|
1615
1619
|
export type PrimitivesRegistry = CorePrimitives & AppPrimitives;
|