0.1.4 #5

Merged
Thilawyn merged 67 commits from next into master 2025-10-02 18:18:23 +02:00
2 changed files with 15 additions and 14 deletions
Showing only changes of commit 46ef35040a - Show all commits

View File

@@ -70,8 +70,7 @@ export const make: {
export namespace useInput { export namespace useInput {
export interface Options<I, P extends PropertyPath.Paths<I>> { export interface Options {
readonly path: P
readonly debounce?: Duration.DurationInput readonly debounce?: Duration.DurationInput
} }
@@ -83,21 +82,23 @@ export namespace useInput {
} }
export const useInput: { export const useInput: {
<A, I, R, P extends PropertyPath.Paths<I>>( <A, I, R, const P extends PropertyPath.Paths<I>>(
self: Form<A, I, R>, self: Form<A, I, R>,
options: useInput.Options<NoInfer<I>, P>, path: P,
options?: useInput.Options,
): Effect.Effect<useInput.Result<PropertyPath.ValueFromPath<I, P>>, NoSuchElementException, R> ): Effect.Effect<useInput.Result<PropertyPath.ValueFromPath<I, P>>, NoSuchElementException, R>
} = Effect.fnUntraced(function* <A, I, R, P extends PropertyPath.Paths<I>>( } = Effect.fnUntraced(function* <A, I, R, const P extends PropertyPath.Paths<I>>(
self: Form<A, I, R>, self: Form<A, I, R>,
options: useInput.Options<NoInfer<I>, P>, path: P,
options?: useInput.Options,
) { ) {
const [internalValueRef, issuesSubscribable] = yield* Hooks.useMemo(() => Effect.all([ const [internalValueRef, issuesSubscribable] = yield* Hooks.useMemo(() => Effect.all([
self.encodedValueRef.pipe( self.encodedValueRef.pipe(
Effect.andThen(PropertyPath.get(options.path)), Effect.andThen(PropertyPath.get(path)),
Effect.andThen(SubscriptionRef.make<PropertyPath.ValueFromPath<I, P>>), Effect.andThen(SubscriptionRef.make<PropertyPath.ValueFromPath<I, P>>),
), ),
Effect.succeed(self.makeFieldIssuesSubscribable(options.path)), Effect.succeed(self.makeFieldIssuesSubscribable(path)),
]), [self, ...options.path]) ]), [self, ...path])
const [value, setValue] = yield* Hooks.useRefState(internalValueRef) const [value, setValue] = yield* Hooks.useRefState(internalValueRef)
const [issues] = yield* Hooks.useSubscribe(issuesSubscribable) const [issues] = yield* Hooks.useSubscribe(issuesSubscribable)
@@ -105,12 +106,12 @@ export const useInput: {
yield* Hooks.useFork(() => Stream.runForEach( yield* Hooks.useFork(() => Stream.runForEach(
internalValueRef.changes.pipe( internalValueRef.changes.pipe(
Stream.changesWith(Equivalence.strict()), Stream.changesWith(Equivalence.strict()),
options.debounce ? Stream.debounce(options.debounce) : identity, options?.debounce ? Stream.debounce(options.debounce) : identity,
Stream.drop(1), Stream.drop(1),
), ),
internalValue => self.encodedValueRef.pipe( internalValue => self.encodedValueRef.pipe(
Effect.andThen(encodedValue => PropertyPath.immutableSet(encodedValue, options.path, internalValue)), Effect.andThen(encodedValue => PropertyPath.immutableSet(encodedValue, path, internalValue)),
Effect.tap(encodedValue => SubscriptionRef.set(self.encodedValueRef, encodedValue)), Effect.tap(encodedValue => SubscriptionRef.set(self.encodedValueRef, encodedValue)),
Effect.andThen(flow( Effect.andThen(flow(
Schema.decode(self.schema), Schema.decode(self.schema),
@@ -119,7 +120,7 @@ export const useInput: {
Effect.catchTag("ParseError", e => SubscriptionRef.set(self.errorRef, Option.some(e))) Effect.catchTag("ParseError", e => SubscriptionRef.set(self.errorRef, Option.some(e)))
)), )),
), ),
), [internalValueRef, self, ...options.path]) ), [internalValueRef, self, ...path])
return { value, setValue, issues } return { value, setValue, issues }
}) })

View File

@@ -20,8 +20,8 @@ class RegisterForm extends Effect.Service<RegisterForm>()("RegisterForm", {
class RegisterPage extends Component.makeUntraced(function* RegisterPage() { class RegisterPage extends Component.makeUntraced(function* RegisterPage() {
const form = yield* RegisterForm const form = yield* RegisterForm
const emailInput = yield* Form.useInput(form, { path: ["email"] }) const emailInput = yield* Form.useInput(form, ["email"])
const passwordInput = yield* Form.useInput(form, { path: ["password"] }) const passwordInput = yield* Form.useInput(form, ["password"])
yield* useFork(() => Stream.runForEach(form.valueRef.changes, Console.log), []) yield* useFork(() => Stream.runForEach(form.valueRef.changes, Console.log), [])