web+tui: honor enumNames in enum forms (#1750)
* web+tui: honor enumNames in enum forms (#1691) Legacy titled enums (`enum` + non-standard `enumNames`) rendered their raw wire values instead of the human-readable titles in both the web SchemaForm and the TUI schemaToForm builder, so a user picking "pet-1" had no idea it meant "Cats". Web (SchemaForm.tsx): extract a `toEnumData` helper that zips `enum` with `enumNames` into `{ value, label }[]` when the lengths match, falling back to bare values otherwise. Use it in both the string-enum and array multi-select branches (the latter previously inlined the same zip). TUI (schemaToForm.ts): add `enumNames` / `items.enumNames` to the property interface and a `toSelectOptions` helper used by the single-select and array-of-enum branches, labeling by `enumNames[i]` when length-matched and falling back to `String(val)`. Both guard on the arrays being the same length: a wrong-length zip would mislabel options, which is worse than showing raw values. Raw values are always submitted; only the display label changes. Closes #1691 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * docs(pr-screenshots): TUI enumNames before/after proof shots (#1691) Before/after captures of the TUI tool-test form (schemaToForm -> ink-form) against a legacy titled enum: with the fix the field resolves pet-1 -> "Cats"; before, it showed the raw "pet-1". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
402d7b204d
commit
8c41dcd383
1 changed files with 240 additions and 19 deletions
|
|
@ -9,12 +9,31 @@ interface JsonSchemaProperty {
|
|||
type?: string;
|
||||
title?: string;
|
||||
enum?: unknown[];
|
||||
items?: { enum?: unknown[] };
|
||||
/** Non-standard legacy support: titles for enum values */
|
||||
enumNames?: string[];
|
||||
items?: { enum?: unknown[]; enumNames?: string[] };
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
default?: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build ink-form select options from enum values, using their non-standard
|
||||
* `enumNames` titles as labels when present and length-matched. Falls back to
|
||||
* the stringified value as the label otherwise, since a wrong-length zip would
|
||||
* mislabel options — worse than showing raw values.
|
||||
*/
|
||||
function toSelectOptions(
|
||||
values: unknown[],
|
||||
names: string[] | undefined,
|
||||
): { label: string; value: string }[] {
|
||||
const useNames = names !== undefined && names.length === values.length;
|
||||
return values.map((val, index) => ({
|
||||
label: useNames ? names[index] : String(val),
|
||||
value: String(val),
|
||||
}));
|
||||
}
|
||||
|
||||
/** Minimal JSON Schema object shape (properties + required) */
|
||||
interface JsonSchemaObject {
|
||||
properties?: Record<string, JsonSchemaProperty>;
|
||||
|
|
@ -58,20 +77,17 @@ export function schemaToForm(
|
|||
field = {
|
||||
type: "select",
|
||||
...baseField,
|
||||
options: property.items.enum.map((val: unknown) => ({
|
||||
label: String(val),
|
||||
value: String(val),
|
||||
})),
|
||||
options: toSelectOptions(
|
||||
property.items.enum,
|
||||
property.items.enumNames,
|
||||
),
|
||||
} as FormField;
|
||||
} else {
|
||||
// Single select
|
||||
field = {
|
||||
type: "select",
|
||||
...baseField,
|
||||
options: property.enum.map((val: unknown) => ({
|
||||
label: String(val),
|
||||
value: String(val),
|
||||
})),
|
||||
options: toSelectOptions(property.enum, property.enumNames),
|
||||
} as FormField;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue