0.2.2 #31

Merged
Thilawyn merged 184 commits from next into master 2026-01-16 17:05:31 +01:00
2 changed files with 21 additions and 32 deletions
Showing only changes of commit c1705c1587 - Show all commits

View File

@@ -1,4 +1,4 @@
import { Effect, Equivalence, type Scope, Stream, Subscribable } from "effect" import { Effect, Equivalence, Stream, Subscribable } from "effect"
import * as React from "react" import * as React from "react"
import * as Component from "./Component.js" import * as Component from "./Component.js"
@@ -16,7 +16,7 @@ export const zipLatestAll = <const T extends readonly Subscribable.Subscribable<
changes: Stream.zipLatestAll(...elements.map(v => v.changes)), changes: Stream.zipLatestAll(...elements.map(v => v.changes)),
}) as any }) as any
export namespace useSubscribables { export declare namespace useSubscribables {
export type Success<T extends readonly Subscribable.Subscribable<any, any, any>[]> = [T[number]] extends [never] export type Success<T extends readonly Subscribable.Subscribable<any, any, any>[]> = [T[number]] extends [never]
? never ? never
: { [K in keyof T]: T[K] extends Subscribable.Subscribable<infer A, infer _E, infer _R> ? A : never } : { [K in keyof T]: T[K] extends Subscribable.Subscribable<infer A, infer _E, infer _R> ? A : never }
@@ -26,19 +26,14 @@ export namespace useSubscribables {
} }
} }
export const useSubscribables: { export const useSubscribables = Effect.fnUntraced(function* <const T extends readonly Subscribable.Subscribable<any, any, any>[]>(
<const T extends readonly Subscribable.Subscribable<any, any, any>[]>(
elements: T,
options?: useSubscribables.Options<useSubscribables.Success<NoInfer<T>>>,
): Effect.Effect<
useSubscribables.Success<T>,
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer E, infer _R> ? E : never,
Scope.Scope | ([T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer _E, infer R> ? R : never)
>
} = Effect.fnUntraced(function* <const T extends readonly Subscribable.Subscribable<any, any, any>[]>(
elements: T, elements: T,
options?: useSubscribables.Options<useSubscribables.Success<NoInfer<T>>>, options?: useSubscribables.Options<useSubscribables.Success<NoInfer<T>>>,
) { ): Effect.fn.Return<
useSubscribables.Success<T>,
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer E, infer _R> ? E : never,
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer _E, infer R> ? R : never
> {
const [reactStateValue, setReactStateValue] = React.useState( const [reactStateValue, setReactStateValue] = React.useState(
yield* Component.useOnMount(() => Effect.all(elements.map(v => v.get))) yield* Component.useOnMount(() => Effect.all(elements.map(v => v.get)))
) )

View File

@@ -1,24 +1,19 @@
import { Effect, Equivalence, Ref, type Scope, Stream, SubscriptionRef } from "effect" import { Effect, Equivalence, Ref, Stream, SubscriptionRef } from "effect"
import * as React from "react" import * as React from "react"
import * as Component from "./Component.js" import * as Component from "./Component.js"
import * as SetStateAction from "./SetStateAction.js" import * as SetStateAction from "./SetStateAction.js"
export namespace useSubscriptionRefState { export declare namespace useSubscriptionRefState {
export interface Options<A> { export interface Options<A> {
readonly equivalence?: Equivalence.Equivalence<A> readonly equivalence?: Equivalence.Equivalence<A>
} }
} }
export const useSubscriptionRefState: { export const useSubscriptionRefState = Effect.fnUntraced(function* <A>(
<A>(
ref: SubscriptionRef.SubscriptionRef<A>,
options?: useSubscriptionRefState.Options<NoInfer<A>>,
): Effect.Effect<readonly [A, React.Dispatch<React.SetStateAction<A>>], never, Scope.Scope>
} = Effect.fnUntraced(function* <A>(
ref: SubscriptionRef.SubscriptionRef<A>, ref: SubscriptionRef.SubscriptionRef<A>,
options?: useSubscriptionRefState.Options<NoInfer<A>>, options?: useSubscriptionRefState.Options<NoInfer<A>>,
) { ): Effect.fn.Return<readonly [A, React.Dispatch<React.SetStateAction<A>>]> {
const [reactStateValue, setReactStateValue] = React.useState(yield* Component.useOnMount(() => ref)) const [reactStateValue, setReactStateValue] = React.useState(yield* Component.useOnMount(() => ref))
yield* Component.useReactEffect(() => Effect.forkScoped( yield* Component.useReactEffect(() => Effect.forkScoped(
@@ -28,28 +23,27 @@ export const useSubscriptionRefState: {
) )
), [ref]) ), [ref])
const setValue = yield* Component.useCallbackSync((setStateAction: React.SetStateAction<A>) => const setValue = yield* Component.useCallbackSync(
Effect.andThen( (setStateAction: React.SetStateAction<A>) => Effect.andThen(
Ref.updateAndGet(ref, prevState => SetStateAction.value(setStateAction, prevState)), Ref.updateAndGet(ref, prevState => SetStateAction.value(setStateAction, prevState)),
v => setReactStateValue(v), v => setReactStateValue(v),
), ),
[ref]) [ref],
)
return [reactStateValue, setValue] return [reactStateValue, setValue]
}) })
export namespace useSubscriptionRefFromState { export declare namespace useSubscriptionRefFromState {
export interface Options<A> { export interface Options<A> {
readonly equivalence?: Equivalence.Equivalence<A> readonly equivalence?: Equivalence.Equivalence<A>
} }
} }
export const useSubscriptionRefFromState: { export const useSubscriptionRefFromState = Effect.fnUntraced(function* <A>(
<A>( [value, setValue]: readonly [A, React.Dispatch<React.SetStateAction<A>>],
state: readonly [A, React.Dispatch<React.SetStateAction<A>>], options?: useSubscriptionRefFromState.Options<NoInfer<A>>,
options?: useSubscriptionRefFromState.Options<NoInfer<A>>, ): Effect.fn.Return<SubscriptionRef.SubscriptionRef<A>> {
): Effect.Effect<SubscriptionRef.SubscriptionRef<A>, never, Scope.Scope>
} = Effect.fnUntraced(function*([value, setValue], options) {
const ref = yield* Component.useOnChange(() => Effect.tap( const ref = yield* Component.useOnChange(() => Effect.tap(
SubscriptionRef.make(value), SubscriptionRef.make(value),
ref => Effect.forkScoped( ref => Effect.forkScoped(