Form tests
All checks were successful
Lint / lint (push) Successful in 11s

This commit is contained in:
Julien Valverdé
2025-08-27 05:40:39 +02:00
parent ecc37515b8
commit 64114f0208
2 changed files with 84 additions and 1 deletions

View File

@@ -9,12 +9,18 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root' import { Route as rootRouteImport } from './routes/__root'
import { Route as FormRouteImport } from './routes/form'
import { Route as BlankRouteImport } from './routes/blank' import { Route as BlankRouteImport } from './routes/blank'
import { Route as IndexRouteImport } from './routes/index' import { Route as IndexRouteImport } from './routes/index'
import { Route as DevMemoRouteImport } from './routes/dev/memo' import { Route as DevMemoRouteImport } from './routes/dev/memo'
import { Route as DevInputRouteImport } from './routes/dev/input' import { Route as DevInputRouteImport } from './routes/dev/input'
import { Route as DevAsyncRenderingRouteImport } from './routes/dev/async-rendering' import { Route as DevAsyncRenderingRouteImport } from './routes/dev/async-rendering'
const FormRoute = FormRouteImport.update({
id: '/form',
path: '/form',
getParentRoute: () => rootRouteImport,
} as any)
const BlankRoute = BlankRouteImport.update({ const BlankRoute = BlankRouteImport.update({
id: '/blank', id: '/blank',
path: '/blank', path: '/blank',
@@ -44,6 +50,7 @@ const DevAsyncRenderingRoute = DevAsyncRenderingRouteImport.update({
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof IndexRoute '/': typeof IndexRoute
'/blank': typeof BlankRoute '/blank': typeof BlankRoute
'/form': typeof FormRoute
'/dev/async-rendering': typeof DevAsyncRenderingRoute '/dev/async-rendering': typeof DevAsyncRenderingRoute
'/dev/input': typeof DevInputRoute '/dev/input': typeof DevInputRoute
'/dev/memo': typeof DevMemoRoute '/dev/memo': typeof DevMemoRoute
@@ -51,6 +58,7 @@ export interface FileRoutesByFullPath {
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/': typeof IndexRoute '/': typeof IndexRoute
'/blank': typeof BlankRoute '/blank': typeof BlankRoute
'/form': typeof FormRoute
'/dev/async-rendering': typeof DevAsyncRenderingRoute '/dev/async-rendering': typeof DevAsyncRenderingRoute
'/dev/input': typeof DevInputRoute '/dev/input': typeof DevInputRoute
'/dev/memo': typeof DevMemoRoute '/dev/memo': typeof DevMemoRoute
@@ -59,6 +67,7 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport __root__: typeof rootRouteImport
'/': typeof IndexRoute '/': typeof IndexRoute
'/blank': typeof BlankRoute '/blank': typeof BlankRoute
'/form': typeof FormRoute
'/dev/async-rendering': typeof DevAsyncRenderingRoute '/dev/async-rendering': typeof DevAsyncRenderingRoute
'/dev/input': typeof DevInputRoute '/dev/input': typeof DevInputRoute
'/dev/memo': typeof DevMemoRoute '/dev/memo': typeof DevMemoRoute
@@ -68,15 +77,23 @@ export interface FileRouteTypes {
fullPaths: fullPaths:
| '/' | '/'
| '/blank' | '/blank'
| '/form'
| '/dev/async-rendering' | '/dev/async-rendering'
| '/dev/input' | '/dev/input'
| '/dev/memo' | '/dev/memo'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: '/' | '/blank' | '/dev/async-rendering' | '/dev/input' | '/dev/memo' to:
| '/'
| '/blank'
| '/form'
| '/dev/async-rendering'
| '/dev/input'
| '/dev/memo'
id: id:
| '__root__' | '__root__'
| '/' | '/'
| '/blank' | '/blank'
| '/form'
| '/dev/async-rendering' | '/dev/async-rendering'
| '/dev/input' | '/dev/input'
| '/dev/memo' | '/dev/memo'
@@ -85,6 +102,7 @@ export interface FileRouteTypes {
export interface RootRouteChildren { export interface RootRouteChildren {
IndexRoute: typeof IndexRoute IndexRoute: typeof IndexRoute
BlankRoute: typeof BlankRoute BlankRoute: typeof BlankRoute
FormRoute: typeof FormRoute
DevAsyncRenderingRoute: typeof DevAsyncRenderingRoute DevAsyncRenderingRoute: typeof DevAsyncRenderingRoute
DevInputRoute: typeof DevInputRoute DevInputRoute: typeof DevInputRoute
DevMemoRoute: typeof DevMemoRoute DevMemoRoute: typeof DevMemoRoute
@@ -92,6 +110,13 @@ export interface RootRouteChildren {
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
interface FileRoutesByPath { interface FileRoutesByPath {
'/form': {
id: '/form'
path: '/form'
fullPath: '/form'
preLoaderRoute: typeof FormRouteImport
parentRoute: typeof rootRouteImport
}
'/blank': { '/blank': {
id: '/blank' id: '/blank'
path: '/blank' path: '/blank'
@@ -133,6 +158,7 @@ declare module '@tanstack/react-router' {
const rootRouteChildren: RootRouteChildren = { const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute, IndexRoute: IndexRoute,
BlankRoute: BlankRoute, BlankRoute: BlankRoute,
FormRoute: FormRoute,
DevAsyncRenderingRoute: DevAsyncRenderingRoute, DevAsyncRenderingRoute: DevAsyncRenderingRoute,
DevInputRoute: DevInputRoute, DevInputRoute: DevInputRoute,
DevMemoRoute: DevMemoRoute, DevMemoRoute: DevMemoRoute,

View File

@@ -0,0 +1,57 @@
import { runtime } from "@/runtime"
import { Container, Flex, TextField } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router"
import { Console, Effect, Schema, Stream } from "effect"
import { Component, Form } from "effect-fc"
import { useContext, useFork } from "effect-fc/hooks"
const LoginFormSchema = Schema.Struct({
email: Schema.String,
password: Schema.String,
})
class LoginForm extends Effect.Service<LoginForm>()("LoginForm", {
scoped: Form.make({
schema: LoginFormSchema,
initialValue: { email: "", password: "" },
})
}) {}
class LoginFormComponent extends Component.makeUntraced(function* LoginFormComponent() {
const form = yield* LoginForm
const emailInput = yield* form.useInput(["email"])
const passwordInput = yield* form.useInput(["password"])
yield* useFork(() => Stream.runForEach(form.latestValueSubscribable.changes, Console.log))
return (
<Container>
<Flex direction="column" gap="2">
<TextField.Root
value={emailInput.value}
onChange={e => emailInput.setValue(e.target.value)}
/>
<TextField.Root
value={passwordInput.value}
onChange={e => passwordInput.setValue(e.target.value)}
/>
</Flex>
</Container>
)
}) {}
const FormRoute = Component.makeUntraced(function* FormRoute() {
const context = yield* useContext(LoginForm.Default)
const LoginFormComponentFC = yield* Effect.provide(LoginFormComponent, context)
return <LoginFormComponentFC />
}).pipe(
Component.withRuntime(runtime.context)
)
export const Route = createFileRoute("/form")({
component: FormRoute
})