0.2.1 #26

Merged
Thilawyn merged 144 commits from next into master 2025-12-01 23:37:40 +01:00
5 changed files with 25 additions and 34 deletions
Showing only changes of commit 6f96608f64 - Show all commits

View File

@@ -105,7 +105,7 @@ export const make: {
export const run = <A, I, R, SA, SE, SR>(
self: Form<A, I, R, SA, SE, SR>
): Effect.Effect<void, never, Scope.Scope | R> => Stream.runForEach(
): Effect.Effect<void, never, Scope.Scope | R | SR> => Stream.runForEach(
self.encodedValueRef.changes.pipe(
Option.isSome(self.debounce) ? Stream.debounce(self.debounce.value) : identity
),
@@ -125,21 +125,22 @@ export const run = <A, I, R, SA, SE, SR>(
Effect.andThen(SubscriptionRef.set(self.errorRef, Option.none())),
Effect.as(Option.some(v)),
),
onFailure: c => Option.match(
Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError"),
{
onSome: e => Effect.as(SubscriptionRef.set(self.errorRef, Option.some(e)), Option.none()),
onNone: () => Effect.succeed(Option.none()),
},
onFailure: c => Chunk.findFirst(Cause.failures(c), e => e._tag === "ParseError").pipe(
Option.match({
onSome: e => SubscriptionRef.set(self.errorRef, Option.some(e)),
onNone: () => Effect.void,
}),
Effect.as(Option.none<A>()),
),
}),
Effect.uninterruptible,
)),
Effect.scoped,
Effect.andThen(value => Option.isSome(value) && self.autosubmit
?
? Effect.asVoid(Effect.forkScoped(submit(self)))
: Effect.void
),
Effect.scoped,
Effect.forkScoped,
)
),
@@ -175,7 +176,7 @@ export namespace service {
export const service = <A, I = A, R = never, SA = void, SE = A, SR = never>(
options: service.Options<A, I, R, SA, SE, SR>
): Effect.Effect<Form<A, I, R, SA, SE, SR>, never, Scope.Scope | R> => Effect.tap(
): Effect.Effect<Form<A, I, R, SA, SE, SR>, never, Scope.Scope | R | SR> => Effect.tap(
make(options),
form => Effect.forkScoped(run(form)),
)

View File

@@ -2,7 +2,7 @@ import { Flex, Text, TextField } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router"
import { GetRandomValues, makeUuid4 } from "@typed/id"
import { Effect } from "effect"
import { Async, Component, Hooks, Memoized } from "effect-fc"
import { Async, Component, Memoized } from "effect-fc"
import * as React from "react"
import { runtime } from "@/runtime"
@@ -69,7 +69,7 @@ class AsyncComponent extends Component.makeUntraced("AsyncComponent")(function*(
class MemoizedAsyncComponent extends Memoized.memoized(AsyncComponent) {}
class SubComponent extends Component.makeUntraced("SubComponent")(function*() {
const [state] = React.useState(yield* Hooks.useOnce(() => Effect.provide(makeUuid4, GetRandomValues.CryptoRandom)))
const [state] = React.useState(yield* Component.useOnMount(() => Effect.provide(makeUuid4, GetRandomValues.CryptoRandom)))
return <Text>{state}</Text>
}) {}

View File

@@ -1,7 +1,7 @@
import { Button, Container, Flex } from "@radix-ui/themes"
import { createFileRoute } from "@tanstack/react-router"
import { Console, Effect, Option, ParseResult, Schema } from "effect"
import { Component, Form, Hooks } from "effect-fc"
import { Component, Form, Subscribable } from "effect-fc"
import { TextFieldFormInput } from "@/lib/form/TextFieldFormInput"
import { DateTimeUtcFromZonedInput } from "@/lib/schema"
import { runtime } from "@/runtime"
@@ -50,7 +50,7 @@ class RegisterForm extends Effect.Service<RegisterForm>()("RegisterForm", {
class RegisterFormView extends Component.makeUntraced("RegisterFormView")(function*() {
const form = yield* RegisterForm
const submit = yield* Form.useSubmit(form)
const [canSubmit] = yield* Hooks.useSubscribables(form.canSubmitSubscribable)
const [canSubmit] = yield* Subscribable.useSubscribables(form.canSubmitSubscribable)
const TextFieldFormInputFC = yield* TextFieldFormInput
@@ -87,7 +87,7 @@ class RegisterFormView extends Component.makeUntraced("RegisterFormView")(functi
const RegisterPage = Component.makeUntraced("RegisterPage")(function*() {
const RegisterFormViewFC = yield* Effect.provide(
RegisterFormView,
yield* Hooks.useContext(RegisterForm.Default, { finalizerExecutionMode: "fork" }),
yield* Component.useContext(RegisterForm.Default, { finalizerExecutionMode: "fork" }),
)
return <RegisterFormViewFC />

View File

@@ -1,6 +1,6 @@
import { createFileRoute } from "@tanstack/react-router"
import { Effect } from "effect"
import { Component, Hooks } from "effect-fc"
import { Component } from "effect-fc"
import { runtime } from "@/runtime"
import { Todos } from "@/todo/Todos"
import { TodosState } from "@/todo/TodosState.service"
@@ -11,7 +11,7 @@ const TodosStateLive = TodosState.Default("todos")
const Index = Component.makeUntraced("Index")(function*() {
const TodosFC = yield* Effect.provide(
Todos,
yield* Hooks.useContext(TodosStateLive, { finalizerExecutionMode: "fork" }),
yield* Component.useContext(TodosStateLive, { finalizerExecutionMode: "fork" }),
)
return <TodosFC />

View File

@@ -1,7 +1,7 @@
import { Box, Button, Flex, IconButton } from "@radix-ui/themes"
import { GetRandomValues, makeUuid4 } from "@typed/id"
import { Chunk, DateTime, Effect, Match, Option, Ref, Runtime, Schema, Stream, SubscriptionRef } from "effect"
import { Component, Form, Hooks, Memoized, Subscribable, SubscriptionSubRef } from "effect-fc"
import { Chunk, Effect, Match, Option, Ref, Runtime, Schema, Stream } from "effect"
import { Component, Form, Subscribable } from "effect-fc"
import { FaArrowDown, FaArrowUp } from "react-icons/fa"
import { FaDeleteLeft } from "react-icons/fa6"
import * as Domain from "@/domain"
@@ -61,6 +61,7 @@ export class Todo extends Component.makeUntraced("Todo")(function*(props: TodoPr
Match.exhaustive,
)
},
autosubmit: props._tag === "edit",
})
return [
@@ -71,7 +72,7 @@ export class Todo extends Component.makeUntraced("Todo")(function*(props: TodoPr
] as const
}), [props._tag, props._tag === "edit" ? props.id : undefined])
const [index, size] = yield* Hooks.useSubscribables(indexRef, state.sizeSubscribable)
const [index, size] = yield* Subscribable.useSubscribables(indexRef, state.sizeSubscribable)
const submit = yield* Form.useSubmit(form)
const TextFieldFormInputFC = yield* TextFieldFormInput
@@ -80,9 +81,7 @@ export class Todo extends Component.makeUntraced("Todo")(function*(props: TodoPr
<Flex direction="row" align="center" gap="2">
<Box flexGrow="1">
<Flex direction="column" align="stretch" gap="2">
<TextFieldFormInputFC
field={contentField}
/>
<TextFieldFormInputFC field={contentField} />
<Flex direction="row" justify="center" align="center" gap="2">
<TextFieldFormInputFC
@@ -93,14 +92,7 @@ export class Todo extends Component.makeUntraced("Todo")(function*(props: TodoPr
/>
{props._tag === "new" &&
<Button
onClick={() => ref.pipe(
Effect.andThen(todo => Ref.update(state.ref, Chunk.prepend(todo))),
Effect.andThen(makeTodo),
Effect.andThen(todo => Ref.set(ref, todo)),
Runtime.runSync(runtime),
)}
>
<Button onClick={() => submit()}>
Add
</Button>
}
@@ -131,6 +123,4 @@ export class Todo extends Component.makeUntraced("Todo")(function*(props: TodoPr
}
</Flex>
)
}).pipe(
Memoized.memoized
) {}
}) {}