@cosmicdrift/kumiko-renderer 0.386.0 → 0.388.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 +12 -4
- package/dist/app/action-form-shim.d.ts +8 -8
- package/dist/app/action-form-shim.js +20 -22
- package/dist/app/action-form-support.d.ts +1 -0
- package/dist/app/action-form-support.js +1 -1
- 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 +7 -3
- 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.d.ts +11 -0
- package/dist/app/entity-edit-prefill.js +18 -13
- 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 +29 -28
- package/dist/app/extension-sections.js +10 -10
- package/dist/app/feature-schema.js +11 -11
- package/dist/app/form-schema.js +2 -2
- package/dist/app/header-actions-bar.js +2 -2
- 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/edit-mounts.d.ts +2 -2
- package/dist/components/embedded-list-field.js +5 -5
- 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 +15 -2
- package/dist/components/render-edit-action-button.d.ts +1 -3
- package/dist/components/render-edit-action-button.js +2 -2
- 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 +74 -73
- package/dist/components/render-field.d.ts +7 -7
- package/dist/components/render-field.js +62 -61
- package/dist/components/render-list.d.ts +42 -43
- package/dist/components/render-list.js +93 -84
- 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/flow-diagram/render.js +9 -1
- package/dist/headless/apex/index.d.ts +1 -2
- package/dist/headless/apex/index.js +5 -6
- package/dist/headless/form/form-controller.js +14 -6
- package/dist/headless/form/types.d.ts +1 -0
- package/dist/headless/form/zod-bridge.js +2 -2
- package/dist/headless/format/index.js +89 -64
- package/dist/headless/format/money.js +1 -1
- package/dist/headless/index.js +2 -2
- package/dist/headless/view-model/edit.js +4 -2
- package/dist/headless/view-model/list.js +184 -150
- package/dist/headless/view-model/types.d.ts +6 -3
- package/dist/hooks/live-refetch-scheduler.js +4 -0
- 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.d.ts +9 -1
- package/dist/hooks/use-reference-lookup.js +32 -19
- package/dist/hooks/use-store.js +18 -22
- package/dist/hooks/use-stream-handler.js +4 -2
- package/dist/i18n-defaults.js +6 -8
- package/dist/i18n.d.ts +10 -10
- package/dist/i18n.js +25 -25
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -4
- package/dist/live/dispatcher-live.js +2 -2
- package/dist/primitives.d.ts +244 -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 +29 -25
- package/dist/web/app/dashboard-body.js +17 -1
- package/dist/web/app/dashboard-panels.js +12 -2
- 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/index.d.ts +1 -1
- package/dist/web/index.js +1 -1
- 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/shell-header.js +2 -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/uniform-bar-controls.d.ts +1 -0
- package/dist/web/layout/uniform-bar-controls.js +4 -0
- 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/lib/file-ref-download.js +4 -1
- 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/code-input.d.ts +6 -0
- package/dist/web/primitives/code-input.js +31 -0
- 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 +6 -6
- 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 +2 -2
- package/dist/web/primitives/field.js +9 -8
- package/dist/web/primitives/file-thumbnail.d.ts +3 -0
- package/dist/web/primitives/file-thumbnail.js +5 -0
- package/dist/web/primitives/form.d.ts +1 -1
- package/dist/web/primitives/form.js +6 -6
- package/dist/web/primitives/input.js +8 -3
- package/dist/web/primitives/layout-elements.js +7 -5
- 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/page-header.js +3 -1
- package/dist/web/primitives/pager.js +1 -1
- package/dist/web/primitives/row-actions.js +6 -7
- 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/primitives/use-focus-on-mount.d.ts +2 -0
- package/dist/web/primitives/use-focus-on-mount.js +9 -0
- 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/bounded-load-cache.d.ts +1 -1
- package/dist/web/widgets/bounded-load-cache.js +10 -4
- package/dist/web/widgets/charts.d.ts +10 -10
- package/dist/web/widgets/charts.js +8 -8
- package/dist/web/widgets/choice-cards.d.ts +17 -0
- package/dist/web/widgets/choice-cards.js +12 -0
- package/dist/web/widgets/collapsible-section.d.ts +3 -3
- package/dist/web/widgets/collapsible-section.js +7 -7
- package/dist/web/widgets/detail-list.d.ts +5 -3
- package/dist/web/widgets/detail-list.js +5 -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.d.ts +1 -0
- package/dist/web/widgets/index.js +5 -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/pdf-preview.js +1 -1
- package/dist/web/widgets/plan-card.d.ts +2 -0
- package/dist/web/widgets/plan-card.js +1 -1
- 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/upload-zone.js +13 -5
- 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/src/changes.json +49 -0
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 = {
|
|
@@ -202,20 +203,21 @@ export type InputProps = {
|
|
|
202
203
|
readonly name: string;
|
|
203
204
|
readonly value: string;
|
|
204
205
|
readonly onChange: (v: string) => void;
|
|
206
|
+
readonly autoFocus?: boolean;
|
|
205
207
|
readonly disabled?: boolean;
|
|
206
208
|
readonly required?: boolean;
|
|
207
209
|
readonly hasError?: boolean;
|
|
208
|
-
/** Hint
|
|
209
|
-
*
|
|
210
|
+
/** Hint text shown when the field is empty. Used for search inputs in
|
|
211
|
+
* toolbars ("Suchen…") where no label is practical. */
|
|
210
212
|
readonly placeholder?: string;
|
|
211
|
-
/** Browser
|
|
212
|
-
* `<input autocomplete
|
|
213
|
+
/** Browser autofill / native keyboard hint. Web applies this to
|
|
214
|
+
* `<input autocomplete=...>`; native applies it to `textContentType`. */
|
|
213
215
|
readonly autoComplete?: string;
|
|
214
|
-
/** `data-testid`
|
|
215
|
-
*
|
|
216
|
+
/** Sets `data-testid` on the actual `<input>` so app tests can address the
|
|
217
|
+
* element directly (getByTestId + readOnly/disabled assertions). */
|
|
216
218
|
readonly testId?: string;
|
|
217
|
-
/** Read-only
|
|
218
|
-
*
|
|
219
|
+
/** Read-only input (for example, a generated free-tier slug). Not
|
|
220
|
+
* `disabled`, so it remains focusable and copyable. */
|
|
219
221
|
readonly readOnly?: boolean;
|
|
220
222
|
/** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer/web). */
|
|
221
223
|
readonly icon?: FieldIconKey;
|
|
@@ -227,6 +229,24 @@ export type InputProps = {
|
|
|
227
229
|
/** Raw keydown access (e.g. Enter-to-submit at the field instead of
|
|
228
230
|
* the surrounding Form). Forwarded to the element. */
|
|
229
231
|
readonly onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
|
|
232
|
+
} | {
|
|
233
|
+
/** Fixed-length numeric one-time code. `onComplete` fires once when input,
|
|
234
|
+
* paste or autofill brings the value to full length; the value holds
|
|
235
|
+
* digits only. */
|
|
236
|
+
readonly kind: "code";
|
|
237
|
+
readonly id: string;
|
|
238
|
+
readonly name: string;
|
|
239
|
+
readonly value: string;
|
|
240
|
+
readonly onChange: (v: string) => void;
|
|
241
|
+
readonly length: number;
|
|
242
|
+
readonly onComplete?: (code: string) => void;
|
|
243
|
+
readonly autoFocus?: boolean;
|
|
244
|
+
readonly disabled?: boolean;
|
|
245
|
+
readonly required?: boolean;
|
|
246
|
+
readonly hasError?: boolean;
|
|
247
|
+
readonly testId?: string;
|
|
248
|
+
/** Default "one-time-code". */
|
|
249
|
+
readonly autoComplete?: string;
|
|
230
250
|
} | {
|
|
231
251
|
readonly kind: "email";
|
|
232
252
|
readonly id: string;
|
|
@@ -237,8 +257,8 @@ export type InputProps = {
|
|
|
237
257
|
readonly required?: boolean;
|
|
238
258
|
readonly hasError?: boolean;
|
|
239
259
|
readonly placeholder?: string;
|
|
240
|
-
/** Default "email". Apps
|
|
241
|
-
*
|
|
260
|
+
/** Default "email". Apps that need "username" (a username-or-email login
|
|
261
|
+
* form) pass that value through. */
|
|
242
262
|
readonly autoComplete?: string;
|
|
243
263
|
readonly testId?: string;
|
|
244
264
|
} | {
|
|
@@ -263,9 +283,9 @@ export type InputProps = {
|
|
|
263
283
|
readonly hasError?: boolean;
|
|
264
284
|
/** Hint text shown when the field is empty (analog to kind:"text"). */
|
|
265
285
|
readonly placeholder?: string;
|
|
266
|
-
/** "current-password"
|
|
267
|
-
*
|
|
268
|
-
* Native
|
|
286
|
+
/** "current-password" for login, "new-password" for reset/signup—browser
|
|
287
|
+
* password managers use this to decide whether to save the value.
|
|
288
|
+
* Native uses textContentType="password" / "newPassword". */
|
|
269
289
|
readonly autoComplete?: "current-password" | "new-password";
|
|
270
290
|
/** Icon button inside the field's trailing edge (clear a stored value,
|
|
271
291
|
* undo a pending removal). `label` is its accessible name + tooltip. */
|
|
@@ -326,7 +346,7 @@ export type InputProps = {
|
|
|
326
346
|
readonly kind: "file" | "image";
|
|
327
347
|
readonly id: string;
|
|
328
348
|
readonly name: string;
|
|
329
|
-
/** FileRef
|
|
349
|
+
/** FileRef UUID (stored file) or null (no upload). */
|
|
330
350
|
readonly value: string | null;
|
|
331
351
|
/** Implementations must offer their own remove control that calls
|
|
332
352
|
* `onChange(null)`: FileListField relies on it to drop a file from an
|
|
@@ -338,8 +358,8 @@ export type InputProps = {
|
|
|
338
358
|
/** Erlaubte Extensions/MIME (z.B. ["jpg","png"]) → `accept`-Attribut. */
|
|
339
359
|
readonly accept?: readonly string[];
|
|
340
360
|
readonly maxSize?: string;
|
|
341
|
-
/**
|
|
342
|
-
*
|
|
361
|
+
/** For the upload POST `/api/files`: the endpoint validates maxSize/accept
|
|
362
|
+
* against the field definition for (entityType, fieldName). */
|
|
343
363
|
readonly entityType?: string;
|
|
344
364
|
/** Screen QN of the actionForm the field belongs to; sent as `actionForm` instead of
|
|
345
365
|
* `entityType`, so the upload stays pending for that form's field. */
|
|
@@ -388,9 +408,9 @@ export type InputProps = {
|
|
|
388
408
|
readonly name: string;
|
|
389
409
|
readonly value: string;
|
|
390
410
|
readonly onChange: (v: string | undefined) => void;
|
|
391
|
-
/** Locale
|
|
392
|
-
*
|
|
393
|
-
*
|
|
411
|
+
/** Locale for display and input parsing. Default = browser locale via
|
|
412
|
+
* navigator.language. Apps with their own LocaleResolver can pass through
|
|
413
|
+
* their current locale. */
|
|
394
414
|
readonly locale?: string;
|
|
395
415
|
/** Datumsgrenzen als ISO `yyyy-mm-dd` — begrenzen Picker (Jahres-
|
|
396
416
|
* Dropdown-Range + ausgegraute Tage). */
|
|
@@ -405,10 +425,10 @@ export type InputProps = {
|
|
|
405
425
|
readonly name: string;
|
|
406
426
|
readonly value: string;
|
|
407
427
|
readonly onChange: (v: string) => void;
|
|
408
|
-
/**
|
|
409
|
-
* required
|
|
410
|
-
*
|
|
411
|
-
* {value,label}
|
|
428
|
+
/** Allowed values. An empty array produces a dropdown with no options, so a
|
|
429
|
+
* required field cannot be satisfied (an author warning, not an end-user
|
|
430
|
+
* message). The string form is for static lists (value == label); the
|
|
431
|
+
* {value,label} form is for database-backed references. */
|
|
412
432
|
readonly options: readonly string[] | readonly {
|
|
413
433
|
readonly value: string;
|
|
414
434
|
readonly label: string;
|
|
@@ -450,14 +470,14 @@ export type InputProps = {
|
|
|
450
470
|
readonly placeholder?: string;
|
|
451
471
|
readonly searchPlaceholder?: string;
|
|
452
472
|
readonly emptyText?: string;
|
|
453
|
-
/**
|
|
454
|
-
*
|
|
455
|
-
* debounced
|
|
473
|
+
/** Remote search: when set, the combobox uses remote mode (local cmdk
|
|
474
|
+
* filtering is disabled and the search input calls the caller's
|
|
475
|
+
* debounced onSearchChange). */
|
|
456
476
|
readonly onSearchChange?: (q: string) => void;
|
|
457
477
|
readonly loading?: boolean;
|
|
458
478
|
/** Fixed "+ createLabel" footer row that fires instead of
|
|
459
479
|
* selecting an option — omit for the plain select-existing
|
|
460
|
-
* combobox
|
|
480
|
+
* combobox. */
|
|
461
481
|
readonly onCreate?: () => void;
|
|
462
482
|
readonly createLabel?: string;
|
|
463
483
|
} & ({
|
|
@@ -472,18 +492,18 @@ export type InputProps = {
|
|
|
472
492
|
readonly kind: "money";
|
|
473
493
|
readonly id: string;
|
|
474
494
|
readonly name: string;
|
|
475
|
-
/** Internal
|
|
476
|
-
* 12,99 EUR).
|
|
477
|
-
*
|
|
495
|
+
/** Internal format: cents/minor units as an integer (for example, 1299 for
|
|
496
|
+
* 12,99 EUR). The renderer converts this to major units for the UI with
|
|
497
|
+
* locale-formatted decimal places. Empty state = `""`. */
|
|
478
498
|
readonly value: number | "";
|
|
479
499
|
readonly onChange: (v: number | undefined) => void;
|
|
480
|
-
/** ISO-4217
|
|
481
|
-
* "EUR".
|
|
482
|
-
*
|
|
500
|
+
/** ISO-4217 currency code, for example "EUR" / "USD" / "CHF". Default
|
|
501
|
+
* "EUR". The renderer displays the symbol as a suffix and formats the
|
|
502
|
+
* decimal places accordingly (EUR/USD/CHF use 2; JPY uses 0). */
|
|
483
503
|
readonly currency?: string;
|
|
484
|
-
/** Locale
|
|
485
|
-
*
|
|
486
|
-
* current locale
|
|
504
|
+
/** Locale for number formatting. Default "de-DE" (comma as the decimal
|
|
505
|
+
* separator). Apps with their own LocaleResolver can pass through their
|
|
506
|
+
* current locale. */
|
|
487
507
|
readonly locale?: string;
|
|
488
508
|
readonly disabled?: boolean;
|
|
489
509
|
readonly required?: boolean;
|
|
@@ -492,22 +512,22 @@ export type InputProps = {
|
|
|
492
512
|
readonly kind: "timestamp";
|
|
493
513
|
readonly id: string;
|
|
494
514
|
readonly name: string;
|
|
495
|
-
/** ISO-8601
|
|
496
|
-
* ("2026-04-25T13:45:00Z")
|
|
497
|
-
* ("2026-04-25T13:45",
|
|
498
|
-
* Web
|
|
499
|
-
*
|
|
515
|
+
/** ISO-8601 datetime string. A UTC instant uses `Z`
|
|
516
|
+
* ("2026-04-25T13:45:00Z"); a wall-clock value has no offset
|
|
517
|
+
* ("2026-04-25T13:45", only with wallClock). Empty state = `""`.
|
|
518
|
+
* Web renders separate date (typable + calendar) and time inputs and
|
|
519
|
+
* converts the result. */
|
|
500
520
|
readonly value: string;
|
|
501
521
|
readonly onChange: (v: string | undefined) => void;
|
|
502
|
-
/** true = locatedTimestamp (
|
|
503
|
-
*
|
|
504
|
-
*
|
|
522
|
+
/** true = locatedTimestamp (wall-clock without an offset; the server
|
|
523
|
+
* validates z.iso.datetime({local:true})). false/undefined = a UTC
|
|
524
|
+
* instant; onChange MUST emit a `Z` suffix. */
|
|
505
525
|
readonly wallClock?: boolean;
|
|
506
|
-
/** Locale
|
|
507
|
-
*
|
|
526
|
+
/** Locale for displaying and parsing the date portion. Default = browser
|
|
527
|
+
* locale. */
|
|
508
528
|
readonly locale?: string;
|
|
509
|
-
/**
|
|
510
|
-
*
|
|
529
|
+
/** Date bounds as ISO datetimes; they constrain the calendar to day-level
|
|
530
|
+
* granularity. */
|
|
511
531
|
readonly min?: string;
|
|
512
532
|
readonly max?: string;
|
|
513
533
|
readonly disabled?: boolean;
|
|
@@ -517,9 +537,9 @@ export type InputProps = {
|
|
|
517
537
|
readonly kind: "locatedTimestamp";
|
|
518
538
|
readonly id: string;
|
|
519
539
|
readonly name: string;
|
|
520
|
-
/** Located-
|
|
521
|
-
* `utc`
|
|
522
|
-
*
|
|
540
|
+
/** Located-timestamp value: wall-clock `at` (without an offset) plus an IANA
|
|
541
|
+
* `tz`. `utc` is present when reading (computed by the server) and ignored
|
|
542
|
+
* when writing. Empty state = `""`. onChange emits `{ at, tz }`. */
|
|
523
543
|
readonly value: {
|
|
524
544
|
readonly at: string;
|
|
525
545
|
readonly tz: string;
|
|
@@ -529,9 +549,9 @@ export type InputProps = {
|
|
|
529
549
|
readonly at: string;
|
|
530
550
|
readonly tz: string;
|
|
531
551
|
} | undefined) => void;
|
|
532
|
-
/** Locale
|
|
552
|
+
/** Locale for the date portion. Default = browser locale. */
|
|
533
553
|
readonly locale?: string;
|
|
534
|
-
/**
|
|
554
|
+
/** Date bounds as ISO datetimes; they constrain the calendar. */
|
|
535
555
|
readonly min?: string;
|
|
536
556
|
readonly max?: string;
|
|
537
557
|
readonly disabled?: boolean;
|
|
@@ -555,15 +575,15 @@ export type InputProps = {
|
|
|
555
575
|
readonly onChange: (v: string) => void;
|
|
556
576
|
/** Visible rows. Acts as a minimum height — the field starts this tall
|
|
557
577
|
* and still grows with its content. Omitted, the default primitive
|
|
558
|
-
* falls back to its own floor
|
|
578
|
+
* falls back to its own floor. */
|
|
559
579
|
readonly rows?: number;
|
|
560
580
|
readonly disabled?: boolean;
|
|
561
581
|
readonly required?: boolean;
|
|
562
582
|
readonly hasError?: boolean;
|
|
563
583
|
/** Hint text shown when the field is empty (analog to kind:"text"). */
|
|
564
584
|
readonly placeholder?: string;
|
|
565
|
-
/** Read-only Textarea.
|
|
566
|
-
*
|
|
585
|
+
/** Read-only Textarea. Not `disabled` — remains focusable and
|
|
586
|
+
* copyable (analogous to kind:"text"). */
|
|
567
587
|
readonly readOnly?: boolean;
|
|
568
588
|
/** Ctrl/Cmd+Enter submits instead of inserting a newline. Plain
|
|
569
589
|
* Enter still inserts a newline. */
|
|
@@ -582,7 +602,7 @@ export type DataTableSort = {
|
|
|
582
602
|
};
|
|
583
603
|
export type DataTableRowActionMode = "adaptive" | "inline";
|
|
584
604
|
export type DataTableRowAction = {
|
|
585
|
-
/** Stable
|
|
605
|
+
/** Stable ID for aria-labels and data-testids. */
|
|
586
606
|
readonly id: string;
|
|
587
607
|
/** Translated Label. */
|
|
588
608
|
readonly label: string;
|
|
@@ -590,22 +610,22 @@ export type DataTableRowAction = {
|
|
|
590
610
|
* primitive. Whether it also forces a confirm dialog is governed by
|
|
591
611
|
* `confirmRequired` (falls back to `style === "danger"` when unset). */
|
|
592
612
|
readonly style?: "primary" | "secondary" | "danger";
|
|
593
|
-
/** Translated
|
|
594
|
-
*
|
|
595
|
-
*
|
|
613
|
+
/** Translated confirmation prompt (dialog description). When set, a modal
|
|
614
|
+
* opens before execution. For style=danger without an explicit confirm,
|
|
615
|
+
* the renderer should show a generic default. */
|
|
596
616
|
readonly confirm?: string;
|
|
597
|
-
/** Translated
|
|
598
|
-
* (
|
|
617
|
+
/** Translated confirm-button label in the dialog. Defaults to `label`
|
|
618
|
+
* (the action label is reused). */
|
|
599
619
|
readonly confirmLabel?: string;
|
|
600
620
|
/** Overrides the default "danger implies a confirm dialog" rule. Schema-driven
|
|
601
621
|
* navigate/drawer actions set it to false: the colour marks the action as
|
|
602
622
|
* destructive, but the target form is the confirmation. */
|
|
603
623
|
readonly confirmRequired?: boolean;
|
|
604
|
-
/**
|
|
605
|
-
*
|
|
606
|
-
* Loading-State auf dem Button zeigen. */
|
|
624
|
+
/** Called with the clicked row's `ListRowViewModel`. May be async, allowing
|
|
625
|
+
* the renderer to show a loading state on the button while the promise resolves. */
|
|
607
626
|
readonly onTrigger: (row: ListRowViewModel) => Promise<void> | void;
|
|
608
|
-
/**
|
|
627
|
+
/** Controls per-row visibility (e.g. show "Start" only when
|
|
628
|
+
* `status==="scheduled"`). */
|
|
609
629
|
readonly isVisible?: (row: ListRowViewModel) => boolean;
|
|
610
630
|
/** This action is what a click on the row does. With `onRowClick` the table
|
|
611
631
|
* (except `"inline"` mode or editable cells) and the card layout drop it
|
|
@@ -632,8 +652,8 @@ export type DataTableFacet = {
|
|
|
632
652
|
readonly field: string;
|
|
633
653
|
/** Translated Button-Label ("Status", "Active"). */
|
|
634
654
|
readonly label: string;
|
|
635
|
-
/**
|
|
636
|
-
* (select
|
|
655
|
+
/** Selectable values with display labels. `value` is the raw filter value
|
|
656
|
+
* (a select option or `"true"`/`"false"`), transported as a string. */
|
|
637
657
|
readonly options: readonly {
|
|
638
658
|
readonly value: string;
|
|
639
659
|
readonly label: string;
|
|
@@ -679,20 +699,20 @@ export type DataTableProps = {
|
|
|
679
699
|
/** Tints a row. Renderers without row tinting ignore it. */
|
|
680
700
|
readonly rowTone?: (row: ListRowViewModel) => SelectOptionTone | undefined;
|
|
681
701
|
readonly onRowClick?: (row: ListRowViewModel) => void;
|
|
682
|
-
/**
|
|
683
|
-
* `sortable: true
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
702
|
+
/** Current sorting, or null when unsorted. If columns contain a
|
|
703
|
+
* `sortable: true` field and `onSortChange` is set, the renderer makes
|
|
704
|
+
* headers clickable and shows ascending/descending indicators. Without
|
|
705
|
+
* `onSortChange`, header clicks remain disabled and `columns.sortable` is
|
|
706
|
+
* only semantic metadata. */
|
|
687
707
|
readonly sort?: DataTableSort | null;
|
|
688
|
-
/**
|
|
689
|
-
*
|
|
690
|
-
*
|
|
708
|
+
/** Called with the next sort state after a header click.
|
|
709
|
+
* The conventional three-state cycle is asc → desc → null. The caller
|
|
710
|
+
* uses it to update URL state or a query parameter and refetch. */
|
|
691
711
|
readonly onSortChange?: (next: DataTableSort | null) => void;
|
|
692
|
-
/**
|
|
693
|
-
* (≤2
|
|
694
|
-
*
|
|
695
|
-
*
|
|
712
|
+
/** Per-row actions rendered in a right-hand column as inline buttons
|
|
713
|
+
* (≤2 actions) or a kebab dropdown (>2). The caller supplies the resolved
|
|
714
|
+
* form, with translated labels and wired `onTrigger`; DataTable handles
|
|
715
|
+
* only rendering and the confirmation dialog. */
|
|
696
716
|
readonly rowActions?: readonly DataTableRowAction[];
|
|
697
717
|
/** How the row-action column renders:
|
|
698
718
|
* - `"adaptive"` (default): with `onRowClick` all actions except the
|
|
@@ -703,45 +723,46 @@ export type DataTableProps = {
|
|
|
703
723
|
* kebab). Actions then sit at the same x-position across all rows
|
|
704
724
|
* (no drifting with label width) and all lists in an app look alike. */
|
|
705
725
|
readonly rowActionMode?: DataTableRowActionMode;
|
|
706
|
-
/** Custom
|
|
707
|
-
*
|
|
726
|
+
/** Custom empty-state content (e.g. Icon + Heading + CTA-Button).
|
|
727
|
+
* The default renderer wraps it in a dashed-border box. */
|
|
708
728
|
readonly emptyState?: ReactNode;
|
|
709
|
-
/**
|
|
710
|
-
* ("Items", "Bestellungen").
|
|
729
|
+
/** Optional title slot at the left of the toolbar, typically the screen
|
|
730
|
+
* title ("Items", "Bestellungen"). The web renderer uses a medium-weight heading. */
|
|
711
731
|
readonly toolbarTitle?: ReactNode;
|
|
712
|
-
/** Toolbar
|
|
713
|
-
*
|
|
714
|
-
*
|
|
732
|
+
/** Toolbar slot in the middle, typically a search input. The renderer
|
|
733
|
+
* controls the layout; the web implementation gives it `flex-1` with a
|
|
734
|
+
* maximum width, while native implementations may use a header search bar. */
|
|
715
735
|
readonly toolbarStart?: ReactNode;
|
|
716
|
-
/** Toolbar
|
|
717
|
-
*
|
|
736
|
+
/** Toolbar slot on the right, typically for a + New button, filters, or a
|
|
737
|
+
* view switch. The web implementation moves the cluster to the right edge
|
|
738
|
+
* with `ml-auto`. */
|
|
718
739
|
readonly toolbarEnd?: ReactNode;
|
|
719
|
-
/** Faceted
|
|
720
|
-
*
|
|
740
|
+
/** Faceted filter dropdowns for select/boolean fields. The renderer places
|
|
741
|
+
* them beside the search input; an empty or undefined value renders no filters. */
|
|
721
742
|
readonly filterFacets?: readonly DataTableFacet[];
|
|
722
|
-
/**
|
|
743
|
+
/** Currently selected values for each facet field, supplied by URL state. */
|
|
723
744
|
readonly filterValues?: Readonly<Record<string, readonly string[]>>;
|
|
724
|
-
/**
|
|
745
|
+
/** Toggling a facet value: the caller updates URL state and refetches. */
|
|
725
746
|
readonly onFilterChange?: (field: string, values: readonly string[]) => void;
|
|
726
|
-
/**
|
|
727
|
-
*
|
|
747
|
+
/** Clears all active facets. The renderer shows the reset button only when
|
|
748
|
+
* at least one facet is active. */
|
|
728
749
|
readonly onFilterReset?: () => void;
|
|
729
|
-
/** Time-range filters beside the facet dropdowns
|
|
750
|
+
/** Time-range filters beside the facet dropdowns. */
|
|
730
751
|
readonly dateRangeFacets?: readonly DataTableDateRangeFacet[];
|
|
731
752
|
/** One bound changed ("" clears it) → caller writes URL state + refetch. */
|
|
732
753
|
readonly onDateRangeChange?: (field: string, bound: "from" | "to", value: string) => void;
|
|
733
|
-
/** Pagination
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
754
|
+
/** Pagination state and callback. When set, the renderer shows a pager below
|
|
755
|
+
* the table (web: a footer bar with ← 1 ... N →). `total`, `limit`, and
|
|
756
|
+
* `page` are one-based for the UI; the caller translates them to
|
|
757
|
+
* `offset = (page-1)*limit` for the server. The caller should clamp a page
|
|
758
|
+
* greater than `total/limit` beforehand. */
|
|
738
759
|
readonly pager?: {
|
|
739
760
|
readonly page: number;
|
|
740
761
|
readonly limit: number;
|
|
741
762
|
readonly total: number;
|
|
742
763
|
readonly onPageChange: (next: number) => void;
|
|
743
764
|
/** Offered page sizes; with `onPageSizeChange` the footer shows a
|
|
744
|
-
* "N
|
|
765
|
+
* "N per page" select. */
|
|
745
766
|
readonly pageSizeOptions?: readonly number[];
|
|
746
767
|
readonly onPageSizeChange?: (next: number) => void;
|
|
747
768
|
};
|
|
@@ -750,16 +771,16 @@ export type DataTableProps = {
|
|
|
750
771
|
/** Noun for the footer count ("1–19 of 19 leases", "1 position"),
|
|
751
772
|
* resolved for the given count. Omitted = generic "entries" wording. */
|
|
752
773
|
readonly itemNoun?: (count: number) => string;
|
|
753
|
-
/** Infinite-
|
|
754
|
-
*
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
774
|
+
/** Infinite-scroll callback. When set, the renderer adds a bottom sentinel
|
|
775
|
+
* and calls `onReachEnd` when it enters the viewport (web:
|
|
776
|
+
* `IntersectionObserver`). The caller manages accumulation, the cursor, and
|
|
777
|
+
* `hasMore`. `loadingMore=true` shows a spinner below the table while the
|
|
778
|
+
* next page loads. Incompatible with `pager`: use either pagination or
|
|
779
|
+
* infinite scrolling, not both. */
|
|
759
780
|
readonly onReachEnd?: () => void;
|
|
760
781
|
readonly loadingMore?: boolean;
|
|
761
|
-
/**
|
|
762
|
-
*
|
|
782
|
+
/** When false and `onReachEnd` is set, the renderer shows an end-of-list
|
|
783
|
+
* message instead of the sentinel. Defaults to true. */
|
|
763
784
|
readonly hasMore?: boolean;
|
|
764
785
|
readonly testId?: string;
|
|
765
786
|
/** Wires an edit path into a component column-renderer: `DataTableCell`
|
|
@@ -775,14 +796,14 @@ export type DataTableProps = {
|
|
|
775
796
|
/** Overrides the cell `data-testid` (default `cell-${row.id}-${field}`). */
|
|
776
797
|
readonly getCellTestId?: (row: ListRowViewModel, field: string) => string;
|
|
777
798
|
/** Drops the table's own rounded/border/card background — for a host
|
|
778
|
-
* that already provides the surrounding boundary (a tab panel
|
|
799
|
+
* that already provides the surrounding boundary (a tab panel)
|
|
779
800
|
* and would otherwise show a card nested inside that boundary. Default
|
|
780
801
|
* false: unchanged card-framed table. */
|
|
781
802
|
readonly chromeless?: boolean;
|
|
782
803
|
/** Fills the available height of its flex container and scrolls rows
|
|
783
804
|
* internally instead of growing with row count — for a host that would
|
|
784
805
|
* otherwise have a long table stretch the whole page, or a short table
|
|
785
|
-
* leave dead space below it (a tab panel
|
|
806
|
+
* leave dead space below it (a tab panel). Requires the same
|
|
786
807
|
* flex-fill chain FormProps.fillHeight sets up above it; without that
|
|
787
808
|
* ancestor chain this collapses to zero height (Web: `flex-1 min-h-0`
|
|
788
809
|
* has no effect outside a sized flex-col ancestor). When true the table
|
|
@@ -795,7 +816,7 @@ export type DataTableProps = {
|
|
|
795
816
|
/** Uses the shared screen padding (wider bottom inset) instead of the
|
|
796
817
|
* table's symmetric embedded inset — for a table that IS the screen body
|
|
797
818
|
* (entityList/projectionList), so a list screen ends at the same footer
|
|
798
|
-
* distance as a form or custom screen
|
|
819
|
+
* distance as a form or custom screen. Ignored when
|
|
799
820
|
* `scrollBody` is true: the wider bottom inset would compete with
|
|
800
821
|
* `scrollBody`'s flex-fill height budget.
|
|
801
822
|
* Default false: unchanged symmetric inset for an embedded table. */
|
|
@@ -921,8 +942,9 @@ export type FormProps = {
|
|
|
921
942
|
readonly focusFirstErrorKey?: number;
|
|
922
943
|
readonly children: ReactNode;
|
|
923
944
|
readonly title?: ReactNode;
|
|
924
|
-
/**
|
|
925
|
-
* your catalog")
|
|
945
|
+
/** Optional muted subtitle below the title (e.g. "Add a new item to
|
|
946
|
+
* your catalog"), providing context in the form header rather than only
|
|
947
|
+
* a label. */
|
|
926
948
|
readonly subtitle?: ReactNode;
|
|
927
949
|
readonly actions?: ReactNode;
|
|
928
950
|
/** Secondary, record-related actions — rendered on the left on desktop,
|
|
@@ -934,7 +956,7 @@ export type FormProps = {
|
|
|
934
956
|
readonly width?: FormWidth;
|
|
935
957
|
/** Pins `actions` to the viewport bottom on narrow screens (`<640px`)
|
|
936
958
|
* instead of normal document flow, so it stays reachable when a virtual
|
|
937
|
-
* keyboard shrinks the visible viewport
|
|
959
|
+
* keyboard shrinks the visible viewport. Desktop/tablet
|
|
938
960
|
* unaffected. */
|
|
939
961
|
readonly stickyActions?: boolean;
|
|
940
962
|
/** Extra content rendered above the card, inside the same page padding
|
|
@@ -948,7 +970,7 @@ export type FormProps = {
|
|
|
948
970
|
/** Sizes the form to fill its container's height (instead of the page's
|
|
949
971
|
* natural content height) so a single scrolling child — a lone
|
|
950
972
|
* relatedList tab's table — can scroll internally instead of stretching
|
|
951
|
-
* the whole page
|
|
973
|
+
* the whole page. Set by RenderEdit for a lone relatedList tab
|
|
952
974
|
* section and for screens that fill the shell height (together with
|
|
953
975
|
* `stickyActions`: sections scroll, footer stays pinned without
|
|
954
976
|
* `position: fixed`); every other caller leaves it unset and keeps normal
|
|
@@ -982,18 +1004,18 @@ export type FormProps = {
|
|
|
982
1004
|
* navigation). */
|
|
983
1005
|
readonly sideRail?: ReactNode;
|
|
984
1006
|
};
|
|
985
|
-
/** Titled
|
|
986
|
-
* View
|
|
987
|
-
*
|
|
1007
|
+
/** Titled group of fields. Web: `<fieldset>` + `<legend>`; native
|
|
1008
|
+
* implementations use a `View` with header text and may render the title as
|
|
1009
|
+
* an accordion or collapsible section. */
|
|
988
1010
|
export type SectionProps = {
|
|
989
1011
|
/** DOM id — the scroll target of a form's "on this page" navigation. */
|
|
990
1012
|
readonly id?: string;
|
|
991
|
-
/** Optional
|
|
992
|
-
*
|
|
993
|
-
*
|
|
1013
|
+
/** Optional; without a title, the Section renders only the grouping and no
|
|
1014
|
+
* header. RenderEdit omits it when it would exactly repeat the screen title
|
|
1015
|
+
* in the action bar. */
|
|
994
1016
|
readonly title?: string;
|
|
995
|
-
/**
|
|
996
|
-
*
|
|
1017
|
+
/** Optional muted subtitle below the title, providing section context rather
|
|
1018
|
+
* than only a label (analogous to `FormProps.subtitle`). */
|
|
997
1019
|
readonly subtitle?: ReactNode;
|
|
998
1020
|
readonly children: ReactNode;
|
|
999
1021
|
/** Rendered top-right in the title row — never a footer. A
|
|
@@ -1016,7 +1038,7 @@ export type SectionProps = {
|
|
|
1016
1038
|
/** Chromeless flex-fill layout host — no title, no card frame, no padding,
|
|
1017
1039
|
* just a container that sizes to its content and, once the ancestor chain
|
|
1018
1040
|
* is height-constrained, shrinks so one scrolling child can scroll
|
|
1019
|
-
* internally instead of the page growing
|
|
1041
|
+
* internally instead of the page growing. Web:
|
|
1020
1042
|
* `<div className="flex min-h-0 flex-col">`. Native: Views are
|
|
1021
1043
|
* already flex-column and the parent is already a bounded viewport there,
|
|
1022
1044
|
* so a native impl may render this as a bare Fragment. Used only as the
|
|
@@ -1033,15 +1055,15 @@ export type FillContainerProps = {
|
|
|
1033
1055
|
* height. */
|
|
1034
1056
|
readonly grow?: boolean;
|
|
1035
1057
|
};
|
|
1036
|
-
/**
|
|
1037
|
-
*
|
|
1038
|
-
* `GridCell
|
|
1058
|
+
/** Column-based layout. Web uses CSS grid; native implementations use
|
|
1059
|
+
* flex-wrap with percentages or react-native-grid. Direct children can be
|
|
1060
|
+
* wrapped in `GridCell` to control their span.
|
|
1039
1061
|
*
|
|
1040
|
-
* `columns: "auto"`
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1062
|
+
* `columns: "auto"` disables the N-column stretch layout: children retain
|
|
1063
|
+
* their content width and wrap onto new lines (for example, self-sized
|
|
1064
|
+
* metric tiles or an inline label-and-badge row) instead of stretching into
|
|
1065
|
+
* equal-width tracks. `GridCell` span wrapping is meaningless in this mode
|
|
1066
|
+
* and should be skipped. */
|
|
1045
1067
|
export type GridProps = {
|
|
1046
1068
|
readonly columns: number | "auto";
|
|
1047
1069
|
readonly children: ReactNode;
|
|
@@ -1063,19 +1085,19 @@ export type GridProps = {
|
|
|
1063
1085
|
};
|
|
1064
1086
|
/** Width class of a field cell inside a `flow` grid: sized by what the field holds. */
|
|
1065
1087
|
export type FieldCellWidth = "text" | "number" | "money" | "date" | "timestamp" | "select" | "full" | "toggle";
|
|
1066
|
-
/** Span
|
|
1067
|
-
*
|
|
1088
|
+
/** Span wrapper for a child within a grid. Web: `style={{gridColumn: span N}}`;
|
|
1089
|
+
* native implementations calculate the width themselves. */
|
|
1068
1090
|
export type GridCellProps = {
|
|
1069
1091
|
readonly span?: number;
|
|
1070
1092
|
/** Only read inside a `flow` grid. */
|
|
1071
1093
|
readonly width?: FieldCellWidth;
|
|
1072
1094
|
readonly children: ReactNode;
|
|
1073
1095
|
};
|
|
1074
|
-
/**
|
|
1075
|
-
*
|
|
1076
|
-
*
|
|
1077
|
-
*
|
|
1078
|
-
*
|
|
1096
|
+
/** Semantic text. Variants map to standard typography roles: `body` is
|
|
1097
|
+
* the default, `small` for secondary labels, `code` for inline monospace
|
|
1098
|
+
* (entityId, screen-id), `required-mark` for the asterisk after labels,
|
|
1099
|
+
* `muted` for dimmed body text (text-sm muted-foreground). Custom impls map
|
|
1100
|
+
* these to their own type scale. */
|
|
1079
1101
|
export type TextProps = {
|
|
1080
1102
|
readonly variant?: "body" | "small" | "code" | "required-mark" | "muted";
|
|
1081
1103
|
/** Pure ornament (e.g. a separator glyph): hidden from assistive tech. */
|
|
@@ -1083,30 +1105,31 @@ export type TextProps = {
|
|
|
1083
1105
|
readonly children: ReactNode;
|
|
1084
1106
|
readonly testId?: string;
|
|
1085
1107
|
};
|
|
1086
|
-
/** Heading
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1108
|
+
/** Heading with two roles: `page` is a page title (web: h1), while `section`
|
|
1109
|
+
* is a group subheading (web: h2 with uppercase and muted styling). Native
|
|
1110
|
+
* implementations map these to `<Text>` with the corresponding font weight
|
|
1111
|
+
* and size. */
|
|
1089
1112
|
export type HeadingProps = {
|
|
1090
1113
|
readonly variant?: "page" | "section";
|
|
1091
1114
|
readonly children: ReactNode;
|
|
1092
1115
|
readonly testId?: string;
|
|
1093
1116
|
};
|
|
1094
|
-
/** Modal
|
|
1095
|
-
* Radix
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
1117
|
+
/** Modal dialog for confirmations or compact sub-forms. The web renderer
|
|
1118
|
+
* uses Radix Dialog with focus trapping, Escape-to-close, and overlay-click
|
|
1119
|
+
* handling; native implementations may use a native modal. Apps control it
|
|
1120
|
+
* through external state (`open` + `onOpenChange`); confirmation runs through
|
|
1121
|
+
* `onConfirm`, while cancellation closes it via `onOpenChange(false)`.
|
|
1099
1122
|
*
|
|
1100
|
-
* Variant `danger`
|
|
1101
|
-
*
|
|
1123
|
+
* Variant `danger` visually marks destructive confirmations with a red
|
|
1124
|
+
* confirm-button class; `default` is for neutral dialogs. */
|
|
1102
1125
|
export type DialogProps = {
|
|
1103
1126
|
readonly open: boolean;
|
|
1104
1127
|
readonly onOpenChange: (open: boolean) => void;
|
|
1105
1128
|
readonly title: string;
|
|
1106
|
-
/** Optional
|
|
1107
|
-
*
|
|
1129
|
+
/** Optional description, typically a sentence explaining the consequence
|
|
1130
|
+
* ("This action cannot be undone."). */
|
|
1108
1131
|
readonly description?: string;
|
|
1109
|
-
/** Confirm-
|
|
1132
|
+
/** Confirm-button label. Defaults to the i18n value
|
|
1110
1133
|
* (`kumiko.dialog.confirm`). */
|
|
1111
1134
|
readonly confirmLabel?: string;
|
|
1112
1135
|
/** Cancel-Button-Label. Default `kumiko.dialog.cancel`. */
|
|
@@ -1118,12 +1141,11 @@ export type DialogProps = {
|
|
|
1118
1141
|
* `children` are present. `"cancel"` for
|
|
1119
1142
|
* dialogs where the safe choice must be the one Enter triggers. */
|
|
1120
1143
|
readonly initialFocus?: "confirm" | "cancel";
|
|
1121
|
-
/**
|
|
1122
|
-
*
|
|
1123
|
-
* onOpenChange(false). */
|
|
1144
|
+
/** Called when the user confirms. Async functions are supported; the dialog
|
|
1145
|
+
* automatically sets a loading state and then calls `onOpenChange(false)`. */
|
|
1124
1146
|
readonly onConfirm: () => void | Promise<void>;
|
|
1125
|
-
/** Optional
|
|
1126
|
-
*
|
|
1147
|
+
/** Optional additional content between the description and buttons, such as
|
|
1148
|
+
* an input when the dialog also collects data. */
|
|
1127
1149
|
readonly children?: ReactNode;
|
|
1128
1150
|
readonly testId?: string;
|
|
1129
1151
|
};
|
|
@@ -1144,7 +1166,7 @@ export type ModalProps = {
|
|
|
1144
1166
|
/** Side panel for hosting an existing self-contained form/widget (own
|
|
1145
1167
|
* submit/cancel buttons) without leaving the underlying screen — e.g. a
|
|
1146
1168
|
* toolbar action's `kind: "drawer"` mounts an actionForm here instead of
|
|
1147
|
-
* navigating to a full page
|
|
1169
|
+
* navigating to a full page. Same "bare content shell, no
|
|
1148
1170
|
* footer buttons of its own" contract as `Modal`, slide-in instead of
|
|
1149
1171
|
* centered overlay. */
|
|
1150
1172
|
export type DrawerProps = {
|
|
@@ -1209,10 +1231,10 @@ export type ConfigCascadeViewProps = {
|
|
|
1209
1231
|
* value). Absent = the raw value; a missing value keeps the no-value text. */
|
|
1210
1232
|
readonly renderValue?: (value: string | number | boolean) => ReactNode;
|
|
1211
1233
|
};
|
|
1212
|
-
/** Card
|
|
1213
|
-
*
|
|
1214
|
-
*
|
|
1215
|
-
*
|
|
1234
|
+
/** Card slots are named content regions, all optional. Adding slots is
|
|
1235
|
+
* additive, so consumers do not need migration. `header` is an escape hatch:
|
|
1236
|
+
* a raw node replaces the default header (`title`/`subtitle`/`headerActions`)
|
|
1237
|
+
* when the convenience slots are insufficient. */
|
|
1216
1238
|
export type CardSlots = {
|
|
1217
1239
|
readonly header?: ReactNode;
|
|
1218
1240
|
readonly title?: ReactNode;
|
|
@@ -1221,9 +1243,9 @@ export type CardSlots = {
|
|
|
1221
1243
|
* title/subtitle/`headerActions` row, within the same header block — for a
|
|
1222
1244
|
* host-supplied header (projectionDetail `slots.header`). */
|
|
1223
1245
|
readonly headerContent?: ReactNode;
|
|
1224
|
-
/**
|
|
1246
|
+
/** Right-aligned header slot, for example a range switcher, filter, or badge. */
|
|
1225
1247
|
readonly headerActions?: ReactNode;
|
|
1226
|
-
/** Footer
|
|
1248
|
+
/** Footer content, separated by a top border; aligned to the right by default. */
|
|
1227
1249
|
readonly footer?: ReactNode;
|
|
1228
1250
|
};
|
|
1229
1251
|
/** Card-Options — Verhalten/Optik, ebenfalls additiv erweiterbar. */
|
|
@@ -1232,12 +1254,12 @@ export type CardOptions = {
|
|
|
1232
1254
|
readonly padded?: boolean;
|
|
1233
1255
|
/** Eckenradius. Default "xl" (= Entity-Card). */
|
|
1234
1256
|
readonly radius?: "lg" | "xl";
|
|
1235
|
-
/**
|
|
1257
|
+
/** Separates the footer with `border-t` and `bg-muted/30`. Defaults to true. */
|
|
1236
1258
|
readonly footerBordered?: boolean;
|
|
1237
1259
|
/** Footer horizontal padding. false = none, so footer content aligns with the card edge. Default true. */
|
|
1238
1260
|
readonly footerInset?: boolean;
|
|
1239
|
-
/** Joins the ancestor fillHeight flex chain
|
|
1240
|
-
* relatedList table sizing to the panel instead of the page
|
|
1261
|
+
/** Joins the ancestor fillHeight flex chain — a tabs-mode
|
|
1262
|
+
* relatedList table sizing to the panel instead of the page — instead of
|
|
1241
1263
|
* normal document-flow height. Default false. */
|
|
1242
1264
|
readonly fillHeight?: boolean;
|
|
1243
1265
|
/** false drops border, background, shadow and radius but keeps padding and
|
|
@@ -1249,13 +1271,15 @@ export type CardOptions = {
|
|
|
1249
1271
|
* shell edge. Default false. */
|
|
1250
1272
|
readonly screenBody?: boolean;
|
|
1251
1273
|
};
|
|
1252
|
-
/**
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1274
|
+
/** Generic card chrome (border/background/radius/shadow plus
|
|
1275
|
+
* header/body/footer) as a primitive, providing one implementation for all
|
|
1276
|
+
* card surfaces. It is slot- and option-based so the contract can evolve
|
|
1277
|
+
* additively. */
|
|
1255
1278
|
export type CardProps = {
|
|
1256
1279
|
readonly slots?: CardSlots;
|
|
1257
1280
|
readonly options?: CardOptions;
|
|
1258
|
-
/** Body
|
|
1281
|
+
/** Body content in the normal case; header and footer are supplied through
|
|
1282
|
+
* `slots`. */
|
|
1259
1283
|
readonly children?: ReactNode;
|
|
1260
1284
|
readonly className?: string;
|
|
1261
1285
|
readonly testId?: string;
|
|
@@ -1320,8 +1344,8 @@ export type StepBarProps = {
|
|
|
1320
1344
|
* native constraint-validation concept (web: `<fieldset disabled>`, spec-
|
|
1321
1345
|
* guaranteed to also bar descendants from participating) must bar it too,
|
|
1322
1346
|
* or a `type="submit"` step-advance button triggers the browser's
|
|
1323
|
-
* full-form check against fields on unvisited, unfocusable steps
|
|
1324
|
-
*
|
|
1347
|
+
* full-form check against fields on unvisited, unfocusable steps.
|
|
1348
|
+
* Implementations without that concept can gate
|
|
1325
1349
|
* on `hidden` alone. */
|
|
1326
1350
|
export type WizardStepGroupProps = {
|
|
1327
1351
|
readonly hidden: boolean;
|
|
@@ -1409,7 +1433,7 @@ export type PageHeaderProps = {
|
|
|
1409
1433
|
* the route names, for a locked screen's fallback. Wins over `hideBreadcrumb`. */
|
|
1410
1434
|
readonly breadcrumbScreenId?: string;
|
|
1411
1435
|
};
|
|
1412
|
-
/** One item in an `ActionOverflowMenu` (
|
|
1436
|
+
/** One item in an `ActionOverflowMenu` (header/row actions beyond the
|
|
1413
1437
|
* primary one collapse into this menu instead of a wall of buttons). */
|
|
1414
1438
|
export type ActionMenuItemSpec = {
|
|
1415
1439
|
readonly id: string;
|
|
@@ -1427,7 +1451,7 @@ export type ActionOverflowMenuProps = {
|
|
|
1427
1451
|
readonly label: string;
|
|
1428
1452
|
readonly testId?: string;
|
|
1429
1453
|
};
|
|
1430
|
-
/** One revealed value on a `secretMint` screen's confirm phase
|
|
1454
|
+
/** One revealed value on a `secretMint` screen's confirm phase. */
|
|
1431
1455
|
export type SecretRevealValue = {
|
|
1432
1456
|
readonly label: string;
|
|
1433
1457
|
readonly value: string;
|
|
@@ -1577,7 +1601,7 @@ export type CorePrimitives = {
|
|
|
1577
1601
|
/** Optional — additive rollout, see StickyActionBar. */
|
|
1578
1602
|
readonly MetricBand?: ComponentType<MetricBandProps>;
|
|
1579
1603
|
/** Optional: without an implementation, callers with >2 header/row
|
|
1580
|
-
* actions fall back to today's all-buttons-inline rendering
|
|
1604
|
+
* actions fall back to today's all-buttons-inline rendering. */
|
|
1581
1605
|
readonly ActionOverflowMenu?: ComponentType<ActionOverflowMenuProps>;
|
|
1582
1606
|
/** Optional (unlike the other Core-Primitives) so existing partial
|
|
1583
1607
|
* CorePrimitives mocks in tests keep compiling — additive rollout of
|
|
@@ -1594,8 +1618,8 @@ export type CorePrimitives = {
|
|
|
1594
1618
|
/** Optional — additive rollout, see StickyActionBar. */
|
|
1595
1619
|
readonly PromoPanel?: ComponentType<PromoPanelProps>;
|
|
1596
1620
|
};
|
|
1597
|
-
/**
|
|
1598
|
-
*
|
|
1621
|
+
/** Extension point for app-owned primitives. Developers extend this
|
|
1622
|
+
* interface through TypeScript module augmentation:
|
|
1599
1623
|
*
|
|
1600
1624
|
* declare module "@cosmicdrift/kumiko-renderer" {
|
|
1601
1625
|
* interface AppPrimitives {
|
|
@@ -1604,12 +1628,11 @@ export type CorePrimitives = {
|
|
|
1604
1628
|
* }
|
|
1605
1629
|
* }
|
|
1606
1630
|
*
|
|
1607
|
-
*
|
|
1608
|
-
* `createKumikoApp({ primitives: { Chip, Accordion } })`,
|
|
1609
|
-
* `usePrimitives().Chip`
|
|
1610
|
-
*
|
|
1611
|
-
*
|
|
1612
|
-
* Components). */
|
|
1631
|
+
* After augmentation, the keys appear in `PrimitivesRegistry`,
|
|
1632
|
+
* `createKumikoApp({ primitives: { Chip, Accordion } })`, and
|
|
1633
|
+
* `usePrimitives().Chip` with TypeScript support. Kumiko's own components
|
|
1634
|
+
* use only `CorePrimitives`; app primitives are exclusively for developer
|
|
1635
|
+
* code such as custom screens, shells, and app-owned components. */
|
|
1613
1636
|
export interface AppPrimitives {
|
|
1614
1637
|
}
|
|
1615
1638
|
export type PrimitivesRegistry = CorePrimitives & AppPrimitives;
|