feat: use template/module config variable's default value as its field placeholder if present

This commit is contained in:
Andrew Aquino
2026-06-27 01:14:48 +00:00
parent efd93027ce
commit 599b607194
4 changed files with 58 additions and 2 deletions
@@ -11,6 +11,7 @@ import {
TemplateBuilderTitle,
} from "#/pages/TemplateBuilder/TemplateBuilderHeader";
import type { ConfigurationFieldDefinition } from "./ConfigurationField";
import { defaultPlaceholder } from "./defaultPlaceholder";
import { TemplateConfiguration } from "./TemplateConfiguration";
interface BaseTemplateParametersStepProps {
@@ -53,7 +54,9 @@ function variableToField(
label: variable.name,
description: variable.description || undefined,
required: variable.required,
placeholder: variable.required ? "Required" : "Optional",
placeholder:
defaultPlaceholder(variable.default) ??
(variable.required ? "Required" : "Optional"),
field: {
name: variable.name,
id,
@@ -12,6 +12,7 @@ import {
TemplateBuilderTitle,
} from "#/pages/TemplateBuilder/TemplateBuilderHeader";
import type { ConfigurationFieldDefinition } from "./ConfigurationField";
import { defaultPlaceholder } from "./defaultPlaceholder";
import { ModuleConfiguration } from "./ModuleConfiguration";
interface ModuleSettingsStepProps {
@@ -51,7 +52,9 @@ function variableToField(
label: variable.name,
description: variable.description || undefined,
required: variable.required,
placeholder: variable.required ? "Required" : "Optional",
placeholder:
defaultPlaceholder(variable.default) ??
(variable.required ? "Required" : "Optional"),
field: {
name: variable.name,
id,
@@ -0,0 +1,28 @@
import { defaultPlaceholder } from "./defaultPlaceholder";
describe("defaultPlaceholder", () => {
it("formats numeric defaults, including zero", () => {
expect(defaultPlaceholder(13337)).toBe("13337");
expect(defaultPlaceholder(0)).toBe("0");
});
it("formats boolean defaults", () => {
expect(defaultPlaceholder(false)).toBe("false");
expect(defaultPlaceholder(true)).toBe("true");
});
it("returns non-empty string defaults unchanged", () => {
expect(defaultPlaceholder("v0.10.0")).toBe("v0.10.0");
});
it("returns undefined for empty or absent defaults", () => {
expect(defaultPlaceholder("")).toBeUndefined();
expect(defaultPlaceholder(undefined)).toBeUndefined();
expect(defaultPlaceholder(null)).toBeUndefined();
});
it("returns undefined for object and array defaults", () => {
expect(defaultPlaceholder({ key: "value" })).toBeUndefined();
expect(defaultPlaceholder(["a", "b"])).toBeUndefined();
});
});
@@ -0,0 +1,22 @@
/**
* Coerces a module variable's `default` into placeholder text.
*
* `TemplateBuilderModuleVariable.default` is generated as
* `Record<string, string>` because every `json.RawMessage` field maps to that
* type, but the actual wire value is a JSON scalar (string, number, or
* boolean). The parameter is typed `unknown` so the generated value is accepted
* without a cast.
*
* An empty-string default returns `undefined` so callers fall back to their
* existing Required/Optional hint. Object or array defaults also return
* `undefined` since they have no meaningful placeholder representation.
*/
export function defaultPlaceholder(value: unknown): string | undefined {
if (typeof value === "number" || typeof value === "boolean") {
return String(value);
}
if (typeof value === "string" && value !== "") {
return value;
}
return undefined;
}