diff --git a/packages/example/package.json b/packages/example/package.json
index 24c7735..e1a234e 100644
--- a/packages/example/package.json
+++ b/packages/example/package.json
@@ -32,6 +32,7 @@
"@effect/platform": "^0.77.2",
"@effect/platform-browser": "^0.56.2",
"@radix-ui/themes": "^3.2.0",
+ "@reffuse/extension-lazyref": "workspace:*",
"@typed/id": "^0.17.1",
"@typed/lazy-ref": "^0.3.3",
"effect": "^3.13.2",
diff --git a/packages/example/src/reffuse.ts b/packages/example/src/reffuse.ts
index ac2e2b8..0aefd92 100644
--- a/packages/example/src/reffuse.ts
+++ b/packages/example/src/reffuse.ts
@@ -1,5 +1,6 @@
import { HttpClient } from "@effect/platform"
import { Clipboard, Geolocation, Permissions } from "@effect/platform-browser"
+import { LazyRefExtension } from "@reffuse/extension-lazyref"
import { Reffuse, ReffuseContext } from "reffuse"
@@ -11,7 +12,8 @@ export const GlobalContext = ReffuseContext.make<
>()
export class GlobalReffuse extends Reffuse.Reffuse.pipe(
- Reffuse.withContexts(GlobalContext)
+ Reffuse.withExtension(LazyRefExtension),
+ Reffuse.withContexts(GlobalContext),
) {}
export const R = new GlobalReffuse()
diff --git a/packages/example/src/routeTree.gen.ts b/packages/example/src/routeTree.gen.ts
index b1e3d9c..98b4224 100644
--- a/packages/example/src/routeTree.gen.ts
+++ b/packages/example/src/routeTree.gen.ts
@@ -14,6 +14,7 @@ import { Route as rootRoute } from './routes/__root'
import { Route as TimeImport } from './routes/time'
import { Route as TestsImport } from './routes/tests'
import { Route as PromiseImport } from './routes/promise'
+import { Route as LazyrefImport } from './routes/lazyref'
import { Route as CountImport } from './routes/count'
import { Route as BlankImport } from './routes/blank'
import { Route as IndexImport } from './routes/index'
@@ -38,6 +39,12 @@ const PromiseRoute = PromiseImport.update({
getParentRoute: () => rootRoute,
} as any)
+const LazyrefRoute = LazyrefImport.update({
+ id: '/lazyref',
+ path: '/lazyref',
+ getParentRoute: () => rootRoute,
+} as any)
+
const CountRoute = CountImport.update({
id: '/count',
path: '/count',
@@ -81,6 +88,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof CountImport
parentRoute: typeof rootRoute
}
+ '/lazyref': {
+ id: '/lazyref'
+ path: '/lazyref'
+ fullPath: '/lazyref'
+ preLoaderRoute: typeof LazyrefImport
+ parentRoute: typeof rootRoute
+ }
'/promise': {
id: '/promise'
path: '/promise'
@@ -111,6 +125,7 @@ export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/blank': typeof BlankRoute
'/count': typeof CountRoute
+ '/lazyref': typeof LazyrefRoute
'/promise': typeof PromiseRoute
'/tests': typeof TestsRoute
'/time': typeof TimeRoute
@@ -120,6 +135,7 @@ export interface FileRoutesByTo {
'/': typeof IndexRoute
'/blank': typeof BlankRoute
'/count': typeof CountRoute
+ '/lazyref': typeof LazyrefRoute
'/promise': typeof PromiseRoute
'/tests': typeof TestsRoute
'/time': typeof TimeRoute
@@ -130,6 +146,7 @@ export interface FileRoutesById {
'/': typeof IndexRoute
'/blank': typeof BlankRoute
'/count': typeof CountRoute
+ '/lazyref': typeof LazyrefRoute
'/promise': typeof PromiseRoute
'/tests': typeof TestsRoute
'/time': typeof TimeRoute
@@ -137,10 +154,25 @@ export interface FileRoutesById {
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths: '/' | '/blank' | '/count' | '/promise' | '/tests' | '/time'
+ fullPaths:
+ | '/'
+ | '/blank'
+ | '/count'
+ | '/lazyref'
+ | '/promise'
+ | '/tests'
+ | '/time'
fileRoutesByTo: FileRoutesByTo
- to: '/' | '/blank' | '/count' | '/promise' | '/tests' | '/time'
- id: '__root__' | '/' | '/blank' | '/count' | '/promise' | '/tests' | '/time'
+ to: '/' | '/blank' | '/count' | '/lazyref' | '/promise' | '/tests' | '/time'
+ id:
+ | '__root__'
+ | '/'
+ | '/blank'
+ | '/count'
+ | '/lazyref'
+ | '/promise'
+ | '/tests'
+ | '/time'
fileRoutesById: FileRoutesById
}
@@ -148,6 +180,7 @@ export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
BlankRoute: typeof BlankRoute
CountRoute: typeof CountRoute
+ LazyrefRoute: typeof LazyrefRoute
PromiseRoute: typeof PromiseRoute
TestsRoute: typeof TestsRoute
TimeRoute: typeof TimeRoute
@@ -157,6 +190,7 @@ const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
BlankRoute: BlankRoute,
CountRoute: CountRoute,
+ LazyrefRoute: LazyrefRoute,
PromiseRoute: PromiseRoute,
TestsRoute: TestsRoute,
TimeRoute: TimeRoute,
@@ -175,6 +209,7 @@ export const routeTree = rootRoute
"/",
"/blank",
"/count",
+ "/lazyref",
"/promise",
"/tests",
"/time"
@@ -189,6 +224,9 @@ export const routeTree = rootRoute
"/count": {
"filePath": "count.tsx"
},
+ "/lazyref": {
+ "filePath": "lazyref.tsx"
+ },
"/promise": {
"filePath": "promise.tsx"
},
diff --git a/packages/example/src/routes/lazyref.tsx b/packages/example/src/routes/lazyref.tsx
new file mode 100644
index 0000000..586f25c
--- /dev/null
+++ b/packages/example/src/routes/lazyref.tsx
@@ -0,0 +1,31 @@
+import { R } from "@/reffuse"
+import { Button, Text } from "@radix-ui/themes"
+import { createFileRoute } from "@tanstack/react-router"
+import * as LazyRef from "@typed/lazy-ref"
+import { Suspense, use } from "react"
+
+
+export const Route = createFileRoute("/lazyref")({
+ component: RouteComponent
+})
+
+function RouteComponent() {
+ const promise = R.usePromise(LazyRef.of(0))
+
+ return (
+ Loading...}>
+
+
+ )
+}
+
+function LazyRefComponent({ promise }: { readonly promise: Promise> }) {
+ const ref = use(promise)
+ const [value, setValue] = R.useLazyRefState(ref)
+
+ return (
+
+ )
+}
diff --git a/packages/extension-lazyref/src/index.ts b/packages/extension-lazyref/src/index.ts
index 301509a..42728c5 100644
--- a/packages/extension-lazyref/src/index.ts
+++ b/packages/extension-lazyref/src/index.ts
@@ -1,10 +1,10 @@
import * as LazyRef from "@typed/lazy-ref"
import { Effect, Stream } from "effect"
import * as React from "react"
-import { ReffuseExtension, ReffuseHelpers, SetStateAction } from "reffuse"
+import { ReffuseExtension, type ReffuseHelpers, SetStateAction } from "reffuse"
-export const withLazyRef = ReffuseExtension.make(() => ({
+export const LazyRefExtension = ReffuseExtension.make(() => ({
useLazyRefState(
this: ReffuseHelpers.ReffuseHelpers,
ref: LazyRef.LazyRef,
diff --git a/packages/reffuse/src/Reffuse.ts b/packages/reffuse/src/Reffuse.ts
index 0721298..87d13e4 100644
--- a/packages/reffuse/src/Reffuse.ts
+++ b/packages/reffuse/src/Reffuse.ts
@@ -1,10 +1,12 @@
import type * as ReffuseContext from "./ReffuseContext.js"
+import type * as ReffuseExtension from "./ReffuseExtension.js"
import * as ReffuseHelpers from "./ReffuseHelpers.js"
import type { Merge, StaticType } from "./types.js"
export class Reffuse extends ReffuseHelpers.make() {}
+
export const withContexts = >(
...contexts: [...{ [K in keyof R2]: ReffuseContext.ReffuseContext }]
) =>
@@ -27,3 +29,19 @@ export const withContexts = >(
) => class extends self {
static readonly contexts = [...self.contexts, ...contexts]
} as any
+
+
+export const withExtension = (extension: ReffuseExtension.ReffuseExtension) =>
+ <
+ BaseClass extends ReffuseHelpers.ReffuseHelpersClass,
+ R
+ >(
+ self: BaseClass & ReffuseHelpers.ReffuseHelpersClass
+ ): (
+ { new(): Merge, A> } &
+ StaticType
+ ) => {
+ const class_ = class extends self {}
+ Object.assign(class_.prototype, extension())
+ return class_ as any
+ }
diff --git a/packages/reffuse/src/ReffuseContext.tsx b/packages/reffuse/src/ReffuseContext.tsx
index c914a61..e7e723a 100644
--- a/packages/reffuse/src/ReffuseContext.tsx
+++ b/packages/reffuse/src/ReffuseContext.tsx
@@ -3,7 +3,6 @@ import * as React from "react"
import * as ReffuseRuntime from "./ReffuseRuntime.js"
-// TODO: merge this with the Provider, just like React 19 contexts
export class ReffuseContext {
readonly Context = React.createContext>(null!)
@@ -11,7 +10,7 @@ export class ReffuseContext {
constructor() {
// TODO: scope the layer creation
- this.Provider = (props) => {
+ this.Provider = props => {
const runtime = ReffuseRuntime.useRuntime()
const value = React.useMemo(() => Effect.context().pipe(
diff --git a/packages/reffuse/src/ReffuseExtension.ts b/packages/reffuse/src/ReffuseExtension.ts
index ce1fdea..3dda6c2 100644
--- a/packages/reffuse/src/ReffuseExtension.ts
+++ b/packages/reffuse/src/ReffuseExtension.ts
@@ -1,18 +1,7 @@
-import type * as ReffuseHelpers from "./ReffuseHelpers.js"
-import type { Merge, StaticType } from "./types.js"
+export interface ReffuseExtension {
+ (): A
+ readonly Type: A
+}
-
-export const make = (extension: () => Ext) =>
- <
- BaseClass extends ReffuseHelpers.ReffuseHelpersClass,
- R
- >(
- self: BaseClass & ReffuseHelpers.ReffuseHelpersClass
- ): (
- { new(): Merge, Ext> } &
- StaticType
- ) => {
- const class_ = class extends self {}
- Object.assign(class_.prototype, extension())
- return class_ as any
- }
+export const make = (extension: () => A): ReffuseExtension =>
+ extension as ReffuseExtension