chrono-state-z 2.0.1 → 2.2.0

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 CHANGED
@@ -1,4 +1,4 @@
1
- # ⚙️ chrono-state-z
1
+ # ⏱️ chrono-state-z
2
2
 
3
3
  [![NPM](https://img.shields.io/npm/v/chrono-state-z.svg)](https://www.npmjs.com/package/chrono-state-z) ![Downloads](https://img.shields.io/npm/dt/chrono-state-z.svg)
4
4
 
@@ -6,20 +6,15 @@
6
6
 
7
7
  ---
8
8
 
9
- **chrono-state-z** is a **reactive, intent-first state runtime**
10
- designed to keep **business logic outside React**.
9
+ **chrono-state-z** is a reactive state runtime that keeps business logic outside React.
10
+ It provides **atoms, computed values, async state, effects, scheduling**, with a **headless core** and **thin React bindings**.
11
11
 
12
- It provides **atoms, computed values, async state, effects, scheduling**,
13
- with a **headless core** and **thin React bindings**.
14
-
15
- > **React renders state. Logic lives elsewhere.**
12
+ > **React renders. Logic lives elsewhere.**
16
13
 
17
14
  ---
18
15
 
19
16
  ## ✨ Why chrono-state-z?
20
17
 
21
- Use chrono-state-z when you need:
22
-
23
18
  - Predictable state & side-effects
24
19
  - Complex async flows (fetch → invalidate → retry)
25
20
  - Logic reusable outside React (tests, workers, backend)
@@ -43,12 +38,50 @@ Use chrono-state-z when you need:
43
38
  ## 📦 Installation
44
39
 
45
40
  ```bash
46
- npm install react ## for react
47
- npm install intentx-core-z chrono-state-z
41
+ npm install chrono-state-z
42
+ # If using React:
43
+ npm install react
48
44
  ```
49
45
 
50
46
  ---
51
47
 
48
+ ## ⚡ Quick Start
49
+
50
+ ```ts
51
+ import { atom, computed, asyncAtom } from "chrono-state-z";
52
+
53
+ const count = atom(0);
54
+ const double = computed(() => count() * 2);
55
+
56
+ const user = asyncAtom(async () =>
57
+ fetch("https://jsonplaceholder.typicode.com/todos/1")
58
+ .then(r => r.json())
59
+ );
60
+ ```
61
+
62
+ ```ts
63
+ import { useAtom, useComputed } from "chrono-state-z";
64
+
65
+ function App() {
66
+ const value = useAtom(count);
67
+ const doubled = useComputed(double);
68
+ const username = useComputed(() => user()?.title);
69
+
70
+ return (
71
+ <button onClick={() => count.set(c => c + 1)}>
72
+ {value}
73
+ </button>
74
+ );
75
+ }
76
+
77
+ ```
78
+
79
+ ✨ Fine-grained updates.
80
+ ✨ Suspense-ready async.
81
+ ✨ No reducers. No boilerplate.
82
+
83
+ ---
84
+
52
85
  ## 🔹 Core Usage
53
86
 
54
87
  ### Atom & Computed
@@ -208,7 +241,7 @@ import { computed, useComputed } from 'chrono-state-z'
208
241
  const total = computed(() => price() * qty())
209
242
 
210
243
  function TotalView() {
211
- const value = useComputed(() => total())
244
+ const value = useComputed(total)
212
245
  return <div>Total: {value}</div>
213
246
  }
214
247
  ```
@@ -218,8 +251,7 @@ function TotalView() {
218
251
  ### useAtomSelector
219
252
 
220
253
  ```tsx
221
- import { atom, useAtomSelector } from 'chrono-state-z'
222
-
254
+ // atom() returns a callable reactive value
223
255
  const user = atom({ id: 1, name: 'Alice', age: 20 })
224
256
 
225
257
  function Username() {
@@ -234,11 +266,13 @@ function Username() {
234
266
 
235
267
  ```tsx
236
268
  import { useStore } from 'chrono-state-z'
269
+ import type { Store } from 'chrono-state-z'
237
270
 
238
- function StoreView({ store }) {
271
+ function StoreView({ store }: { store: Store<any> }) {
239
272
  const state = useStore(store)
240
- return <pre>{JSON.stringify(state)}</pre>
273
+ return <pre>{JSON.stringify(state, null, 2)}</pre>
241
274
  }
275
+
242
276
  ```
243
277
 
244
278
  ---
@@ -246,13 +280,22 @@ function StoreView({ store }) {
246
280
  ### useStoreSelector
247
281
 
248
282
  ```tsx
283
+ // Only re-renders when saving changes, not the whole store.
249
284
  import { useStoreSelector } from 'chrono-state-z'
250
285
 
251
286
  function SavingBadge({ store }) {
252
287
  const saving = useStoreSelector(store, s => s.saving)
288
+ // const saving = useStoreSelector(
289
+ // store,
290
+ // s => s.meta,
291
+ // shallowEqual
292
+ // )
253
293
  return saving ? 'Saving...' : 'Idle'
254
294
  }
295
+
255
296
  ```
297
+ - `selector` should be pure and stable.
298
+ - If you need dynamic selection, memoize the selector.
256
299
 
257
300
  ---
258
301
 
@@ -261,28 +304,48 @@ function SavingBadge({ store }) {
261
304
  ```ts
262
305
  import { useWatch } from 'chrono-state-z'
263
306
 
264
- useWatch(
265
- () => user(),
266
- (u) => {
267
- if (u?.role === 'admin') redirect('/admin')
268
- }
269
- )
307
+ const user = atom<{ role?: string } | null>(null)
308
+
309
+ function AuthGuard() {
310
+ useWatch(
311
+ () => user(),
312
+ (u) => {
313
+ if (u?.role === 'admin') {
314
+ redirect('/admin')
315
+ }
316
+ }
317
+ )
318
+
319
+ return null
320
+ }
321
+
322
+ ```
323
+
324
+ ### AsyncAtom
325
+ ```ts
326
+ const user = asyncAtom(fetchUser)
327
+
328
+ // load explicitly
329
+ await user.load()
330
+
331
+ // read value (throws / suspends if not ready)
332
+ const u = user()
270
333
  ```
271
334
 
272
335
  ---
273
336
 
274
- ## 🧩 Architecture Example
337
+ ## 🧩 Architecture Pattern
275
338
 
276
339
  ```ts
277
340
  import { asyncAtom, computed } from 'chrono-state-z'
278
341
 
279
342
  export function createUserLogic() {
280
343
  const user = asyncAtom(fetchUser)
281
- const username = computed(() => user()?.name ?? 'Guest')
344
+ const name = computed(() => user()?.name ?? 'Guest')
282
345
 
283
346
  return {
284
347
  user,
285
- username,
348
+ name,
286
349
  reload: () => user.invalidate()
287
350
  }
288
351
  }
@@ -291,29 +354,88 @@ export function createUserLogic() {
291
354
  ```tsx
292
355
  function UserView({ logic }) {
293
356
  const user = useAtom(logic.user)
294
- const name = useComputed(() => logic.username())
357
+ const name = useComputed(logic.name)
295
358
 
296
359
  return (
297
- <div>
298
- <h3>Hello {name}</h3>
360
+ <>
361
+ <div>Hello {name}</div>
299
362
  <button onClick={logic.reload}>Reload</button>
300
- </div>
363
+ </>
301
364
  )
302
365
  }
366
+
303
367
  ```
304
368
 
305
369
  ---
306
370
 
307
- ## 📊 Comparison with Other Libraries
371
+ ## 🔍 Comparison
372
+
373
+ <b>This is not about “better” — it's about architectural.</b>
374
+
375
+ | Feature | chrono-state-z | Redux Toolkit | Zustand | Jotai | MobX |
376
+ | --------------------------- | -------------- | ------------- | -------- | ----- | ---- |
377
+ | Fine-grained reactivity | ✅ | ❌ | ⚠️ | ✅ | ✅ |
378
+ | Built-in async primitives | ✅ | ⚠️ | ❌ | ⚠️ | ❌ |
379
+ | Scheduler / priority system | ✅ | ❌ | ❌ | ❌ | ❌ |
380
+ | Headless (non-React) core | ✅ | ✅ | ⚠️ | ⚠️ | ✅ |
381
+ | Boilerplate level | ✅ | ❌ | ✅ | ✅ | ⚠️ |
382
+ | Devtools maturity | ⚠️ | ✅ | ✅ | ⚠️ | ✅ |
383
+ | Learning curve | ⚠️ | ⚠️ | ✅ | ✅ | ⚠️ |
384
+
385
+
386
+ <br />
387
+
388
+ <b>📝 Notes</b>
389
+
390
+ ⚠️ Fine-grained in Zustand: achieved via selectors, but not dependency-tracked graph-level.
391
+
392
+ ⚠️ Async in Redux / Jotai / Recoil: supported via patterns (thunks, query libs, async selectors), not core-first primitives.
393
+
394
+ ⚠️ Headless in Zustand/Jotai: possible, but primarily designed for React usage.
395
+
396
+ ⚠️ Devtools: Redux and MobX have mature ecosystems; newer libs are still evolving.
397
+
398
+ ---
399
+
400
+ ## ⚖️ Strengths Compared to Others
401
+
402
+ <b>vs Redux Toolkit</b>
403
+
404
+ - More fine-grained updates
405
+ - Less reducer boilerplate
406
+ - Built-in reactive primitives
407
+ - Redux has stronger ecosystem & devtools
408
+
409
+ <b>vs Zustand</b>
410
+
411
+ - More structured async handling
412
+ - Explicit intent layer
413
+ - Built-in scheduler support
414
+ - Zustand is simpler & lighter for small apps
415
+
416
+ <b>vs Jotai</b>
417
+
418
+ - More explicit effect + scheduler control
419
+ - Async-first primitives
420
+ - Jotai is more minimal and React-native
421
+
422
+ <b>vs MobX</b>
423
+
424
+ - More explicit dependency graph (no proxy magic)
425
+ - Better control over update priority
426
+ - MobX is more ergonomic for mutable patterns
427
+
428
+ <b>vs Recoil</b>
429
+
430
+ - Headless core (not React-bound)
431
+ - Explicit effect system
432
+ - Recoil has better React DevTools integration
433
+
434
+ <b>vs Solid signals</b>
308
435
 
309
- | Feature | chrono-state-z | Redux | Zustand | Jotai |
310
- |---------------------------|---------------- |-------|--------- |------- |
311
- | Fine-grained reactivity | ✅ | ❌ | ⚠️ | ✅ |
312
- | Async primitives | ✅ | ⚠️ | ❌ | ⚠️ |
313
- | Intent / effect layer | ✅ | ⚠️ | ❌ | ❌ |
314
- | Scheduler / priority | ✅ | ❌ | ❌ | ❌ |
315
- | Headless (non-React) core | ✅ | ❌ | ⚠️ | ❌ |
316
- | Testability | ✅ | ⚠️ | ⚠️ | ❌ |
436
+ - Similar fine-grained reactive model
437
+ - Designed for React ecosystem
438
+ - Solid is framework-native and extremely optimized
317
439
 
318
440
  ---
319
441
 
@@ -337,4 +459,4 @@ function UserView({ logic }) {
337
459
 
338
460
  ## 📜 License
339
461
 
340
- MIT / Delpi
462
+ MIT
@@ -1,9 +1,10 @@
1
- import { Priority } from "intentx-core-z";
1
+ import { CommonResource } from "./asyncResource";
2
2
  export type AsyncAtom<T> = {
3
- (): T;
4
- set(v: T, p?: Priority): void;
5
- load(): Promise<T>;
6
- cancel(): void;
7
- invalidate(p?: Priority): void;
8
- };
9
- export declare function asyncAtom<T>(fetcher: () => Promise<T>): AsyncAtom<T>;
3
+ (): T | undefined;
4
+ } & CommonResource<T>;
5
+ export declare function asyncAtom<T>(fetcher: (signal?: AbortSignal) => Promise<T>, options?: {
6
+ suspense?: boolean;
7
+ }): AsyncAtom<T>;
8
+ export declare function asyncAtomFamily<K, T>(factory: (key: K) => (signal?: AbortSignal) => Promise<T>, options?: {
9
+ suspense?: boolean;
10
+ }): (key: K) => AsyncAtom<T>;
@@ -1,6 +1,8 @@
1
1
  import type { Priority } from "intentx-core-z";
2
2
  export type AsyncComputed<T> = {
3
- (): T;
4
- invalidate(p?: Priority): void;
3
+ (): T | undefined;
4
+ invalidate(priority?: Priority): void;
5
+ status(): string;
6
+ error(): any;
5
7
  };
6
- export declare function asyncComputed<T>(getter: () => Promise<T>, priority?: Priority): AsyncComputed<T>;
8
+ export declare function asyncComputed<T>(getter: (signal?: AbortSignal) => Promise<T>, priority?: Priority): AsyncComputed<T>;
@@ -0,0 +1,28 @@
1
+ import { Priority } from "intentx-core-z";
2
+ export type CommonResource<T> = {
3
+ load(): Promise<T>;
4
+ cancel(): void;
5
+ invalidate(priority?: Priority): void;
6
+ status(): AsyncState<T>["status"];
7
+ error(): any;
8
+ setSuccess(value: T, priority?: Priority): void;
9
+ };
10
+ export type AsyncState<T> = {
11
+ status: "idle";
12
+ } | {
13
+ status: "loading";
14
+ promise: Promise<T>;
15
+ } | {
16
+ status: "success";
17
+ data: T;
18
+ } | {
19
+ status: "error";
20
+ error: any;
21
+ };
22
+ export type AsyncResource<T> = {
23
+ read(): T | undefined;
24
+ } & CommonResource<T>;
25
+ export declare function createAsyncResource<T>(fetcher: (signal?: AbortSignal) => Promise<T>, options?: {
26
+ suspense?: boolean;
27
+ priority?: Priority;
28
+ }): AsyncResource<T>;
@@ -1,6 +1,6 @@
1
- import { Priority } from "intentx-core-z";
2
- export type Atom<T> = (() => T) & {
3
- set(v: T, p?: Priority): void;
4
- subscribe(fn: () => void): () => void;
5
- };
6
- export declare function atom<T>(initial: T): Atom<T>;
1
+ export type ReadonlyAtom<T> = () => T;
2
+ export declare const atom: <T>(initial: T, options?: import("./createAtomFactory").AtomOptions<T>) => import("./createBaseAtom").Atom<T>;
3
+ export declare const atomMiddleware: <T>(initial: T, middleware?: import("./createAtomFactory").AtomMiddleware<T>) => import("./createBaseAtom").Atom<T>;
4
+ export declare function readonlyAtom<T>(atom: {
5
+ (): T;
6
+ }): ReadonlyAtom<T>;
@@ -0,0 +1,7 @@
1
+ import type { Signal } from "intentx-core-z";
2
+ export type AtomOptions<T> = {
3
+ equals?: (a: T, b: T) => boolean;
4
+ };
5
+ export type AtomMiddleware<T> = (next: T, prev: T) => T;
6
+ export declare function createAtomFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, options?: AtomOptions<T>) => import("./createBaseAtom").Atom<T>;
7
+ export declare function createAtomWithMiddlewareFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, middleware?: AtomMiddleware<T>) => import("./createBaseAtom").Atom<T>;
@@ -0,0 +1,6 @@
1
+ import type { Priority, Signal } from "intentx-core-z";
2
+ export type Atom<T> = Signal<T> & {
3
+ update(fn: (prev: T) => T, priority?: Priority): void;
4
+ };
5
+ export type AtomTransform<T> = (next: T, prev: T) => T;
6
+ export declare function createBaseAtomFactory(signal: <T>(v: T) => Signal<T>): <T>(initial: T, transform?: AtomTransform<T>) => Atom<T>;
@@ -1,11 +1,3 @@
1
- import type { IntentHandler, Scope } from "intentx-core-z";
2
- export type Subscriber = () => void;
3
- export type Store<S extends object> = {
4
- scope: Scope;
5
- state(): S;
6
- setState(fn: (s: S) => void): void;
7
- subscribe(fn: Subscriber): () => void;
8
- emit(type: string, payload?: any): Promise<void>;
9
- on(type: string, handler: IntentHandler<S>): () => void;
10
- };
1
+ import type { Scope } from "intentx-core-z";
2
+ import { Store } from "./types";
11
3
  export declare function createStore<S extends object>(initial: S, scope?: Scope): Store<S>;
@@ -1 +1,7 @@
1
- export declare function factoryAtom<K, A>(factory: (key: K) => A): (key: K) => A;
1
+ export declare function factoryAtom<K, A>(factory: (key: K) => A, options?: {
2
+ weak?: boolean;
3
+ }): {
4
+ (key: K): A;
5
+ delete(key: K): void;
6
+ clear(): void;
7
+ };
@@ -1,14 +1,12 @@
1
- export { atom } from "./atom";
2
- export { computed } from "./computed";
1
+ export * from "./atom";
2
+ export * from "./asyncComputed";
3
+ export * from "./createAtomFactory";
3
4
  export { asyncAtom } from "./asyncAtom";
4
- export { asyncComputed } from "./asyncComputed";
5
- export { effect } from "./effect";
6
- export { watch } from "./watch";
5
+ export { computed } from "intentx-core-z";
6
+ export { effect } from "intentx-core-z";
7
+ export * from "./watch";
7
8
  export { createStore } from "./createStore";
8
- export type { Store } from "./createStore";
9
- export { createScope, defaultScope } from "./scope";
10
- export type { Scope } from "./scope";
11
- export { transaction } from "./transaction";
12
- export { createSelector } from "./selector";
9
+ export * from "./selector";
10
+ export type { Store, Subscriber } from "./types";
13
11
  export { factoryAtom } from "./factoryAtom";
14
- export { createTestRuntime } from "./testRuntime";
12
+ export { transaction } from "./transaction";
@@ -1 +1,7 @@
1
- export declare function createSelector<T, R>(select: (state: T) => R, isEqual?: (a: R, b: R) => boolean): (state: T) => R;
1
+ export type EqualityFn<T> = (a: T, b: T) => boolean;
2
+ export declare function createSelector<S, R>(select: (state: S) => R, isEqual?: EqualityFn<R>): (state: S) => R;
3
+ export declare function selectAtom<T, R>(atom: () => T, selector: (value: T) => R, onChange: (value: R) => void, options?: {
4
+ isEqual?: (a: R, b: R) => boolean;
5
+ immediate?: boolean;
6
+ }): () => void;
7
+ export declare function watchSelector<S, R>(getState: () => S, subscribe: (fn: () => void) => () => void, selector: (state: S) => R, onChange: (value: R) => void, isEqual?: EqualityFn<R>): () => void;
@@ -0,0 +1,12 @@
1
+ import type { IntentHandler, Scope } from "intentx-core-z";
2
+ import { EqualityFn } from "./selector";
3
+ export type Subscriber = () => void;
4
+ export type Store<S extends object> = {
5
+ scope: Scope;
6
+ state(): S;
7
+ setState(fn: (s: S) => void): void;
8
+ subscribe(fn: Subscriber): () => void;
9
+ emit(type: string, payload?: any): Promise<void>;
10
+ on(type: string, handler: IntentHandler<S>): () => void;
11
+ watch<R>(selector: (state: S) => R, onChange: (value: R) => void, isEqual?: EqualityFn<R>): () => void;
12
+ };
@@ -1,2 +1,7 @@
1
1
  import type { Priority } from "intentx-core-z";
2
- export declare function watch<T>(getter: () => T, fn: (value: T) => void, priority?: Priority): () => void;
2
+ export type WatchOptions<T> = {
3
+ immediate?: boolean;
4
+ equals?: (a: T, b: T) => boolean;
5
+ priority?: Priority;
6
+ };
7
+ export declare function watch<T>(getter: () => T, fn: (value: T, prev: T | undefined, onCleanup: (callback: () => void) => void) => void, options?: WatchOptions<T>): () => void;
@@ -1 +1 @@
1
- "use strict";var e=require("intentx-core-z"),t=require("react");function n(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var r=n(t);const c={activeEffect:null};function o(t){let n=t;const r=new Set,o=new Set,u=()=>(c.activeEffect&&o.add(c.activeEffect),n);return u.set=(t,c="normal")=>{Object.is(t,n)||(n=t,o.forEach(t=>e.schedule(t,c)),r.forEach(e=>e()))},u.subscribe=e=>(r.add(e),()=>r.delete(e)),u}function u(t){let n,r=!0;const o=new Set,u=()=>{r||(r=!0,o.forEach(t=>e.schedule(t)))};return()=>{if(c.activeEffect&&o.add(c.activeEffect),r){const e=c.activeEffect;c.activeEffect=u,n=t(),r=!1,c.activeEffect=e}return n}}function s(t,n="normal"){let r=null,o=!1;const u=()=>{if(!o){null==r||r();try{c.activeEffect=u;const e=t();"function"==typeof e&&(r=e)}finally{c.activeEffect=null}}};return e.schedule(u,n),()=>{o=!0,null==r||r(),r=null}}function l(e,t,n="normal"){return s(()=>{t(e())},n)}const a=e.createScope("default");function f(e){return r.useSyncExternalStore(t=>{let n=e();return s(()=>{const r=e();Object.is(n,r)||(n=r,t())})},e,e)}Object.defineProperty(exports,"createScope",{enumerable:!0,get:function(){return e.createScope}}),Object.defineProperty(exports,"transaction",{enumerable:!0,get:function(){return e.batch}}),exports.asyncAtom=function(t){const n=o(null);let r=null,c=!1;const u=()=>(r||(c=!1,r=t().then(e=>(c||n.set(e),e)).finally(()=>{r=null})),r),s=()=>{c=!0,r=null},l=()=>{const e=n();if(null===e)throw u();return e};return l.set=n.set,l.load=u,l.cancel=s,l.invalidate=(t="normal")=>{s(),e.schedule(()=>{try{u()}catch{}},t)},l},exports.asyncComputed=function(t,n="normal"){const r=o(void 0);let c=null,u=!1,s=null;const l=()=>(c||(u=!1,s=null,c=t().then(e=>(u||r.set(e,n),e)).catch(e=>{throw u||(s=e),e}).finally(()=>{c=null})),c),a=()=>{const e=r();if(s)throw s;if(void 0===e)throw l();return e};return a.invalidate=(t=n)=>{u=!0,c=null,e.schedule(()=>{try{l()}catch{}},t)},a},exports.atom=o,exports.computed=u,exports.createSelector=function(e,t=Object.is){let n,r=!1;return c=>{const o=e(c);return r&&t(n,o)?n:(r=!0,n=o,o)}},exports.createStore=function(t,n=a){let r=t;const c=new Set,o=e.createIntentBus((e,t)=>{const n=new AbortController;return{payload:e,scope:t,state:r,signal:n.signal,setState(e){e(r),c.forEach(e=>e())},emit:(e,n)=>o.emit(e,n,t)}});return{scope:n,state:()=>r,setState(e){e(r),c.forEach(e=>e())},subscribe:e=>(c.add(e),()=>c.delete(e)),emit:(e,t)=>o.emit(e,t,n),on:(e,t)=>o.on(e,t,n)}},exports.createTestRuntime=function(){let e=[];return{schedule(t){e.push(t)},flushEffects(){for(;e.length;)e.shift()()}}},exports.defaultScope=a,exports.effect=s,exports.factoryAtom=function(e){const t=new Map;return n=>{let r=t.get(n);return r||(r=e(n),t.set(n,r)),r}},exports.scheduleReactJob=function(e,n="normal"){"low"===n?t.startTransition(e):e()},exports.useAtom=f,exports.useBatch=function(){return e.batch},exports.useComputed=function(e){return f(r.useMemo(()=>u(e),[e]))},exports.useEffectReact=function(e,t="normal"){r.useEffect(()=>{const n=s(e,t);return()=>n()},[e,t])},exports.useFactoryAtom=function(e,t){return f(e(t))},exports.useStore=function(e){return t.useSyncExternalStore(e.subscribe,e.state,e.state)},exports.useStoreSelector=function(e,n,r=Object.is){const c=t.useRef(null),o=()=>{const t=n(e.state()),o=c.current;return null!==o&&r(o,t)?o:(c.current=t,t)};return t.useSyncExternalStore(e.subscribe,o,o)},exports.useWatch=function(e,t){r.useEffect(()=>{const n=l(e,t);return()=>null==n?void 0:n()},[e,t])},exports.watch=l;
1
+ "use strict";var e=require("intentx-core-z"),t=require("react");function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}}),t.default=e,Object.freeze(t)}var n=r(t);function o(e){return function(t,r){const n=e(t),o=n.set;return n.set=(e,t="normal")=>{const s=n(),c=r?r(e,s):e;o(c,t)},n.update=(e,t="normal")=>{n.set(e(n()),t)},n}}function s(e){const t=o(e);return function(e,r){var n;const o=null!==(n=null==r?void 0:r.equals)&&void 0!==n?n:Object.is;return t(e,(e,t)=>o(e,t)?t:e)}}function c(e){const t=o(e);return function(e,r){return t(e,r)}}const u=s(e.signal),a=c(e.signal);function i(t,r){var n,o;const s=null!==(n=null==r?void 0:r.suspense)&&void 0!==n&&n,c=null!==(o=null==r?void 0:r.priority)&&void 0!==o?o:"normal",a=u({status:"idle"});let i=null;const l=()=>{const e=a();if("loading"===e.status)return e.promise;null==i||i.abort(),i=new AbortController;const r=t(i.signal).then(e=>(a.set({status:"success",data:e},c),e)).catch(e=>{if("AbortError"===(null==e?void 0:e.name))return Promise.resolve(void 0);throw a.set({status:"error",error:e}),e});return a.set({status:"loading",promise:r},c),r},f=()=>{null==i||i.abort()};return{read:()=>{const e=a();switch(e.status){case"success":return e.data;case"error":if(s)throw e.error;return;case"loading":if(s)throw e.promise;return;case"idle":const t=l();if(s)throw t;return}},load:l,cancel:f,invalidate:(t=c)=>{f(),a.set({status:"idle"},t),e.schedule(l,t)},status:()=>a().status,error:()=>"error"===a().status?a().error:void 0,setSuccess:(e,t=c)=>{a.set({status:"success",data:e},t)}}}function l(t,r,n){const{immediate:o=!1,equals:s=Object.is,priority:c="normal"}=null!=n?n:{};let u,a,i=!1;const l=e.effect(()=>{const e=t();if(!i)return i=!0,o&&f(e,u),void(u=e);s(e,u)||(f(e,u),u=e)},c);function f(e,t){const n=a;a=void 0,null==n||n(),r(e,t,e=>{a=e})}return()=>{null==a||a(),l()}}function f(e,t=Object.is){let r,n=!1;return o=>{const s=e(o);return n&&t(r,s)?r:(n=!0,r=s,s)}}function d(e,t,r,n,o=Object.is){const s=f(r,o);let c=!1;const u=()=>{c||n(s(e()))};u();const a=t(u);return()=>{c=!0,a()}}const p=e.createScope("default");function m(t){return n.useSyncExternalStore(r=>e.effect(()=>{t(),r()}),t,t)}Object.defineProperty(exports,"computed",{enumerable:!0,get:function(){return e.computed}}),Object.defineProperty(exports,"createScope",{enumerable:!0,get:function(){return e.createScope}}),Object.defineProperty(exports,"effect",{enumerable:!0,get:function(){return e.effect}}),Object.defineProperty(exports,"transaction",{enumerable:!0,get:function(){return e.batch}}),exports.asyncAtom=function(e,t){const r=i(e,t),n=()=>r.read();return n.load=r.load,n.cancel=r.cancel,n.invalidate=r.invalidate,n.status=r.status,n.error=r.error,n.setSuccess=e=>r.setSuccess(e),n},exports.asyncComputed=function(e,t="normal"){const r=i(e,{suspense:!0,priority:t}),n=()=>r.read();return n.invalidate=r.invalidate,n.status=r.status,n.error=r.error,n},exports.atom=u,exports.atomMiddleware=a,exports.createAtomFactory=s,exports.createAtomWithMiddlewareFactory=c,exports.createSelector=f,exports.createStore=function(t,r=p){let n=t;const o=new Set,s=e.createIntentBus((e,t)=>{const r=new AbortController;return{payload:e,scope:t,state:n,signal:r.signal,setState(e){e(n),o.forEach(e=>e())},emit:(e,r)=>s.emit(e,r,t)}});return{scope:r,state:()=>n,setState(e){e(n),o.forEach(e=>e())},subscribe:e=>(o.add(e),()=>o.delete(e)),emit:(e,t)=>s.emit(e,t,r),on:(e,t)=>s.on(e,t,r),watch:(e,t,r)=>d(()=>n,e=>(o.add(e),()=>o.delete(e)),e,t,r)}},exports.factoryAtom=function(e,t){var r;const n=null!==(r=null==t?void 0:t.weak)&&void 0!==r&&r,o=n?new WeakMap:new Map,s=t=>{const r=o.get(t);if(void 0!==r)return r;const n=e(t);return o.set(t,n),n};return s.delete=e=>{n||o.delete(e)},s.clear=()=>{n||o.clear()},s},exports.readonlyAtom=function(e){return()=>e()},exports.scheduleReactJob=function(e,r="normal"){"low"===r?t.startTransition(e):e()},exports.selectAtom=function(t,r,n,o){var s;const c=null!==(s=null==o?void 0:o.isEqual)&&void 0!==s?s:Object.is;let u;return e.effect(()=>{const e=r(t());void 0!==u&&c(u,e)||(u=e,((null==o?void 0:o.immediate)||void 0!==u)&&n(e))})},exports.useAtom=m,exports.useAtomSelector=function(r,n,o=Object.is){const s=t.useRef(f(n,o)),c=()=>s.current(r());return t.useSyncExternalStore(t=>e.effect(()=>{r(),t()}),c,c)},exports.useBatch=function(){return e.batch},exports.useComputed=function(t,r=[]){return m(n.useMemo(()=>e.computed(t),r))},exports.useEffectReact=function(t,r="normal"){const o=n.useRef(t);o.current=t,n.useEffect(()=>{const t=e.effect(()=>{o.current()},r);return()=>t()},[r])},exports.useFactoryAtom=function(e,t){const r=n.useRef(e);r.current=e;const o=n.useRef(null),s=n.useRef(null);return null!==o.current&&s.current===t||(o.current=r.current(t),s.current=t),m(o.current)},exports.useStore=function(e){return t.useSyncExternalStore(e.subscribe,e.state,e.state)},exports.useStoreSelector=function(e,t,r=Object.is){const o=n.useRef(t);o.current=t;const s=n.useRef(f(e=>o.current(e),r)),c=n.useCallback(()=>s.current(e.state()),[e]);return n.useSyncExternalStore(e.subscribe,c,c)},exports.useWatch=function(e,t,r){const o=n.useRef(t);o.current=t;const s=n.useRef(r);s.current=r,n.useEffect(()=>{const t=l(e,e=>{o.current(e)},s.current);return()=>null==t?void 0:t()},[e])},exports.watch=l,exports.watchSelector=d;
package/build/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export { createScope } from "intentx-core-z";
2
+ export type { Scope } from "intentx-core-z";
1
3
  export * from './core';
2
4
  export * from './react';
@@ -1 +1 @@
1
- import{schedule as t,createScope as n,createIntentBus as e,batch as r}from"intentx-core-z";export{createScope,batch as transaction}from"intentx-core-z";import*as c from"react";import o,{startTransition as u}from"react";const l={activeEffect:null};function f(n){let e=n;const r=new Set,c=new Set,o=()=>(l.activeEffect&&c.add(l.activeEffect),e);return o.set=(n,o="normal")=>{Object.is(n,e)||(e=n,c.forEach(n=>t(n,o)),r.forEach(t=>t()))},o.subscribe=t=>(r.add(t),()=>r.delete(t)),o}function i(n){let e,r=!0;const c=new Set,o=()=>{r||(r=!0,c.forEach(n=>t(n)))};return()=>{if(l.activeEffect&&c.add(l.activeEffect),r){const t=l.activeEffect;l.activeEffect=o,e=n(),r=!1,l.activeEffect=t}return e}}function s(n){const e=f(null);let r=null,c=!1;const o=()=>(r||(c=!1,r=n().then(t=>(c||e.set(t),t)).finally(()=>{r=null})),r),u=()=>{c=!0,r=null},l=()=>{const t=e();if(null===t)throw o();return t};return l.set=e.set,l.load=o,l.cancel=u,l.invalidate=(n="normal")=>{u(),t(()=>{try{o()}catch{}},n)},l}function a(n,e="normal"){const r=f(void 0);let c=null,o=!1,u=null;const l=()=>(c||(o=!1,u=null,c=n().then(t=>(o||r.set(t,e),t)).catch(t=>{throw o||(u=t),t}).finally(()=>{c=null})),c),i=()=>{const t=r();if(u)throw u;if(void 0===t)throw l();return t};return i.invalidate=(n=e)=>{o=!0,c=null,t(()=>{try{l()}catch{}},n)},i}function E(n,e="normal"){let r=null,c=!1;const o=()=>{if(!c){null==r||r();try{l.activeEffect=o;const t=n();"function"==typeof t&&(r=t)}finally{l.activeEffect=null}}};return t(o,e),()=>{c=!0,null==r||r(),r=null}}function h(t,n,e="normal"){return E(()=>{n(t())},e)}const d=n("default");function m(t,n=d){let r=t;const c=new Set,o=e((t,n)=>{const e=new AbortController;return{payload:t,scope:n,state:r,signal:e.signal,setState(t){t(r),c.forEach(t=>t())},emit:(t,e)=>o.emit(t,e,n)}});return{scope:n,state:()=>r,setState(t){t(r),c.forEach(t=>t())},subscribe:t=>(c.add(t),()=>c.delete(t)),emit:(t,e)=>o.emit(t,e,n),on:(t,e)=>o.on(t,e,n)}}function v(t,n=Object.is){let e,r=!1;return c=>{const o=t(c);return r&&n(e,o)?e:(r=!0,e=o,o)}}function b(t){const n=new Map;return e=>{let r=n.get(e);return r||(r=t(e),n.set(e,r)),r}}function S(){let t=[];return{schedule(n){t.push(n)},flushEffects(){for(;t.length;)t.shift()()}}}function p(t){return c.useSyncExternalStore(n=>{let e=t();return E(()=>{const r=t();Object.is(e,r)||(e=r,n())})},t,t)}function w(t){return p(c.useMemo(()=>i(t),[t]))}function y(t,n){return p(t(n))}function x(t){return o.useSyncExternalStore(t.subscribe,t.state,t.state)}function g(t,n,e=Object.is){const r=o.useRef(null),c=()=>{const c=n(t.state()),o=r.current;return null!==o&&e(o,c)?o:(r.current=c,c)};return o.useSyncExternalStore(t.subscribe,c,c)}function j(t,n){c.useEffect(()=>{const e=h(t,n);return()=>null==e?void 0:e()},[t,n])}function O(t,n="normal"){c.useEffect(()=>{const e=E(t,n);return()=>e()},[t,n])}function z(){return r}function M(t,n="normal"){"low"===n?u(t):t()}export{s as asyncAtom,a as asyncComputed,f as atom,i as computed,v as createSelector,m as createStore,S as createTestRuntime,d as defaultScope,E as effect,b as factoryAtom,M as scheduleReactJob,p as useAtom,z as useBatch,w as useComputed,O as useEffectReact,y as useFactoryAtom,x as useStore,g as useStoreSelector,j as useWatch,h as watch};
1
+ import{signal as t,schedule as e,effect as n,createScope as r,createIntentBus as s,batch as o,computed as u}from"intentx-core-z";export{computed,createScope,effect,batch as transaction}from"intentx-core-z";import*as c from"react";import i,{startTransition as a}from"react";function l(t){return function(e,n){const r=t(e),s=r.set;return r.set=(t,e="normal")=>{const o=r(),u=n?n(t,o):t;s(u,e)},r.update=(t,e="normal")=>{r.set(t(r()),e)},r}}function f(t){const e=l(t);return function(t,n){var r;const s=null!==(r=null==n?void 0:n.equals)&&void 0!==r?r:Object.is;return e(t,(t,e)=>s(t,e)?e:t)}}function d(t){const e=l(t);return function(t,n){return e(t,n)}}const v=f(t),m=d(t);function p(t){return()=>t()}function b(t,n){var r,s;const o=null!==(r=null==n?void 0:n.suspense)&&void 0!==r&&r,u=null!==(s=null==n?void 0:n.priority)&&void 0!==s?s:"normal",c=v({status:"idle"});let i=null;const a=()=>{const e=c();if("loading"===e.status)return e.promise;null==i||i.abort(),i=new AbortController;const n=t(i.signal).then(t=>(c.set({status:"success",data:t},u),t)).catch(t=>{if("AbortError"===(null==t?void 0:t.name))return Promise.resolve(void 0);throw c.set({status:"error",error:t}),t});return c.set({status:"loading",promise:n},u),n},l=()=>{null==i||i.abort()};return{read:()=>{const t=c();switch(t.status){case"success":return t.data;case"error":if(o)throw t.error;return;case"loading":if(o)throw t.promise;return;case"idle":const e=a();if(o)throw e;return}},load:a,cancel:l,invalidate:(t=u)=>{l(),c.set({status:"idle"},t),e(a,t)},status:()=>c().status,error:()=>"error"===c().status?c().error:void 0,setSuccess:(t,e=u)=>{c.set({status:"success",data:t},e)}}}function S(t,e="normal"){const n=b(t,{suspense:!0,priority:e}),r=()=>n.read();return r.invalidate=n.invalidate,r.status=n.status,r.error=n.error,r}function w(t,e){const n=b(t,e),r=()=>n.read();return r.load=n.load,r.cancel=n.cancel,r.invalidate=n.invalidate,r.status=n.status,r.error=n.error,r.setSuccess=t=>n.setSuccess(t),r}function h(t,e,r){const{immediate:s=!1,equals:o=Object.is,priority:u="normal"}=null!=r?r:{};let c,i,a=!1;const l=n(()=>{const e=t();if(!a)return a=!0,s&&f(e,c),void(c=e);o(e,c)||(f(e,c),c=e)},u);function f(t,n){const r=i;i=void 0,null==r||r(),e(t,n,t=>{i=t})}return()=>{null==i||i(),l()}}function E(t,e=Object.is){let n,r=!1;return s=>{const o=t(s);return r&&e(n,o)?n:(r=!0,n=o,o)}}function R(t,e,r,s){var o;const u=null!==(o=null==s?void 0:s.isEqual)&&void 0!==o?o:Object.is;let c;return n(()=>{const n=e(t());void 0!==c&&u(c,n)||(c=n,((null==s?void 0:s.immediate)||void 0!==c)&&r(n))})}function x(t,e,n,r,s=Object.is){const o=E(n,s);let u=!1;const c=()=>{u||r(o(t()))};c();const i=e(c);return()=>{u=!0,i()}}const y=r("default");function g(t,e=y){let n=t;const r=new Set,o=s((t,e)=>{const s=new AbortController;return{payload:t,scope:e,state:n,signal:s.signal,setState(t){t(n),r.forEach(t=>t())},emit:(t,n)=>o.emit(t,n,e)}});return{scope:e,state:()=>n,setState(t){t(n),r.forEach(t=>t())},subscribe:t=>(r.add(t),()=>r.delete(t)),emit:(t,n)=>o.emit(t,n,e),on:(t,n)=>o.on(t,n,e),watch:(t,e,s)=>x(()=>n,t=>(r.add(t),()=>r.delete(t)),t,e,s)}}function j(t,e){var n;const r=null!==(n=null==e?void 0:e.weak)&&void 0!==n&&n,s=r?new WeakMap:new Map,o=e=>{const n=s.get(e);if(void 0!==n)return n;const r=t(e);return s.set(e,r),r};return o.delete=t=>{r||s.delete(t)},o.clear=()=>{r||s.clear()},o}function O(t){return c.useSyncExternalStore(e=>n(()=>{t(),e()}),t,t)}function k(t,e,r=Object.is){const s=i.useRef(E(e,r)),o=()=>s.current(t());return i.useSyncExternalStore(e=>n(()=>{t(),e()}),o,o)}function q(){return o}function A(t,e=[]){return O(c.useMemo(()=>u(t),e))}function C(t,e="normal"){const r=c.useRef(t);r.current=t,c.useEffect(()=>{const t=n(()=>{r.current()},e);return()=>t()},[e])}function M(t,e){const n=c.useRef(t);n.current=t;const r=c.useRef(null),s=c.useRef(null);return null!==r.current&&s.current===e||(r.current=n.current(e),s.current=e),O(r.current)}function z(t){return i.useSyncExternalStore(t.subscribe,t.state,t.state)}function P(t,e,n=Object.is){const r=c.useRef(e);r.current=e;const s=c.useRef(E(t=>r.current(t),n)),o=c.useCallback(()=>s.current(t.state()),[t]);return c.useSyncExternalStore(t.subscribe,o,o)}function W(t,e,n){const r=c.useRef(e);r.current=e;const s=c.useRef(n);s.current=n,c.useEffect(()=>{const e=h(t,t=>{r.current(t)},s.current);return()=>null==e?void 0:e()},[t])}function B(t,e="normal"){"low"===e?a(t):t()}export{w as asyncAtom,S as asyncComputed,v as atom,m as atomMiddleware,f as createAtomFactory,d as createAtomWithMiddlewareFactory,E as createSelector,g as createStore,j as factoryAtom,p as readonlyAtom,B as scheduleReactJob,R as selectAtom,O as useAtom,k as useAtomSelector,q as useBatch,A as useComputed,C as useEffectReact,M as useFactoryAtom,z as useStore,P as useStoreSelector,W as useWatch,h as watch,x as watchSelector};
@@ -1,9 +1,10 @@
1
1
  export { useAtom } from './useAtom';
2
+ export { useAtomSelector } from './useAtomSelector';
3
+ export { useBatch } from './useBatch';
2
4
  export { useComputed } from './useComputed';
5
+ export { useEffectReact } from './useEffectReact';
3
6
  export { useFactoryAtom } from './useFactoryAtom';
4
7
  export { useStore } from './useStore';
5
8
  export { useStoreSelector } from './useStoreSelector';
6
9
  export { useWatch } from './useWatch';
7
- export { useEffectReact } from './useEffectReact';
8
- export { useBatch } from './useBatch';
9
10
  export { scheduleReactJob } from './schedule';
@@ -1 +1,2 @@
1
- export declare function useComputed<T>(fn: () => T): T;
1
+ import * as React from 'react';
2
+ export declare function useComputed<T>(fn: () => T, deps?: React.DependencyList): T;
@@ -1,4 +1,4 @@
1
- export declare function useStoreSelector<S, T>(store: {
1
+ export declare function useStoreSelector<S, R>(store: {
2
2
  state(): S;
3
3
  subscribe(fn: () => void): () => void;
4
- }, selector: (state: S) => T, isEqual?: (a: T, b: T) => boolean): T;
4
+ }, selector: (state: S) => R, isEqual?: (a: R, b: R) => boolean): R;
@@ -1 +1,2 @@
1
- export declare function useWatch<T>(getter: () => T, fn: (val: T) => void): void;
1
+ import type { WatchOptions } from "../core/watch";
2
+ export declare function useWatch<T>(getter: () => T, fn: (val: T) => void, options?: WatchOptions<T>): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chrono-state-z",
3
- "version": "2.0.1",
4
- "description": "Reactive, intent-first state runtime with atoms, computed, async state, effects, and FSM. Logic-first, React-agnostic.",
3
+ "version": "2.2.0",
4
+ "description": "A fine-grained, intent-driven reactive state runtime for building complex React logic outside components.",
5
5
  "license": "MIT",
6
6
  "author": "Delpi.Kye",
7
7
  "sideEffects": false,
@@ -9,25 +9,13 @@
9
9
  "main": "build/index.cjs.js",
10
10
  "module": "build/index.esm.js",
11
11
  "types": "build/index.d.ts",
12
-
13
12
  "exports": {
14
13
  ".": {
15
14
  "types": "./build/index.d.ts",
16
15
  "import": "./build/index.esm.js",
17
16
  "require": "./build/index.cjs.js"
18
- },
19
- "./react": {
20
- "types": "./build/react/index.d.ts",
21
- "import": "./build/react/index.esm.js",
22
- "require": "./build/react/index.cjs.js"
23
- },
24
- "./devtools": {
25
- "types": "./build/devtools/index.d.ts",
26
- "import": "./build/devtools/index.esm.js",
27
- "require": "./build/devtools/index.cjs.js"
28
17
  }
29
18
  },
30
-
31
19
  "files": [
32
20
  "build"
33
21
  ],
@@ -43,35 +31,33 @@
43
31
  "type": "git",
44
32
  "url": "https://github.com/delpikye-v/chrono-state.git"
45
33
  },
46
-
47
34
  "homepage": "https://github.com/delpikye-v/chrono-state",
48
-
49
35
  "bugs": {
50
36
  "url": "https://github.com/delpikye-v/chrono-state/issues"
51
37
  },
52
-
53
38
  "keywords": [
54
- "react",
55
39
  "state-management",
40
+ "react-state",
56
41
  "reactive",
42
+ "fine-grained",
43
+ "signals",
57
44
  "atom",
58
45
  "computed",
59
46
  "async-state",
60
- "external-store",
47
+ "scheduler",
48
+ "deterministic",
61
49
  "intent",
62
- "intent-first",
63
50
  "logic-first",
64
51
  "headless",
65
- "fsm",
66
- "effects",
67
- "scheduler"
52
+ "react-hooks",
53
+ "react-18"
68
54
  ],
69
-
70
55
  "peerDependencies": {
71
- "react": "^18.0.0",
72
- "intentx-core-z": "^1.0.0"
56
+ "react": ">=18"
57
+ },
58
+ "dependencies": {
59
+ "intentx-core-z": "^2.2.1"
73
60
  },
74
-
75
61
  "devDependencies": {
76
62
  "@rollup/plugin-commonjs": "^25.0.0",
77
63
  "@rollup/plugin-node-resolve": "^15.2.3",
@@ -1 +0,0 @@
1
- export declare function computed<T>(getter: () => T): () => T;
@@ -1,2 +0,0 @@
1
- import { Priority } from "intentx-core-z";
2
- export declare function effect(fn: () => void | (() => void), priority?: Priority): () => void;
@@ -1,3 +0,0 @@
1
- export declare const effectContext: {
2
- activeEffect: (() => void) | null;
3
- };
@@ -1,22 +0,0 @@
1
- export type NodeType = 'atom' | 'computed' | 'effect';
2
- export type GraphNode = {
3
- id: number;
4
- name?: string;
5
- type: NodeType;
6
- value?: any;
7
- deps: Set<number>;
8
- highlighted?: boolean;
9
- };
10
- export type GraphSnapshotNode = {
11
- id: number;
12
- name?: string;
13
- type: NodeType;
14
- value?: any;
15
- deps: number[];
16
- highlighted?: boolean;
17
- };
18
- export declare function trackNode(type: NodeType, name?: string, value?: any): GraphNode;
19
- export declare function linkNodes(from: GraphNode, to: GraphNode): void;
20
- export declare function getGraphSnapshot(): GraphSnapshotNode[];
21
- export declare function highlightNode(id: number): void;
22
- export declare function clearHighlights(): void;
@@ -1,4 +0,0 @@
1
- import { Scope } from "intentx-core-z";
2
- export { createScope } from "intentx-core-z";
3
- export type { Scope } from "intentx-core-z";
4
- export declare const defaultScope: Scope;
@@ -1,9 +0,0 @@
1
- import type { IntentHandler } from "intentx-core-z";
2
- export type Subscriber = () => void;
3
- export type Store<S extends object> = {
4
- state(): S;
5
- setState(fn: (s: S) => void): void;
6
- subscribe(fn: Subscriber): () => void;
7
- emit(intent: string, payload?: any): Promise<void>;
8
- on(intent: string, handler: IntentHandler<S>): () => void;
9
- };
@@ -1,6 +0,0 @@
1
- type Job = () => void;
2
- export declare function createTestRuntime(): {
3
- schedule(job: Job): void;
4
- flushEffects(): void;
5
- };
6
- export {};
@@ -1,4 +0,0 @@
1
- export declare function useScopedStore<S>(store: {
2
- state(): S;
3
- subscribe(fn: () => void): () => void;
4
- }): S;