@iadev93/zuno-react 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.mts +72 -0
- package/dist/index.d.ts +12 -10
- package/dist/index.js +2 -75
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +8 -5
- package/dist/index.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @iadev93/zuno-react
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
<p><b>Idiomatic React bindings for Zuno.</b></p>
|
|
4
4
|
|
|
5
|
-
This package provides
|
|
5
|
+
This package provides deep integration with React using `useSyncExternalStore` for performance and consistency.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ZunoSubscribableStore, CreateZunoOptions } from '@iadev93/zuno';
|
|
2
|
+
export { ZunoReadable } from '@iadev93/zuno';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type definition for an equality function.
|
|
6
|
+
* It takes two values of the same type and returns true if they are considered equal, false otherwise.
|
|
7
|
+
* Used to prevent unnecessary re-renders in React hooks when the selected state hasn't "meaningfully" changed.
|
|
8
|
+
*/
|
|
9
|
+
type EqualityFn<T> = (a: T, b: T) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Type definition for a selector function.
|
|
12
|
+
* It takes the full state of a store and returns a selected portion of that state.
|
|
13
|
+
* This allows components to subscribe only to the parts of the state they care about,
|
|
14
|
+
* optimizing performance by avoiding re-renders for unrelated state changes.
|
|
15
|
+
*/
|
|
16
|
+
type Selector<TState, TSelected> = (state: TState) => TSelected;
|
|
17
|
+
/**
|
|
18
|
+
* An extended interface for a Zuno store that includes methods for setting state
|
|
19
|
+
* and a unique key identifier. This represents a store that has been "bound" or registered.
|
|
20
|
+
*/
|
|
21
|
+
type BoundStore<T> = {
|
|
22
|
+
key: string;
|
|
23
|
+
get: () => T;
|
|
24
|
+
set: (next: T | ((prev: T) => T)) => Promise<any>;
|
|
25
|
+
subscribe: (cb: (state: T) => void) => () => void;
|
|
26
|
+
raw: () => ZunoSubscribableStore<T>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The core interface for the Zuno library, providing methods to create,
|
|
30
|
+
* retrieve, and update stores.
|
|
31
|
+
*/
|
|
32
|
+
type ZunoCore = {
|
|
33
|
+
store<T>(storeKey: string, init: () => T): BoundStore<T>;
|
|
34
|
+
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
35
|
+
get<T>(storeKey: string, init?: () => T): T;
|
|
36
|
+
stop?: () => void;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* An extended interface for a Zuno store that includes React-specific features.
|
|
40
|
+
*/
|
|
41
|
+
type ReactBoundStore<T> = BoundStore<T> & {
|
|
42
|
+
/**
|
|
43
|
+
* React hook for this store.
|
|
44
|
+
* Optional selector + equality for derived values and avoiding rerenders.
|
|
45
|
+
*/
|
|
46
|
+
use: <TSelected = T>(selector?: Selector<T, TSelected>, equalityFn?: EqualityFn<TSelected>) => TSelected;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Binds Zuno to React.
|
|
50
|
+
* @param zuno The Zuno instance to bind.
|
|
51
|
+
* @returns A React-enhanced Zuno instance.
|
|
52
|
+
*/
|
|
53
|
+
declare const bindReact: (zuno: ZunoCore) => {
|
|
54
|
+
store: <T>(storeKey: string, init: () => T) => ReactBoundStore<T>;
|
|
55
|
+
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
56
|
+
get<T>(storeKey: string, init?: () => T): T;
|
|
57
|
+
stop?: () => void;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Creates a Zuno instance and returns a React-enhanced instance.
|
|
61
|
+
*
|
|
62
|
+
* @param opts The options for the Zuno instance.
|
|
63
|
+
* @returns An object with a `store` method that returns stores with a `use` hook.
|
|
64
|
+
*/
|
|
65
|
+
declare const createZunoReact: (opts: CreateZunoOptions) => {
|
|
66
|
+
store: <T>(storeKey: string, init: () => T) => ReactBoundStore<T>;
|
|
67
|
+
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
68
|
+
get<T>(storeKey: string, init?: () => T): T;
|
|
69
|
+
stop?: () => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { type BoundStore, type EqualityFn, type ReactBoundStore, type Selector, type ZunoCore, bindReact, createZunoReact };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZunoSubscribableStore, CreateZunoOptions } from '@iadev93/zuno';
|
|
2
|
+
export { ZunoReadable } from '@iadev93/zuno';
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
5
|
* Type definition for an equality function.
|
|
4
6
|
* It takes two values of the same type and returns true if they are considered equal, false otherwise.
|
|
5
7
|
* Used to prevent unnecessary re-renders in React hooks when the selected state hasn't "meaningfully" changed.
|
|
6
8
|
*/
|
|
7
|
-
|
|
9
|
+
type EqualityFn<T> = (a: T, b: T) => boolean;
|
|
8
10
|
/**
|
|
9
11
|
* Type definition for a selector function.
|
|
10
12
|
* It takes the full state of a store and returns a selected portion of that state.
|
|
11
13
|
* This allows components to subscribe only to the parts of the state they care about,
|
|
12
14
|
* optimizing performance by avoiding re-renders for unrelated state changes.
|
|
13
15
|
*/
|
|
14
|
-
|
|
16
|
+
type Selector<TState, TSelected> = (state: TState) => TSelected;
|
|
15
17
|
/**
|
|
16
18
|
* An extended interface for a Zuno store that includes methods for setting state
|
|
17
19
|
* and a unique key identifier. This represents a store that has been "bound" or registered.
|
|
18
20
|
*/
|
|
19
|
-
|
|
21
|
+
type BoundStore<T> = {
|
|
20
22
|
key: string;
|
|
21
23
|
get: () => T;
|
|
22
24
|
set: (next: T | ((prev: T) => T)) => Promise<any>;
|
|
@@ -27,7 +29,7 @@ export type BoundStore<T> = {
|
|
|
27
29
|
* The core interface for the Zuno library, providing methods to create,
|
|
28
30
|
* retrieve, and update stores.
|
|
29
31
|
*/
|
|
30
|
-
|
|
32
|
+
type ZunoCore = {
|
|
31
33
|
store<T>(storeKey: string, init: () => T): BoundStore<T>;
|
|
32
34
|
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
33
35
|
get<T>(storeKey: string, init?: () => T): T;
|
|
@@ -36,7 +38,7 @@ export type ZunoCore = {
|
|
|
36
38
|
/**
|
|
37
39
|
* An extended interface for a Zuno store that includes React-specific features.
|
|
38
40
|
*/
|
|
39
|
-
|
|
41
|
+
type ReactBoundStore<T> = BoundStore<T> & {
|
|
40
42
|
/**
|
|
41
43
|
* React hook for this store.
|
|
42
44
|
* Optional selector + equality for derived values and avoiding rerenders.
|
|
@@ -48,7 +50,7 @@ export type ReactBoundStore<T> = BoundStore<T> & {
|
|
|
48
50
|
* @param zuno The Zuno instance to bind.
|
|
49
51
|
* @returns A React-enhanced Zuno instance.
|
|
50
52
|
*/
|
|
51
|
-
|
|
53
|
+
declare const bindReact: (zuno: ZunoCore) => {
|
|
52
54
|
store: <T>(storeKey: string, init: () => T) => ReactBoundStore<T>;
|
|
53
55
|
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
54
56
|
get<T>(storeKey: string, init?: () => T): T;
|
|
@@ -60,11 +62,11 @@ export declare const bindReact: (zuno: ZunoCore) => {
|
|
|
60
62
|
* @param opts The options for the Zuno instance.
|
|
61
63
|
* @returns An object with a `store` method that returns stores with a `use` hook.
|
|
62
64
|
*/
|
|
63
|
-
|
|
65
|
+
declare const createZunoReact: (opts: CreateZunoOptions) => {
|
|
64
66
|
store: <T>(storeKey: string, init: () => T) => ReactBoundStore<T>;
|
|
65
67
|
set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;
|
|
66
68
|
get<T>(storeKey: string, init?: () => T): T;
|
|
67
69
|
stop?: () => void;
|
|
68
70
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
|
|
72
|
+
export { type BoundStore, type EqualityFn, type ReactBoundStore, type Selector, type ZunoCore, bindReact, createZunoReact };
|
package/dist/index.js
CHANGED
|
@@ -1,75 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The default equality function, using `Object.is` for strict equality comparison.
|
|
5
|
-
* This is a common and safe default for comparing primitive values and references.
|
|
6
|
-
*/
|
|
7
|
-
const defaultEq = Object.is;
|
|
8
|
-
/**
|
|
9
|
-
* Binds Zuno to React.
|
|
10
|
-
* @param zuno The Zuno instance to bind.
|
|
11
|
-
* @returns A React-enhanced Zuno instance.
|
|
12
|
-
*/
|
|
13
|
-
export const bindReact = (zuno) => {
|
|
14
|
-
/**
|
|
15
|
-
* A custom hook for accessing a Zuno store in a React component.
|
|
16
|
-
*/
|
|
17
|
-
const useExternalStore = (readable, selector, equalityFn = defaultEq) => {
|
|
18
|
-
const select = React.useMemo(() => {
|
|
19
|
-
return (selector ??
|
|
20
|
-
((s) => s));
|
|
21
|
-
}, [selector]);
|
|
22
|
-
const lastRef = React.useRef(null);
|
|
23
|
-
const hasLast = React.useRef(false);
|
|
24
|
-
const getSnapshot = React.useCallback(() => {
|
|
25
|
-
const next = select(readable.getSnapshot());
|
|
26
|
-
if (!hasLast.current) {
|
|
27
|
-
hasLast.current = true;
|
|
28
|
-
lastRef.current = next;
|
|
29
|
-
return next;
|
|
30
|
-
}
|
|
31
|
-
const prev = lastRef.current;
|
|
32
|
-
if (equalityFn(prev, next))
|
|
33
|
-
return prev;
|
|
34
|
-
lastRef.current = next;
|
|
35
|
-
return next;
|
|
36
|
-
}, [readable, select, equalityFn]);
|
|
37
|
-
const subscribe = React.useCallback((onChange) => readable.subscribe(onChange), [readable]);
|
|
38
|
-
const getServerSnapshot = React.useCallback(() => {
|
|
39
|
-
const s = readable.getServerSnapshot ? readable.getServerSnapshot() : readable.getSnapshot();
|
|
40
|
-
return select(s);
|
|
41
|
-
}, [readable, select]);
|
|
42
|
-
React.useEffect(() => {
|
|
43
|
-
hasLast.current = false;
|
|
44
|
-
lastRef.current = null;
|
|
45
|
-
}, [select, equalityFn]);
|
|
46
|
-
return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* Creates a React-enhanced store.
|
|
50
|
-
*/
|
|
51
|
-
const store = (storeKey, init) => {
|
|
52
|
-
const base = zuno.store(storeKey, init);
|
|
53
|
-
return {
|
|
54
|
-
...base,
|
|
55
|
-
use: (selector, equalityFn = defaultEq) => {
|
|
56
|
-
const readable = React.useMemo(() => toReadable(base.raw()), [storeKey]);
|
|
57
|
-
return useExternalStore(readable, selector, equalityFn);
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
return {
|
|
62
|
-
...zuno,
|
|
63
|
-
store,
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Creates a Zuno instance and returns a React-enhanced instance.
|
|
68
|
-
*
|
|
69
|
-
* @param opts The options for the Zuno instance.
|
|
70
|
-
* @returns An object with a `store` method that returns stores with a `use` hook.
|
|
71
|
-
*/
|
|
72
|
-
export const createZunoReact = (opts) => {
|
|
73
|
-
const zuno = createZuno(opts);
|
|
74
|
-
return bindReact(zuno);
|
|
75
|
-
};
|
|
1
|
+
'use strict';var e=require('react'),zuno=require('@iadev93/zuno');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var e__namespace=/*#__PURE__*/_interopNamespace(e);var l=Object.is,y=a=>{let T=(t,u,n=l)=>{let o=e__namespace.useMemo(()=>u??(r=>r),[u]),s=e__namespace.useRef(null),c=e__namespace.useRef(false),i=e__namespace.useCallback(()=>{let r=o(t.getSnapshot());if(!c.current)return c.current=true,s.current=r,r;let S=s.current;return n(S,r)?S:(s.current=r,r)},[t,o,n]),p=e__namespace.useCallback(r=>t.subscribe(r),[t]),d=e__namespace.useCallback(()=>{let r=t.getServerSnapshot?t.getServerSnapshot():t.getSnapshot();return o(r)},[t,o]);return e__namespace.useEffect(()=>{c.current=false,s.current=null;},[o,n]),e__namespace.useSyncExternalStore(p,i,d)};return {...a,store:(t,u)=>{let n=a.store(t,u);return {...n,use:(o,s=l)=>{let c=e__namespace.useMemo(()=>zuno.toReadable(n.raw()),[t]);return T(c,o,s)}}}}},x=a=>{let T=zuno.createZuno(a);return y(T)};exports.bindReact=y;exports.createZunoReact=x;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["defaultEq","bindReact","zuno","useExternalStore","readable","selector","equalityFn","select","e","s","lastRef","hasLast","getSnapshot","next","prev","subscribe","onChange","getServerSnapshot","storeKey","init","base","toReadable","createZunoReact","opts","createZuno"],"mappings":"waAsBA,IAAMA,CAAAA,CAA6B,MAAA,CAAO,GA4C7BC,CAAAA,CAAaC,CAAAA,EAAmB,CAI3C,IAAMC,CAAAA,CAAmB,CACvBC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAAoCN,CAAAA,GACtB,CACd,IAAMO,EAAeC,YAAA,CAAA,OAAA,CAAQ,IACnBH,IACJI,CAAAA,EAAcA,CAAAA,CAAAA,CACjB,CAACJ,CAAQ,CAAC,CAAA,CAEPK,CAAAA,CAAgBF,YAAA,CAAA,MAAA,CAAyB,IAAI,EAC7CG,CAAAA,CAAgBH,YAAA,CAAA,MAAA,CAAO,KAAK,CAAA,CAE5BI,CAAAA,CAAoBJ,yBAAY,IAAM,CAC1C,IAAMK,CAAAA,CAAON,CAAAA,CAAOH,CAAAA,CAAS,aAAa,CAAA,CAE1C,GAAI,CAACO,CAAAA,CAAQ,QACX,OAAAA,CAAAA,CAAQ,OAAA,CAAU,IAAA,CAClBD,CAAAA,CAAQ,OAAA,CAAUG,EACXA,CAAAA,CAGT,IAAMC,EAAOJ,CAAAA,CAAQ,OAAA,CACrB,OAAIJ,CAAAA,CAAWQ,CAAAA,CAAMD,CAAI,CAAA,CAAUC,CAAAA,EAEnCJ,CAAAA,CAAQ,QAAUG,CAAAA,CACXA,CAAAA,CACT,EAAG,CAACT,CAAAA,CAAUG,EAAQD,CAAU,CAAC,CAAA,CAE3BS,CAAAA,CAAkBP,YAAA,CAAA,WAAA,CACrBQ,CAAAA,EAAyBZ,EAAS,SAAA,CAAUY,CAAQ,EACrD,CAACZ,CAAQ,CACX,CAAA,CAEMa,CAAAA,CAA0BT,YAAA,CAAA,WAAA,CAAY,IAAM,CAChD,IAAMC,EAAIL,CAAAA,CAAS,iBAAA,CAAoBA,EAAS,iBAAA,EAAkB,CAAIA,EAAS,WAAA,EAAY,CAC3F,OAAOG,CAAAA,CAAOE,CAAC,CACjB,EAAG,CAACL,CAAAA,CAAUG,CAAM,CAAC,CAAA,CAErB,OAAMC,YAAA,CAAA,SAAA,CAAU,IAAM,CACpBG,CAAAA,CAAQ,OAAA,CAAU,KAAA,CAClBD,EAAQ,OAAA,CAAU,KACpB,EAAG,CAACH,CAAAA,CAAQD,CAAU,CAAC,CAAA,CAEVE,YAAA,CAAA,oBAAA,CAAqBO,CAAAA,CAAWH,CAAAA,CAAaK,CAAiB,CAC7E,CAAA,CAuBA,OAAO,CACL,GAAGf,CAAAA,CACH,MApBY,CAAKgB,CAAAA,CAAkBC,CAAAA,GAAsC,CACzE,IAAMC,CAAAA,CAAOlB,EAAK,KAAA,CAASgB,CAAAA,CAAUC,CAAI,CAAA,CAEzC,OAAO,CACL,GAAGC,CAAAA,CACH,GAAA,CAAK,CACHf,CAAAA,CACAC,CAAAA,CAAoCN,IACjC,CACH,IAAMI,EAAiBI,YAAA,CAAA,OAAA,CACrB,IAAMa,gBAAWD,CAAAA,CAAK,GAAA,EAAiC,CAAA,CACvD,CAACF,CAAQ,CACX,CAAA,CACA,OAAOf,EAA+BC,CAAAA,CAAUC,CAAAA,CAAUC,CAAU,CACtE,CACF,CACF,CAKA,CACF,CAAA,CAQagB,EAAmBC,CAAAA,EAA4B,CAC1D,IAAMrB,CAAAA,CAAOsB,eAAAA,CAAWD,CAAI,CAAA,CAC5B,OAAOtB,CAAAA,CAAUC,CAAI,CACvB","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { type ZunoReadable, type ZunoSubscribableStore, toReadable, createZuno, type CreateZunoOptions } from \"@iadev93/zuno\";\n\n/**\n * Type definition for an equality function.\n * It takes two values of the same type and returns true if they are considered equal, false otherwise.\n * Used to prevent unnecessary re-renders in React hooks when the selected state hasn't \"meaningfully\" changed.\n */\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\n\n/**\n * Type definition for a selector function.\n * It takes the full state of a store and returns a selected portion of that state.\n * This allows components to subscribe only to the parts of the state they care about,\n * optimizing performance by avoiding re-renders for unrelated state changes.\n */\nexport type Selector<TState, TSelected> = (state: TState) => TSelected;\n\n/**\n * The default equality function, using `Object.is` for strict equality comparison.\n * This is a common and safe default for comparing primitive values and references.\n */\nconst defaultEq: EqualityFn<any> = Object.is;\n\n/**\n * An extended interface for a Zuno store that includes methods for setting state\n * and a unique key identifier. This represents a store that has been \"bound\" or registered.\n */\nexport type BoundStore<T> = {\n key: string;\n get: () => T;\n set: (next: T | ((prev: T) => T)) => Promise<any>;\n subscribe: (cb: (state: T) => void) => () => void;\n raw: () => ZunoSubscribableStore<T>;\n};\n\n/**\n * The core interface for the Zuno library, providing methods to create,\n * retrieve, and update stores.\n */\nexport type ZunoCore = {\n store<T>(storeKey: string, init: () => T): BoundStore<T>;\n set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;\n get<T>(storeKey: string, init?: () => T): T;\n stop?: () => void;\n};\n\n/**\n * An extended interface for a Zuno store that includes React-specific features.\n */\nexport type ReactBoundStore<T> = BoundStore<T> & {\n /**\n * React hook for this store.\n * Optional selector + equality for derived values and avoiding rerenders.\n */\n use: <TSelected = T>(\n selector?: Selector<T, TSelected>,\n equalityFn?: EqualityFn<TSelected>\n ) => TSelected;\n};\n\n/**\n * Binds Zuno to React.\n * @param zuno The Zuno instance to bind.\n * @returns A React-enhanced Zuno instance.\n */\nexport const bindReact = (zuno: ZunoCore) => {\n /**\n * A custom hook for accessing a Zuno store in a React component.\n */\n const useExternalStore = <TState, TSelected = TState>(\n readable: ZunoReadable<TState>,\n selector?: Selector<TState, TSelected>,\n equalityFn: EqualityFn<TSelected> = defaultEq\n ): TSelected => {\n const select = React.useMemo(() => {\n return (selector ??\n ((s: TState) => s as unknown as TSelected)) as Selector<TState, TSelected>;\n }, [selector]);\n\n const lastRef = React.useRef<TSelected | null>(null);\n const hasLast = React.useRef(false);\n\n const getSnapshot = React.useCallback(() => {\n const next = select(readable.getSnapshot());\n\n if (!hasLast.current) {\n hasLast.current = true;\n lastRef.current = next;\n return next;\n }\n\n const prev = lastRef.current as TSelected;\n if (equalityFn(prev, next)) return prev;\n\n lastRef.current = next;\n return next;\n }, [readable, select, equalityFn]);\n\n const subscribe = React.useCallback(\n (onChange: () => void) => readable.subscribe(onChange),\n [readable]\n );\n\n const getServerSnapshot = React.useCallback(() => {\n const s = readable.getServerSnapshot ? readable.getServerSnapshot() : readable.getSnapshot();\n return select(s);\n }, [readable, select]);\n\n React.useEffect(() => {\n hasLast.current = false;\n lastRef.current = null;\n }, [select, equalityFn]);\n\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n };\n\n /**\n * Creates a React-enhanced store.\n */\n const store = <T,>(storeKey: string, init: () => T): ReactBoundStore<T> => {\n const base = zuno.store<T>(storeKey, init);\n\n return {\n ...base,\n use: <TSelected = T>(\n selector?: Selector<T, TSelected>,\n equalityFn: EqualityFn<TSelected> = defaultEq\n ) => {\n const readable = React.useMemo(\n () => toReadable(base.raw() as ZunoSubscribableStore<T>),\n [storeKey]\n );\n return useExternalStore<T, TSelected>(readable, selector, equalityFn);\n },\n };\n };\n\n return {\n ...zuno,\n store,\n };\n};\n\n/**\n * Creates a Zuno instance and returns a React-enhanced instance.\n * \n * @param opts The options for the Zuno instance.\n * @returns An object with a `store` method that returns stores with a `use` hook.\n */\nexport const createZunoReact = (opts: CreateZunoOptions) => {\n const zuno = createZuno(opts);\n return bindReact(zuno);\n};\n\n// Convenience re-export\nexport type { ZunoReadable } from \"@iadev93/zuno\";\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import*as e from'react';import {toReadable,createZuno}from'@iadev93/zuno';var l=Object.is,y=a=>{let T=(t,u,n=l)=>{let o=e.useMemo(()=>u??(r=>r),[u]),s=e.useRef(null),c=e.useRef(false),i=e.useCallback(()=>{let r=o(t.getSnapshot());if(!c.current)return c.current=true,s.current=r,r;let S=s.current;return n(S,r)?S:(s.current=r,r)},[t,o,n]),p=e.useCallback(r=>t.subscribe(r),[t]),d=e.useCallback(()=>{let r=t.getServerSnapshot?t.getServerSnapshot():t.getSnapshot();return o(r)},[t,o]);return e.useEffect(()=>{c.current=false,s.current=null;},[o,n]),e.useSyncExternalStore(p,i,d)};return {...a,store:(t,u)=>{let n=a.store(t,u);return {...n,use:(o,s=l)=>{let c=e.useMemo(()=>toReadable(n.raw()),[t]);return T(c,o,s)}}}}},x=a=>{let T=createZuno(a);return y(T)};export{y as bindReact,x as createZunoReact};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["defaultEq","bindReact","zuno","useExternalStore","readable","selector","equalityFn","select","s","lastRef","hasLast","getSnapshot","next","prev","subscribe","onChange","getServerSnapshot","storeKey","init","base","toReadable","createZunoReact","opts","createZuno"],"mappings":"0EAsBA,IAAMA,CAAAA,CAA6B,MAAA,CAAO,GA4C7BC,CAAAA,CAAaC,CAAAA,EAAmB,CAI3C,IAAMC,CAAAA,CAAmB,CACvBC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAAoCN,CAAAA,GACtB,CACd,IAAMO,EAAe,CAAA,CAAA,OAAA,CAAQ,IACnBF,IACJG,CAAAA,EAAcA,CAAAA,CAAAA,CACjB,CAACH,CAAQ,CAAC,CAAA,CAEPI,CAAAA,CAAgB,CAAA,CAAA,MAAA,CAAyB,IAAI,EAC7CC,CAAAA,CAAgB,CAAA,CAAA,MAAA,CAAO,KAAK,CAAA,CAE5BC,CAAAA,CAAoB,cAAY,IAAM,CAC1C,IAAMC,CAAAA,CAAOL,CAAAA,CAAOH,CAAAA,CAAS,aAAa,CAAA,CAE1C,GAAI,CAACM,CAAAA,CAAQ,QACX,OAAAA,CAAAA,CAAQ,OAAA,CAAU,IAAA,CAClBD,CAAAA,CAAQ,OAAA,CAAUG,EACXA,CAAAA,CAGT,IAAMC,EAAOJ,CAAAA,CAAQ,OAAA,CACrB,OAAIH,CAAAA,CAAWO,CAAAA,CAAMD,CAAI,CAAA,CAAUC,CAAAA,EAEnCJ,CAAAA,CAAQ,QAAUG,CAAAA,CACXA,CAAAA,CACT,EAAG,CAACR,CAAAA,CAAUG,EAAQD,CAAU,CAAC,CAAA,CAE3BQ,CAAAA,CAAkB,CAAA,CAAA,WAAA,CACrBC,CAAAA,EAAyBX,EAAS,SAAA,CAAUW,CAAQ,EACrD,CAACX,CAAQ,CACX,CAAA,CAEMY,CAAAA,CAA0B,CAAA,CAAA,WAAA,CAAY,IAAM,CAChD,IAAMR,EAAIJ,CAAAA,CAAS,iBAAA,CAAoBA,EAAS,iBAAA,EAAkB,CAAIA,EAAS,WAAA,EAAY,CAC3F,OAAOG,CAAAA,CAAOC,CAAC,CACjB,EAAG,CAACJ,CAAAA,CAAUG,CAAM,CAAC,CAAA,CAErB,OAAM,CAAA,CAAA,SAAA,CAAU,IAAM,CACpBG,CAAAA,CAAQ,OAAA,CAAU,KAAA,CAClBD,EAAQ,OAAA,CAAU,KACpB,EAAG,CAACF,CAAAA,CAAQD,CAAU,CAAC,CAAA,CAEV,CAAA,CAAA,oBAAA,CAAqBQ,CAAAA,CAAWH,CAAAA,CAAaK,CAAiB,CAC7E,CAAA,CAuBA,OAAO,CACL,GAAGd,CAAAA,CACH,MApBY,CAAKe,CAAAA,CAAkBC,CAAAA,GAAsC,CACzE,IAAMC,CAAAA,CAAOjB,EAAK,KAAA,CAASe,CAAAA,CAAUC,CAAI,CAAA,CAEzC,OAAO,CACL,GAAGC,CAAAA,CACH,GAAA,CAAK,CACHd,CAAAA,CACAC,CAAAA,CAAoCN,IACjC,CACH,IAAMI,EAAiB,CAAA,CAAA,OAAA,CACrB,IAAMgB,WAAWD,CAAAA,CAAK,GAAA,EAAiC,CAAA,CACvD,CAACF,CAAQ,CACX,CAAA,CACA,OAAOd,EAA+BC,CAAAA,CAAUC,CAAAA,CAAUC,CAAU,CACtE,CACF,CACF,CAKA,CACF,CAAA,CAQae,EAAmBC,CAAAA,EAA4B,CAC1D,IAAMpB,CAAAA,CAAOqB,UAAAA,CAAWD,CAAI,CAAA,CAC5B,OAAOrB,CAAAA,CAAUC,CAAI,CACvB","file":"index.mjs","sourcesContent":["import * as React from \"react\";\nimport { type ZunoReadable, type ZunoSubscribableStore, toReadable, createZuno, type CreateZunoOptions } from \"@iadev93/zuno\";\n\n/**\n * Type definition for an equality function.\n * It takes two values of the same type and returns true if they are considered equal, false otherwise.\n * Used to prevent unnecessary re-renders in React hooks when the selected state hasn't \"meaningfully\" changed.\n */\nexport type EqualityFn<T> = (a: T, b: T) => boolean;\n\n/**\n * Type definition for a selector function.\n * It takes the full state of a store and returns a selected portion of that state.\n * This allows components to subscribe only to the parts of the state they care about,\n * optimizing performance by avoiding re-renders for unrelated state changes.\n */\nexport type Selector<TState, TSelected> = (state: TState) => TSelected;\n\n/**\n * The default equality function, using `Object.is` for strict equality comparison.\n * This is a common and safe default for comparing primitive values and references.\n */\nconst defaultEq: EqualityFn<any> = Object.is;\n\n/**\n * An extended interface for a Zuno store that includes methods for setting state\n * and a unique key identifier. This represents a store that has been \"bound\" or registered.\n */\nexport type BoundStore<T> = {\n key: string;\n get: () => T;\n set: (next: T | ((prev: T) => T)) => Promise<any>;\n subscribe: (cb: (state: T) => void) => () => void;\n raw: () => ZunoSubscribableStore<T>;\n};\n\n/**\n * The core interface for the Zuno library, providing methods to create,\n * retrieve, and update stores.\n */\nexport type ZunoCore = {\n store<T>(storeKey: string, init: () => T): BoundStore<T>;\n set<T>(storeKey: string, next: T | ((prev: T) => T), init?: () => T): Promise<any>;\n get<T>(storeKey: string, init?: () => T): T;\n stop?: () => void;\n};\n\n/**\n * An extended interface for a Zuno store that includes React-specific features.\n */\nexport type ReactBoundStore<T> = BoundStore<T> & {\n /**\n * React hook for this store.\n * Optional selector + equality for derived values and avoiding rerenders.\n */\n use: <TSelected = T>(\n selector?: Selector<T, TSelected>,\n equalityFn?: EqualityFn<TSelected>\n ) => TSelected;\n};\n\n/**\n * Binds Zuno to React.\n * @param zuno The Zuno instance to bind.\n * @returns A React-enhanced Zuno instance.\n */\nexport const bindReact = (zuno: ZunoCore) => {\n /**\n * A custom hook for accessing a Zuno store in a React component.\n */\n const useExternalStore = <TState, TSelected = TState>(\n readable: ZunoReadable<TState>,\n selector?: Selector<TState, TSelected>,\n equalityFn: EqualityFn<TSelected> = defaultEq\n ): TSelected => {\n const select = React.useMemo(() => {\n return (selector ??\n ((s: TState) => s as unknown as TSelected)) as Selector<TState, TSelected>;\n }, [selector]);\n\n const lastRef = React.useRef<TSelected | null>(null);\n const hasLast = React.useRef(false);\n\n const getSnapshot = React.useCallback(() => {\n const next = select(readable.getSnapshot());\n\n if (!hasLast.current) {\n hasLast.current = true;\n lastRef.current = next;\n return next;\n }\n\n const prev = lastRef.current as TSelected;\n if (equalityFn(prev, next)) return prev;\n\n lastRef.current = next;\n return next;\n }, [readable, select, equalityFn]);\n\n const subscribe = React.useCallback(\n (onChange: () => void) => readable.subscribe(onChange),\n [readable]\n );\n\n const getServerSnapshot = React.useCallback(() => {\n const s = readable.getServerSnapshot ? readable.getServerSnapshot() : readable.getSnapshot();\n return select(s);\n }, [readable, select]);\n\n React.useEffect(() => {\n hasLast.current = false;\n lastRef.current = null;\n }, [select, equalityFn]);\n\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n };\n\n /**\n * Creates a React-enhanced store.\n */\n const store = <T,>(storeKey: string, init: () => T): ReactBoundStore<T> => {\n const base = zuno.store<T>(storeKey, init);\n\n return {\n ...base,\n use: <TSelected = T>(\n selector?: Selector<T, TSelected>,\n equalityFn: EqualityFn<TSelected> = defaultEq\n ) => {\n const readable = React.useMemo(\n () => toReadable(base.raw() as ZunoSubscribableStore<T>),\n [storeKey]\n );\n return useExternalStore<T, TSelected>(readable, selector, equalityFn);\n },\n };\n };\n\n return {\n ...zuno,\n store,\n };\n};\n\n/**\n * Creates a Zuno instance and returns a React-enhanced instance.\n * \n * @param opts The options for the Zuno instance.\n * @returns An object with a `store` method that returns stores with a `use` hook.\n */\nexport const createZunoReact = (opts: CreateZunoOptions) => {\n const zuno = createZuno(opts);\n return bindReact(zuno);\n};\n\n// Convenience re-export\nexport type { ZunoReadable } from \"@iadev93/zuno\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iadev93/zuno-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -11,17 +11,19 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
15
16
|
}
|
|
16
17
|
},
|
|
17
18
|
"peerDependencies": {
|
|
18
19
|
"react": ">=18",
|
|
19
|
-
"@iadev93/zuno": "0.0.
|
|
20
|
+
"@iadev93/zuno": "0.0.7"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
|
22
23
|
"@types/react": "^18.0.0",
|
|
24
|
+
"tsup": "^8.5.1",
|
|
23
25
|
"typescript": "^5.9.3",
|
|
24
|
-
"@iadev93/zuno": "0.0.
|
|
26
|
+
"@iadev93/zuno": "0.0.7"
|
|
25
27
|
},
|
|
26
28
|
"keywords": [
|
|
27
29
|
"zuno",
|
|
@@ -45,6 +47,7 @@
|
|
|
45
47
|
"author": "Ibrahim Aftab",
|
|
46
48
|
"license": "MIT",
|
|
47
49
|
"scripts": {
|
|
48
|
-
"build": "
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"dev": "tsup --watch"
|
|
49
52
|
}
|
|
50
53
|
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,qBAAqB,EAA0B,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE9H;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,CAAC,MAAM,EAAE,SAAS,IAAI,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;AAQvE;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,CAAC;IACb,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAClD,GAAG,EAAE,MAAM,qBAAqB,CAAC,CAAC,CAAC,CAAC;CACrC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IACzD,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACnF,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG;IAC/C;;;OAGG;IACH,GAAG,EAAE,CAAC,SAAS,GAAG,CAAC,EACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,EACjC,UAAU,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,KAC/B,SAAS,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,QAAQ;YAsDvB,CAAC,YAAa,MAAM,QAAQ,MAAM,CAAC,KAAG,eAAe,CAAC,CAAC,CAAC;QA9EnE,CAAC,YAAY,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;QAC9E,CAAC,YAAY,MAAM,SAAS,MAAM,CAAC,GAAG,CAAC;WACpC,MAAM,IAAI;CAkGlB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,iBAAiB;YA9BtC,CAAC,YAAa,MAAM,QAAQ,MAAM,CAAC,KAAG,eAAe,CAAC,CAAC,CAAC;QA9EnE,CAAC,YAAY,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;QAC9E,CAAC,YAAY,MAAM,SAAS,MAAM,CAAC,GAAG,CAAC;WACpC,MAAM,IAAI;CA6GlB,CAAC;AAGF,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|