diff --git a/javascript/packages/client/src/actions/actions.ts b/javascript/packages/client/src/actions/actions.ts index 8159e8ed8..19f236e42 100644 --- a/javascript/packages/client/src/actions/actions.ts +++ b/javascript/packages/client/src/actions/actions.ts @@ -466,9 +466,27 @@ export class Actions implements ElementObserverDelegate, InstructionsDelegate { return null } + if (kind === "seeded") { + return { value: this.seededLiteral(name, scope, raw) } + } + return { value: coerceState(raw, kind) } } + private seededLiteral(name: string, scope: StateScope, raw: string): StateValue { + const current = this.state.getState(name, { scope }) + + if (typeof current === "number" && /^-?\d+$/.test(raw)) { + return Number(raw) + } + + if (typeof current === "boolean" && (raw === "true" || raw === "false")) { + return raw === "true" + } + + return raw + } + private toggle(element: Element, rest: string): void { const groups: StateGroups = new Map() diff --git a/javascript/packages/client/test/actions.test.ts b/javascript/packages/client/test/actions.test.ts index 7d9ed0e00..9bf2ca239 100644 --- a/javascript/packages/client/test/actions.test.ts +++ b/javascript/packages/client/test/actions.test.ts @@ -28,6 +28,7 @@ const PAGE = `` + `` + `` + + `` + `` + `` + `
closed
` + @@ -55,6 +56,7 @@ const PAGE = { name: "failed", kind: "boolean", default: "false", scope: "region" }, { name: "attempts", kind: "integer", default: "0", scope: "region" }, { name: "sort", kind: "string", default: '"name"', scope: "region" }, + { name: "page", kind: "seeded", default: "params.fetch(:page, 1).to_i", scope: "region" }, { name: "starred", kind: "boolean", default: "false", scope: 2 }, ], reads: { attempts: [1], sort: [5] }, @@ -102,6 +104,18 @@ describe("declarative actions", () => { expect(state.getState("open")).toBe(false) }) + test("a literal assigned to a seeded state takes the type of the value it holds", () => { + state.setState({ page: 3 }) + click("#page-reset") + + expect(state.getState("page")).toBe(1) + + state.setState({ page: "three" }) + click("#page-reset") + + expect(state.getState("page")).toBe("1") + }) + test("two clauses on one attribute both write", () => { const order: string[] = [] const handler = (event: Event): void => {