diff --git a/packages/extension-query/README.md b/packages/extension-query/README.md new file mode 100644 index 0000000..699855e --- /dev/null +++ b/packages/extension-query/README.md @@ -0,0 +1,9 @@ +# LazyRef extension for Reffuse + +Extension to integrate `@typed/lazy-ref` with Reffuse. + +## Peer dependencies +- `@typed/lazy-ref` +- `reffuse` 0.1.2+ +- `effect` 3.13+ +- `react` & `@types/react` 19+ diff --git a/packages/extension-query/package.json b/packages/extension-query/package.json new file mode 100644 index 0000000..10b1b4f --- /dev/null +++ b/packages/extension-query/package.json @@ -0,0 +1,41 @@ +{ + "name": "@reffuse/extension-query", + "version": "0.1.0", + "type": "module", + "files": [ + "./README.md", + "./dist" + ], + "license": "MIT", + "repository": { + "url": "git+https://github.com/Thiladev/reffuse.git" + }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./*": { + "types": "./dist/*.d.ts", + "default": "./dist/*.js" + } + }, + "scripts": { + "build": "tsc", + "lint:tsc": "tsc --noEmit", + "pack": "npm pack", + "clean:cache": "rm -f tsconfig.tsbuildinfo", + "clean:dist": "rm -rf dist", + "clean:node": "rm -rf node_modules" + }, + "devDependencies": { + "reffuse": "workspace:*" + }, + "peerDependencies": { + "@types/react": "^19.0.0", + "effect": "^3.13.0", + "react": "^19.0.0", + "reffuse": "^0.1.2" + } +} diff --git a/packages/extension-query/src/index.ts b/packages/extension-query/src/index.ts new file mode 100644 index 0000000..e5fbb02 --- /dev/null +++ b/packages/extension-query/src/index.ts @@ -0,0 +1,29 @@ +import * as LazyRef from "@typed/lazy-ref" +import { Effect, Stream } from "effect" +import * as React from "react" +import { ReffuseExtension, type ReffuseHelpers, SetStateAction } from "reffuse" + + +export const LazyRefExtension = ReffuseExtension.make(() => ({ + useLazyRefState( + this: ReffuseHelpers.ReffuseHelpers, + ref: LazyRef.LazyRef, + ): [A, React.Dispatch>] { + const runSync = this.useRunSync() + + const initialState = React.useMemo(() => runSync(ref), []) + const [reactStateValue, setReactStateValue] = React.useState(initialState) + + this.useFork(() => Stream.runForEach(ref.changes, v => Effect.sync(() => + setReactStateValue(v) + )), [ref]) + + const setValue = React.useCallback((setStateAction: React.SetStateAction) => + runSync(LazyRef.update(ref, prevState => + SetStateAction.value(setStateAction, prevState) + )), + [ref]) + + return [reactStateValue, setValue] + }, +})) diff --git a/packages/extension-query/tsconfig.json b/packages/extension-query/tsconfig.json new file mode 100644 index 0000000..eea16a8 --- /dev/null +++ b/packages/extension-query/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "NodeNext", + "moduleDetection": "force", + "jsx": "react-jsx", + // "allowJs": true, + + // Bundler mode + "moduleResolution": "NodeNext", + // "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + // "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, + + // Build + "outDir": "./dist", + "declaration": true + }, + + "include": ["./src"] +}