@cosmicdrift/kumiko-framework 0.399.0 → 0.400.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/agents/api/framework-engine.md +9 -3
  2. package/agents/api/framework-ui-types.md +10 -5
  3. package/agents/api/renderer-web.md +2 -1
  4. package/agents/api/types.md +242 -80
  5. package/agents/api.md +2 -2
  6. package/agents/examples/derived-fields-sql.md +251 -0
  7. package/agents/examples/documents.md +161 -0
  8. package/agents/examples/inspection-checklist.md +807 -0
  9. package/agents/examples.md +3 -0
  10. package/agents/features-index.md +2 -0
  11. package/agents/features.md +8 -0
  12. package/dist/api/entity-read-access.d.ts +2 -0
  13. package/dist/api/entity-read-access.js +46 -2
  14. package/dist/api/server-boot-checks.js +2 -2
  15. package/dist/api/server-routes.js +3 -1
  16. package/dist/db/derived-field-sql.d.ts +23 -0
  17. package/dist/db/derived-field-sql.js +115 -0
  18. package/dist/db/derived-related-sql.d.ts +31 -0
  19. package/dist/db/derived-related-sql.js +137 -0
  20. package/dist/db/driver-row-coercion.d.ts +1 -0
  21. package/dist/db/driver-row-coercion.js +13 -0
  22. package/dist/db/eagerload.d.ts +3 -1
  23. package/dist/db/eagerload.js +4 -6
  24. package/dist/db/event-store-executor-context.js +1 -1
  25. package/dist/db/event-store-executor-read-paging.js +1 -1
  26. package/dist/db/event-store-executor-read-search.d.ts +3 -0
  27. package/dist/db/event-store-executor-read-search.js +17 -9
  28. package/dist/db/event-store-executor-read-sort.d.ts +9 -2
  29. package/dist/db/event-store-executor-read-sort.js +27 -14
  30. package/dist/db/event-store-executor-read-where.d.ts +0 -5
  31. package/dist/db/event-store-executor-read-where.js +3 -9
  32. package/dist/db/event-store-executor-read.js +23 -4
  33. package/dist/db/event-store-executor-write-steps.d.ts +6 -1
  34. package/dist/db/event-store-executor-write-steps.js +20 -1
  35. package/dist/db/event-store-executor-write.js +8 -8
  36. package/dist/db/money.d.ts +4 -0
  37. package/dist/db/money.js +34 -29
  38. package/dist/db/parent-ref-clause.d.ts +1 -0
  39. package/dist/db/parent-ref-clause.js +18 -8
  40. package/dist/db/read-gate-clause.d.ts +7 -0
  41. package/dist/db/read-gate-clause.js +188 -0
  42. package/dist/db/read-ownership.d.ts +9 -0
  43. package/dist/db/read-ownership.js +12 -0
  44. package/dist/engine/boot-validator/boot-check.d.ts +3 -1
  45. package/dist/engine/boot-validator/boot-check.js +7 -11
  46. package/dist/engine/boot-validator/boot-context.d.ts +26 -0
  47. package/dist/engine/boot-validator/boot-context.js +57 -0
  48. package/dist/engine/boot-validator/boot-options.d.ts +33 -0
  49. package/dist/engine/boot-validator/boot-options.js +1 -0
  50. package/dist/engine/boot-validator/boot-phases-app.d.ts +5 -0
  51. package/dist/engine/boot-validator/boot-phases-app.js +103 -0
  52. package/dist/engine/boot-validator/boot-phases.d.ts +11 -0
  53. package/dist/engine/boot-validator/boot-phases.js +140 -0
  54. package/dist/engine/boot-validator/boot-report.d.ts +6 -0
  55. package/dist/engine/boot-validator/boot-report.js +47 -0
  56. package/dist/engine/boot-validator/boot-rule.d.ts +12 -0
  57. package/dist/engine/boot-validator/boot-rule.js +14 -0
  58. package/dist/engine/boot-validator/boot-warnings.d.ts +2 -0
  59. package/dist/engine/boot-validator/boot-warnings.js +20 -0
  60. package/dist/engine/boot-validator/derived-sql-fields.d.ts +4 -0
  61. package/dist/engine/boot-validator/derived-sql-fields.js +184 -0
  62. package/dist/engine/boot-validator/entity-handler.d.ts +3 -0
  63. package/dist/engine/boot-validator/entity-handler.js +6 -3
  64. package/dist/engine/boot-validator/entity-list-screens.js +3 -1
  65. package/dist/engine/boot-validator/field-conditions.d.ts +2 -0
  66. package/dist/engine/boot-validator/field-conditions.js +178 -0
  67. package/dist/engine/boot-validator/i18n-keys.d.ts +2 -2
  68. package/dist/engine/boot-validator/i18n-keys.js +1 -3
  69. package/dist/engine/boot-validator/index.d.ts +5 -34
  70. package/dist/engine/boot-validator/index.js +24 -204
  71. package/dist/engine/boot-validator/pii-retention.js +2 -7
  72. package/dist/engine/boot-validator/projection-list-screens.js +19 -1
  73. package/dist/engine/boot-validator/read-gate.d.ts +2 -0
  74. package/dist/engine/boot-validator/read-gate.js +54 -0
  75. package/dist/engine/boot-validator/screens-forms.js +19 -6
  76. package/dist/engine/boot-validator/screens-kind-entity-list.js +8 -6
  77. package/dist/engine/boot-validator/screens-lists.js +8 -0
  78. package/dist/engine/boot-validator/zod-shape.js +4 -2
  79. package/dist/engine/build-app-schema.js +11 -5
  80. package/dist/engine/embedded-derived.d.ts +8 -6
  81. package/dist/engine/embedded-derived.js +25 -7
  82. package/dist/engine/entity-handlers.d.ts +1 -1
  83. package/dist/engine/entity-handlers.js +17 -18
  84. package/dist/engine/entity-list-runtime-options.d.ts +2 -1
  85. package/dist/engine/entity-list-runtime-options.js +86 -5
  86. package/dist/engine/factories.d.ts +5 -5
  87. package/dist/engine/factories.js +3 -5
  88. package/dist/engine/field-access.d.ts +2 -0
  89. package/dist/engine/field-access.js +48 -1
  90. package/dist/engine/field-state.d.ts +12 -0
  91. package/dist/engine/field-state.js +67 -0
  92. package/dist/engine/handler-helpers.d.ts +3 -0
  93. package/dist/engine/handler-helpers.js +7 -1
  94. package/dist/engine/index.d.ts +2 -2
  95. package/dist/engine/index.js +2 -2
  96. package/dist/engine/ownership.d.ts +1 -1
  97. package/dist/engine/ownership.js +9 -5
  98. package/dist/engine/registry-state.d.ts +1 -0
  99. package/dist/engine/registry-state.js +1 -1
  100. package/dist/engine/schema-builder.js +3 -0
  101. package/dist/engine/strip-unreadable-related-lists.d.ts +4 -0
  102. package/dist/engine/strip-unreadable-related-lists.js +80 -0
  103. package/dist/files/assert-file-refs-belong-to-tenant.js +26 -6
  104. package/dist/files/bind-pending-file-refs.d.ts +3 -2
  105. package/dist/files/bind-pending-file-refs.js +11 -12
  106. package/dist/files/bind-referenced-files.write.js +5 -5
  107. package/dist/files/create-file-ref-from-bytes.d.ts +2 -0
  108. package/dist/files/create-file-ref-from-bytes.js +2 -0
  109. package/dist/files/create-file-ref.d.ts +2 -0
  110. package/dist/files/create-file-ref.js +39 -22
  111. package/dist/files/dispose-removed-file-refs.js +5 -8
  112. package/dist/files/file-field-slots.d.ts +10 -0
  113. package/dist/files/file-field-slots.js +53 -0
  114. package/dist/files/file-ref-entity.d.ts +1 -1
  115. package/dist/files/file-ref-table.d.ts +1 -1
  116. package/dist/files/file-routes.js +12 -3
  117. package/dist/files/index.d.ts +1 -0
  118. package/dist/files/index.js +1 -0
  119. package/dist/files/load-save-file-refs.js +3 -4
  120. package/dist/files/record-read-check.js +2 -30
  121. package/dist/files/record-write-check.d.ts +2 -0
  122. package/dist/files/record-write-check.js +18 -3
  123. package/dist/files/upload-field-resolution.d.ts +2 -1
  124. package/dist/files/upload-field-resolution.js +33 -13
  125. package/dist/pipeline/dispatch-batch.js +6 -5
  126. package/dist/pipeline/dispatch-write.js +2 -1
  127. package/dist/pipeline/write-result-masking.js +2 -1
  128. package/dist/schema-cli/validate-command.js +46 -12
  129. package/dist/schema-cli.js +1 -1
  130. package/dist/ui-types/index.d.ts +2 -1
  131. package/dist/ui-types/index.js +2 -1
  132. package/package.json +3 -3
  133. package/src/changes.json +55 -0
@@ -30,10 +30,10 @@ function createBigIntField<R extends true | false = false>(overrides?: Partial<O
30
30
  function createBooleanField<R extends true | false = false>(overrides?: Partial<Omit<BooleanFieldDef, "type" | "required">> & { required?: R; }): BooleanFieldDef & { required: R; default: boolean; };
31
31
  function createDateField<R extends true | false = false>(overrides?: Partial<Omit<DateFieldDef, "type" | "required" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind & { required?: R; }): DateFieldDef & { required: R; };
32
32
  function createDecimalField<R extends true | false = false>(config: { precision: number; scale: number; } & Partial<Omit<DecimalFieldDef, "type" | "precision" | "scale" | "required" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind & { required?: R; }): DecimalFieldDef & { required: R; };
33
- function createDerivedField(spec: DerivedFieldDef): DerivedFieldDef; // Read-time computed field for `EntityDefinition.derivedFields` (NOT `fields`).
33
+ function createDerivedField(spec: DerivedFieldDef): DerivedFieldDef; // Read-time computed field for `EntityDefinition.derivedFields` (NOT `fields`), never persisted.
34
34
  function createEmbeddedField(schema: EmbeddedFieldDef["schema"], overrides?: Partial<Omit<EmbeddedFieldDef, "type" | "schema" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind): EmbeddedFieldDef;
35
35
  function createEmbeddedListField(schema: EmbeddedFieldDef["schema"], overrides?: Partial<Omit<EmbeddedFieldDef, "type" | "schema" | "multiple" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind): EmbeddedFieldDef & { multiple: true; };
36
- function createEntity<const F, const T extends EntityTenancy = "tenant">(def: { table?: string; fields: F; description?: string; softDelete?: boolean; systemStream?: boolean; eventVersion?: number; eventMigrations?: EntityDefinition["eventMigrations"]; searchWeight?: number; defaultCurrency?: string; transitions?: Readonly<Record<string, Readonly<Record<string, string[]>>>>; lockedWhen?: EntityDefinition["lockedWhen"]; indexes?: EntityIndexDef[]; idType?: "serial" | "uuid"; access?: EntityDefinition["access"]; parentRef?: EntityDefinition["parentRef"]; retention?: RetentionDef; derivedFields?: EntityDefinition["derivedFields"]; tenancy?: T; transferable?: boolean; attachedFileAccess?: EntityDefinition["attachedFileAccess"]; }): F extends FieldsMap ? EntityDefinition<F, T> : never;
36
+ function createEntity<const F, const T extends EntityTenancy = "tenant">(def: { table?: string; fields: F; description?: string; softDelete?: boolean; systemStream?: boolean; eventVersion?: number; eventMigrations?: EntityDefinition["eventMigrations"]; searchWeight?: number; defaultCurrency?: string; transitions?: Readonly<Record<string, Readonly<Record<string, string[]>>>>; lockedWhen?: EntityDefinition["lockedWhen"]; indexes?: EntityIndexDef[]; idType?: "serial" | "uuid"; access?: EntityDefinition["access"]; parentRef?: EntityDefinition["parentRef"]; readGate?: EntityDefinition["readGate"]; retention?: RetentionDef; derivedFields?: EntityDefinition["derivedFields"]; tenancy?: T; transferable?: boolean; attachedFileAccess?: EntityDefinition["attachedFileAccess"]; }): F extends FieldsMap ? EntityDefinition<F, T> : never;
37
37
  function createEntityExecutor<E extends EntityDefinition>(entityName: string, entity: E): { table: EntityTable; executor: EventStoreExecutor<EntityRow<E>>; };
38
38
  function createFileField(overrides?: Partial<Omit<FileFieldDef, "type" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind): FileFieldDef;
39
39
  function createFilesField(overrides?: Partial<Omit<FilesFieldDef, "type" | keyof ResolvedPiiFlags>> & PersonalAnnotationsNoFind): FilesFieldDef;
@@ -120,6 +120,7 @@ function normalizeEditField(f: EditFieldSpec): Exclude<EditFieldSpec, string>;
120
120
  function normalizeListColumn(c: ListColumnSpec): Exclude<ListColumnSpec, string>;
121
121
  function pageRows<TRow extends Readonly<Record<TSortField, PagedListRowValue>> & { id: string; }, TSortField extends string>(rows: TRow[], request: PagedListRequest<TSortField>, options: { searchFields: TSortField[]; defaultSort: TSortField; }): CursorResult<TRow>;
122
122
  function pagedListSchema<const TSortField extends string>(sortableFields: [ TSortField, ...TSortField[] ]): …;
123
+ function parentVisibilityFor(ctx: HandlerContext, user: SessionUser): ParentVisibilityOption;
123
124
  function parseChangesetChanges(markdown: string, source: string): PendingChange[]; // Parse structured upgrade metadata embedded in a Changeset body.
124
125
  function parseFeatureChangelog(raw: string, featureName: string): FeatureChangelog | null; // Parse a changes.json body.
125
126
  function parseQn(value: string): ParsedQn;
@@ -145,6 +146,7 @@ function tenantChannel(tenantId: TenantId): string;
145
146
  function toKebab(input: string): string;
146
147
  function typedPayload<TPayload>(event: { type: string; payload: Record<string, unknown>; }, eventDef: EventDef<TPayload>): TPayload;
147
148
  function unwrapWorkflowStepError(error: unknown): unknown;
149
+ function userCanWriteFieldRow(user: SessionUser, accessMap: OwnershipMap | undefined, oldRow: Readonly<Record<string, unknown>>, newRow: Readonly<Record<string, unknown>>): boolean;
148
150
  function validateAppCustomScreenWriteQns(appRoot: string, knownQns: ReadonlySet<string>): void; // Boot-time scan of app `src/**` for `dispatcher.write("…")` string literals.
149
151
  function validateBoot(rawFeatures: FeatureDefinition[], options?: ValidateBootOptions): void; // Validates all feature configurations at boot time.
150
152
  function validateBundledListsOptions(options: unknown): void;
@@ -482,6 +484,7 @@ type EditRelatedListSection = {
482
484
  id?: string; // Kebab-case tab id, used as the `?tab=` value.
483
485
  kind: "relatedList";
484
486
  title: string;
487
+ readOnly?: boolean; // Rows are aggregates or other values with no record of their own, so they lead nowhere on purpose.
485
488
  query: string; // Fully qualified query QN.
486
489
  parentParam?: string; // Query-payload key the parent record's id is passed under.
487
490
  parentFilter?: {
@@ -506,6 +509,7 @@ type EditRelatedListSection = {
506
509
  rowTone?: RelatedListRowTone; // Tints rows whose field matches — a declarative rule, not a function, so the screen definition stays serializable.
507
510
  toolbarActions?: RelatedListToolbarAction[]; // Toolbar actions above the table — same type and dispatch semantics as `entityList`/`projectionList`'s `toolbarActions` ("+ Anlegen" etc.), plus `visible`/`params` evaluated against the parent record (see RelatedListToolbarAction).
508
511
  countField?: string; // Record field rendered as a count badge in the tab label when the enclosing `EditLayout.mode` is "tabs" (e.g. an open-items counter).
512
+ count?: true; // Tab badge counted from this section's own query (`limit: 1, totalCount: true` → `total`), so it matches the tab's rows and stays live.
509
513
  actions?: RowAction[]; // Rendered top-right in the section's Card title row — same navigate/drawer/writeHandler dispatch as `ProjectionDetailScreenDefinition.actions`, evaluated against the parent record.
510
514
  emptyState?: RelatedListEmptyStateSpec; // Rendered inside the section's Card in place of the table when this section's query returns zero rows.
511
515
  };
@@ -532,6 +536,7 @@ type EntityDefinition<F extends FieldsMap = FieldsMap, T extends EntityTenancy =
532
536
  write?: OwnershipMap;
533
537
  }; // Row-level ownership rules (H.2).
534
538
  parentRef?: ParentRefDef; // Join-row carrier reference.
539
+ readGate?: ReadGateDef; // Declarative read gate for rows readable only through other rows (a link to a visible host, a file whose owner is readable).
535
540
  retention?: RetentionDef; // Default retention policy for this entity.
536
541
  derivedFields?: DerivedFieldsMap; // Read-time computed fields, keyed by name.
537
542
  description?: string; // Optional free-text semantics for the AI agent manifest — see TextFieldDef.description.
@@ -942,7 +947,7 @@ type JobTrigger =
942
947
  manual: true;
943
948
  }
944
949
  ;
945
- type JsonbFieldDef = ResolvedPiiFlags & {
950
+ type JsonbFieldDef = PiiAndFieldState & {
946
951
  type: "jsonb";
947
952
  description?: string;
948
953
  emptyValue?: JsonbEmptyValue; // `"array"`: the field holds a JSON array, so a row that never wrote it reads `[]` and writes take an array.
@@ -1798,6 +1803,7 @@ type WriteResult<TData = unknown> =
1798
1803
  | {
1799
1804
  isSuccess: true;
1800
1805
  data: TData;
1806
+ lifecycle?: LifecycleResult; // The executor result behind a handler that answers with its own `data`.
1801
1807
  }
1802
1808
  | WriteFailure
1803
1809
  ;
@@ -10,13 +10,17 @@ Import from `@cosmicdrift/kumiko-framework/ui-types`. Types used here but not ex
10
10
  function applyFormDerivations(values: unknown, screen: FormDerivationScreen): unknown; // Recomputes every derived head field of an action form from its inputs.
11
11
  function availableSelectOptions(field: SelectOptionRules, values: Record<string, unknown>): string[]; // Options of a select field that are offered for the given row values, in declaration order.
12
12
  function cardColumnRoles<C extends CardRoleColumn>(columns: C[]): CardColumnRoles<C>;
13
- function computeDerivedCellValue(op: EmbeddedDerivedCellDef["op"], values: (number | undefined)[]): number | undefined; // Computes a derived cell from its source values.
13
+ function computeDerivedCellValue(op: NumericDerivedOp, values: (number | undefined)[]): number | undefined; // Computes a derived cell from its source values.
14
14
  function evalFieldCondition(cond: FieldCondition, values: Record<string, unknown>): boolean; // Evaluates a declarative FieldCondition against the current row/form values.
15
+ function findMissingConditionalRequirements(fields: Readonly<Record<string, FieldDefinition>>, values: Record<string, unknown>, previous?: Record<string, unknown>): string[]; // Paths of fields (and embedded sub-fields) whose `requiredWhen` holds while the value is missing.
15
16
  function findUnavailableSelectOptions(fields: Readonly<Record<string, FieldDefinition>>, values: Record<string, unknown>, previous?: Record<string, unknown>): UnavailableSelectOption[]; // Select values that violate a `conditionalOptions` rule.
16
17
  function formalLocaleTag<Locale extends string>(locale: Locale): `${Locale}-x-formal`;
17
18
  function isExtensionEditSection(section: EditSectionSpec): section is EditExtensionSection;
19
+ function isFieldRequired(def: RequiredState, values: Record<string, unknown>): boolean;
20
+ function isFieldVisible(def: FieldStateConditions, values: Record<string, unknown>): boolean;
18
21
  function isFormDerivationInputMode(screen: FormDerivationScreen, values: unknown, field: string): boolean; // True when `field` is a `listSum` without `whenEmpty` whose list has no rows: the sum has nothing to add up, so the user types the value.
19
22
  function isFormatSpec(r: unknown): r is FormatSpec;
23
+ function isMissingRequiredValue(value: unknown): boolean;
20
24
  function isRecordLocked(lockedWhen: FieldCondition | undefined, row: Readonly<Record<string, unknown>>): boolean;
21
25
  function isUiAccessGranted(access: AccessRule | undefined, userRoles: string[] | undefined): boolean;
22
26
  function isUnchangedValue(a: unknown, b: unknown): boolean;
@@ -26,6 +30,7 @@ function resolveNavParentScreen(screens: ScreenDefinition[], detail: ScreenDefin
26
30
  function resolveTranslationValue(value: TranslationValue, locale: string, params?: Readonly<Record<string, unknown>>): string; // Resolve a TranslationValue to display text: a plural entry picks its CLDR category via `Intl.PluralRules` from `params.count`, falling back to `other` when `count` is missing, non-finite, or `locale` is invalid.
27
31
  function roundDerivedCellValue(value: number, target: DerivedCellRoundingTarget): number; // Rounds a derived cell's computed value to the precision its target sub-field declares — commercial rounding (round-half-away-from-zero, correct for signed minor-unit money).
28
32
  function translationValueOtherText(value: TranslationValue): string; // Text-only reading of a TranslationValue — the CLDR `other` form for a plural entry, or the string as-is.
33
+ function withDerivedCells(row: unknown, derived: Readonly<Record<string, EmbeddedDerivedCellDef>>, targets: Readonly<Record<string, DerivedCellRoundingTarget>>): unknown; // Recomputes every derived cell of an embedded-list row from its raw values, overwriting whatever the client sent instead of merely checking it — the server is the authority for derived cells.
29
34
  ```
30
35
 
31
36
  ## Constants
@@ -331,12 +336,12 @@ type EditWriteFormSection = {
331
336
  submitLabel?: string; // i18n-key for the submit button.
332
337
  actions?: RowAction[]; // Rendered top-right in the section's Card title row — same navigate/drawer/writeHandler dispatch as `ProjectionDetailScreenDefinition.actions`, evaluated against the same record.
333
338
  };
334
- type EmbeddedDerivedCellDef = { // A cell computed from other cells of the same row.
335
- op: "multiply" | "sum" | "subtract" | "percent"; // `percent` = `from[0] * from[1] / 100` (exactly two sources, e.g. amount and rate).
336
- from: string[];
339
+ type EmbeddedDerivedCellDef = ({ op: "multiply" | "sum" | "subtract" | "percent"; from: string[]; } | { op: "inRange"; from: string[]; inside: string; outside: string; }) & { // A cell computed from other cells of the same row.
340
+ when?: Exclude<FieldCondition, boolean>; // Row-level condition on a sibling sub-field.
337
341
  };
338
342
  type EmbeddedListEditSpec = {
339
343
  readOnlyCells?: string[]; // Sub-fields shown as read-only cells; every other cell stays editable.
344
+ cardHiddenCells?: string[]; // Sub-fields that only steer a row (e.g. the kind that decides which controls appear) and are not shown on phone cards; the desktop table still shows them.
340
345
  fixedRows?: boolean; // `true` keeps the rows as they are: no add, remove, duplicate, move or paste-appended rows.
341
346
  };
342
347
  type EntityEditAction = RowAction & {
@@ -507,7 +512,7 @@ type SecretsEditScreenDefinition = {
507
512
  access?: AccessRule;
508
513
  };
509
514
  type SelectOptionTone = (typeof SELECT_OPTION_TONES)[number];
510
- type TextFieldDef = ResolvedPiiFlags & {
515
+ type TextFieldDef = PiiAndFieldState & {
511
516
  type: "text";
512
517
  description?: string; // Optional free-text semantics for the AI agent manifest — never rendered; the i18n label is what users see.
513
518
  maxLength?: number;
@@ -499,7 +499,7 @@ interface FileFieldProps extends FieldBase {
499
499
  entityType?: string; // Binds the upload to a specific entity field; the `/api/files` endpoint then validates `accept`/`maxSize` server-side against that field's definition.
500
500
  fieldName?: string;
501
501
  }
502
- type FileRefTarget = Pick<FileUploadFormDataInput, "entityType" | "entityId" | "fieldName" | "actionForm">;
502
+ type FileRefTarget = Pick<FileUploadFormDataInput, "entityType" | "entityId" | "fieldName" | "subField" | "actionForm">;
503
503
  type FloatingPanelGeometry = {
504
504
  x: number;
505
505
  y: number;
@@ -776,6 +776,7 @@ type InputProps =
776
776
  hasError?: boolean;
777
777
  radioVariant?: "list" | "card"; // `"card"` renders the radio group as bordered cards with label plus optional description per option and always uses the radio group, regardless of option count or `display`.
778
778
  display?: "radio" | "dropdown"; // Requested presentation.
779
+ optionTones?: Readonly<Partial<Record<string, SelectOptionTone>>>; // Tone per option value; the selected segment of a radio presentation takes its colors.
779
780
  }
780
781
  | ({ kind: "combobox"; id: string; name: string; options: { value: string; label: string; }[]; disabled?: boolean; required?: boolean; hasError?: boolean; placeholder?: string; searchPlaceholder?: string; emptyText?: string; onSearchChange?: (q: string) => void; loading?: boolean; onCreate?: () => void; createLabel?: string; } & ({ multiple?: false; value: string; onChange: (v: string) => void; } | { multiple: true; value: string[]; onChange: (v: string[]) => void; }))
781
782
  | {