From 075e92cb66667f992f6c418f8262ef5b158531bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 30 Mar 2026 14:20:25 +0200 Subject: [PATCH] Refactor Form --- bun.lock | 4 ++-- packages/effect-fc/package.json | 2 +- packages/effect-fc/src/Form.ts | 29 ++++++++++++++++++++++++-- packages/effect-fc/src/Subscribable.ts | 5 +++-- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/bun.lock b/bun.lock index eef3d3c..a273547 100644 --- a/bun.lock +++ b/bun.lock @@ -37,7 +37,7 @@ "name": "effect-fc", "version": "0.2.4", "dependencies": { - "effect-lens": "^0.1.3", + "effect-lens": "^0.1.4", }, "devDependencies": { "@effect/platform-browser": "^0.76.0", @@ -1380,7 +1380,7 @@ "effect-fc": ["effect-fc@workspace:packages/effect-fc"], - "effect-lens": ["effect-lens@0.1.3", "", { "peerDependencies": { "effect": "^3.21.0" } }, "sha512-LtGugMzJehYlQfD9GAbvAOFolVj6UOokqA2EI3M43GC2+wqTDloQjyiW3hrpH3UlayDor7Yg1ZG05Do5a0knsA=="], + "effect-lens": ["effect-lens@0.1.4", "", { "peerDependencies": { "effect": "^3.21.0" } }, "sha512-jq/yWuUQcF0tKYsWPPXc0GMtanR1wFo8SGLCI+9nFmDPBJsDmLZDjVj0n15P94om5vfGNOBWtmszqMV1NliYmw=="], "electron-to-chromium": ["electron-to-chromium@1.5.313", "", {}, "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA=="], diff --git a/packages/effect-fc/package.json b/packages/effect-fc/package.json index fee8cb4..ea76d45 100644 --- a/packages/effect-fc/package.json +++ b/packages/effect-fc/package.json @@ -46,6 +46,6 @@ "react": "^19.2.0" }, "dependencies": { - "effect-lens": "^0.1.3" + "effect-lens": "^0.1.4" } } diff --git a/packages/effect-fc/src/Form.ts b/packages/effect-fc/src/Form.ts index 2125cfa..b05e80e 100644 --- a/packages/effect-fc/src/Form.ts +++ b/packages/effect-fc/src/Form.ts @@ -233,6 +233,14 @@ export const service = Effect.forkScoped(form.run), ) + +const filterIssuesByPath = ( + issues: readonly ParseResult.ArrayFormatterIssue[], + path: readonly PropertyKey[], +): readonly ParseResult.ArrayFormatterIssue[] => Array.filter(issues, issue => + issue.path.length >= path.length && Array.every(path, (p, i) => p === issue.path[i]) +) + export const focusObjectField =

( self: Form, key: K, @@ -242,9 +250,26 @@ export const focusObjectField =

a[key])), + Subscribable.mapOption(form.value, a => a[key]), Lens.focusObjectField(form.encodedValue, key), - Subscribable.map(form.issues, issues => Array.filter(issues, issue => issue.path.length >= path.length && Array.every(path, (p, i) => p === issue.path[i]))), + Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)), + form.isValidating, + form.canSubmit, + ) +} + +export const focusArrayAt =

( + self: Form, + index: number, +): Form => { + const form = self as FormImpl + const path = [...form.path, index] as const + + return new FormImpl( + path, + Subscribable.mapOptionEffect(form.value, Array.get(index)), + Lens.focusArrayAt(form.encodedValue, index), + Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)), form.isValidating, form.canSubmit, ) diff --git a/packages/effect-fc/src/Subscribable.ts b/packages/effect-fc/src/Subscribable.ts index 67e60ad..c79ba93 100644 --- a/packages/effect-fc/src/Subscribable.ts +++ b/packages/effect-fc/src/Subscribable.ts @@ -1,9 +1,10 @@ -import { Effect, Equivalence, Stream, Subscribable } from "effect" +import { Effect, Equivalence, Stream } from "effect" +import { Subscribable } from "effect-lens" import * as React from "react" import * as Component from "./Component.js" -export * from "effect/Subscribable" +export * from "effect-lens/Subscribable" export const zipLatestAll = []>( ...elements: T