0.1.2 #4

Merged
Thilawyn merged 57 commits from next into master 2025-02-26 19:27:39 +01:00
Showing only changes of commit 693c7b2db8 - Show all commits

View File

@@ -4,29 +4,9 @@ import * as ReffuseRuntime from "./ReffuseRuntime.js"
export class ReffuseContext<R> {
readonly Context = React.createContext<Context.Context<R>>(null!)
readonly Provider: ReffuseContextReactProvider<R>
constructor() {
// TODO: scope the layer creation
this.Provider = props => {
const runtime = ReffuseRuntime.useRuntime()
const value = React.useMemo(() => Effect.context<R>().pipe(
Effect.provide(props.layer),
Runtime.runSync(runtime),
), [props.layer, runtime])
return (
<this.Context
{...props}
value={value}
/>
)
}
this.Provider.displayName = "ReffuseContextReactProvider"
}
readonly Provider = makeProvider(this.Context)
readonly AsyncProvider = makeAsyncProvider(this.Context)
useContext(): Context.Context<R> {
@@ -37,15 +17,73 @@ export class ReffuseContext<R> {
const context = this.useContext()
return React.useMemo(() => Layer.effectContext(Effect.succeed(context)), [context])
}
}
export type ReffuseContextReactProvider<R> = React.FC<{
export type R<T> = T extends ReffuseContext<infer R> ? R : never
export type ReactProvider<R> = React.FC<{
readonly layer: Layer.Layer<R, unknown>
readonly children?: React.ReactNode
}>
export type R<T> = T extends ReffuseContext<infer R> ? R : never
function makeProvider<R>(Context: React.Context<Context.Context<R>>): ReactProvider<R> {
return function ReffuseContextReactProvider(props) {
const runtime = ReffuseRuntime.useRuntime()
const value = React.useMemo(() => Effect.context<R>().pipe(
Effect.provide(props.layer),
Runtime.runSync(runtime),
), [props.layer, runtime])
return (
<Context
{...props}
value={value}
/>
)
}
}
export type AsyncReactProvider<R> = React.FC<{
readonly layer: Layer.Layer<R, unknown>
readonly fallback?: React.ReactNode
readonly children?: React.ReactNode
}>
function makeAsyncProvider<R>(Context: React.Context<Context.Context<R>>): AsyncReactProvider<R> {
function Inner({ promise, children }: {
readonly promise: Promise<Context.Context<R>>
readonly children?: React.ReactNode
}) {
const value = React.use(promise)
return (
<Context
value={value}
children={children}
/>
)
}
return function ReffuseContextAsyncReactProvider(props) {
const runtime = ReffuseRuntime.useRuntime()
const promise = React.useMemo(() => Effect.context<R>().pipe(
Effect.provide(props.layer),
Runtime.runPromise(runtime),
), [props.layer, runtime])
return (
<React.Suspense fallback={props.fallback}>
<Inner
{...props}
promise={promise}
/>
</React.Suspense>
)
}
}
export function make<R = never>() {