@yoltra/react 0.1.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 ADDED
@@ -0,0 +1,411 @@
1
+ ![yoltra logo](../../assets/yoltra-logo.png)
2
+
3
+ # @yoltra/react
4
+
5
+ > [ 🇲🇽 Versión en Español](https://github.com/yoltra/yoltra/blob/main/packages/react/README.es.md) 
6
+ > |   👉 🇺🇸 English Version
7
+
8
+ ![npm downloads](https://badgen.net/npm/dm/@yoltra/react)
9
+ ![License](https://badgen.net/npm/license/@yoltra/react)
10
+
11
+ **React hooks for [yoltra](https://github.com/yoltra/yoltra/blob/main/README.md) with
12
+ fine-grained path subscriptions.**
13
+
14
+ Subscribe to `"items.0.title"` or `"items.*.done"` — the component re-renders only when that
15
+ exact path changes. No selectors, no memoization, no manual optimization.
16
+
17
+ [See the flamegraph comparison (Redux vs yoltra).](https://github.com/yoltra/yoltra/blob/main/examples/v0/yoltra-in-react/redux-yoltra-profiler.md)
18
+
19
+ ---
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @yoltra/core @yoltra/react
25
+ ```
26
+
27
+ **Peer dependencies:** React 18+
28
+
29
+ ---
30
+
31
+ ## Setup with `createHooks` (recommended)
32
+
33
+ `createHooks` binds fully-typed hooks to your store context. All type parameters are inferred —
34
+ no explicit generics needed in components.
35
+
36
+ ### 1. Define types and store
37
+
38
+ ```typescript
39
+ // store.ts
40
+ import { createStore, eventKeys } from "@yoltra/core";
41
+
42
+ export type AppEM = {
43
+ counter: { increment: number; decrement: number; reset: null };
44
+ };
45
+
46
+ export type AppState = { counter: { value: number } };
47
+
48
+ export const store = createStore<AppState, AppEM>({
49
+ name: "App",
50
+ reducer: {
51
+ counter: {
52
+ state: { value: 0 },
53
+ when: {
54
+ keys: eventKeys<AppEM>()([
55
+ ["counter", "increment"],
56
+ ["counter", "decrement"],
57
+ ["counter", "reset"],
58
+ ]),
59
+ },
60
+ reducer: (state, event) => {
61
+ switch (event.type) {
62
+ case "increment":
63
+ return { value: state.value + event.payload };
64
+ case "decrement":
65
+ return { value: state.value - event.payload };
66
+ case "reset":
67
+ return { value: 0 };
68
+ default:
69
+ return state;
70
+ }
71
+ },
72
+ },
73
+ },
74
+ });
75
+ ```
76
+
77
+ ### 2. Create typed hooks
78
+
79
+ ```typescript
80
+ // hooks.ts
81
+ import { createContext } from "react";
82
+
83
+ import { createHooks } from "@yoltra/react";
84
+ import type { StoreInstance } from "@yoltra/core";
85
+
86
+ import type { AppState, AppEM } from "./store";
87
+
88
+ export const AppStoreContext = createContext<StoreInstance<"counter", AppState, AppEM> | null>(
89
+ null,
90
+ );
91
+
92
+ export const {
93
+ useStore,
94
+ useEmit,
95
+ useSelector,
96
+ useAtomicProp,
97
+ useAtomicProps,
98
+ useEvent,
99
+ shallowEqual,
100
+ } = createHooks(AppStoreContext);
101
+ ```
102
+
103
+ ### 3. Provide and use
104
+
105
+ ```tsx
106
+ // App.tsx
107
+ import { store } from "./store";
108
+ import { AppStoreContext, useAtomicProp, useEmit } from "./hooks";
109
+
110
+ function Counter() {
111
+ const value = useAtomicProp({ reducer: "counter", property: "value" });
112
+ const emit = useEmit();
113
+
114
+ return (
115
+ <div>
116
+ <h1>Count: {value}</h1>
117
+ <button onClick={() => emit("counter", "increment", 1)}>+</button>
118
+ <button onClick={() => emit("counter", "decrement", 1)}>-</button>
119
+ <button onClick={() => emit("counter", "reset", null)}>Reset</button>
120
+ </div>
121
+ );
122
+ }
123
+
124
+ export function App() {
125
+ return (
126
+ <AppStoreContext.Provider value={store}>
127
+ <Counter />
128
+ </AppStoreContext.Provider>
129
+ );
130
+ }
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Hooks API
136
+
137
+ ### `useAtomicProp({ reducer, property }, map?, isEqual?)`
138
+
139
+ Fine-grained single-path selector. Re-renders only when the specified path changes.
140
+
141
+ ```tsx
142
+ // Exact path — re-renders when items[0].title changes
143
+ const title = useAtomicProp({
144
+ reducer: "todos",
145
+ property: "items.0.title",
146
+ });
147
+
148
+ // With mapper — derive a value from the path
149
+ const count = useAtomicProp({ reducer: "todos", property: "items" }, (items) => items.length);
150
+
151
+ // Wildcard pattern — re-renders when any item changes
152
+ const allTitles = useAtomicProp(
153
+ { reducer: "todos", property: "items.**" },
154
+ (state) => state.items.map((t) => t.title),
155
+ shallowEqual,
156
+ );
157
+ ```
158
+
159
+ **Supported patterns:**
160
+
161
+ - `"items.0.title"` — exact path (including numeric array indices)
162
+ - `"items.*.title"` — `*` matches one segment
163
+ - `"items.**"` — `**` matches zero or more segments
164
+
165
+ ---
166
+
167
+ ### `useAtomicProps(specs, selector, isEqual?)`
168
+
169
+ Multi-path selector. Subscribes to several paths and recomputes when any change.
170
+
171
+ ```tsx
172
+ const filtered = useAtomicProps(
173
+ [
174
+ { reducer: "todos", property: "items.**" },
175
+ { reducer: "filter", property: "q" },
176
+ ],
177
+ (state) => state.todos.items.filter((item) => item.title.includes(state.filter.q)),
178
+ shallowEqual,
179
+ );
180
+ ```
181
+
182
+ ---
183
+
184
+ ### `useEvent(channel, type, handler, phase?)`
185
+
186
+ Subscribe to store events from a component. Does not affect event flow — fire-and-forget.
187
+
188
+ ```tsx
189
+ // Committed events (default) — events that passed middleware
190
+ useEvent("ui", "save", (event) => {
191
+ showToast("Saved!");
192
+ });
193
+
194
+ // Uncommitted events — events rejected by middleware
195
+ useEvent(
196
+ "ui",
197
+ "delete",
198
+ (event) => {
199
+ showToast("Delete was blocked by permissions");
200
+ },
201
+ "uncommitted",
202
+ );
203
+
204
+ // All events — distinguish by phase
205
+ useEvent(
206
+ "ui",
207
+ "action",
208
+ (event, getState, emit, phase) => {
209
+ console.log(`Action ${phase}:`, event.type);
210
+ },
211
+ "all",
212
+ );
213
+ ```
214
+
215
+ **Phases:**
216
+
217
+ - `'committed'` (default) — events that passed middleware and reached reducers
218
+ - `'uncommitted'` — events rejected by middleware
219
+ - `'all'` — both, with `phase` parameter to distinguish
220
+
221
+ ---
222
+
223
+ ### `useEmit()`
224
+
225
+ Returns the store's typed `emit` function (stable reference).
226
+
227
+ ```tsx
228
+ const emit = useEmit();
229
+ await emit("counter", "increment", 1);
230
+ ```
231
+
232
+ ---
233
+
234
+ ### `useSelector(selector, isEqual?)`
235
+
236
+ Coarse-grained selector via `useSyncExternalStore`. Re-renders when the selected value changes.
237
+
238
+ ```tsx
239
+ const count = useSelector((state) => state.counter.value);
240
+ ```
241
+
242
+ ---
243
+
244
+ ### `useStore()`
245
+
246
+ Returns the store instance. Throws if called outside a provider.
247
+
248
+ ```tsx
249
+ const store = useStore();
250
+ const state = store.getState();
251
+ ```
252
+
253
+ ---
254
+
255
+ ## Suspense Hooks
256
+
257
+ ### `useSuspenseAtomicProp(spec, options)`
258
+
259
+ Suspense-compatible version of `useAtomicProp`. Throws a promise while loading, caught by the
260
+ nearest `<Suspense>` boundary.
261
+
262
+ ```tsx
263
+ function UserName({ userId }: { userId: string }) {
264
+ const name = useSuspenseAtomicProp(
265
+ { reducer: "users", property: `byId.${userId}.name` },
266
+ {
267
+ load: async (name, slice) => name ?? (await fetchUser(userId)).name,
268
+ staleTime: 30_000,
269
+ },
270
+ );
271
+ return <span>{name}</span>;
272
+ }
273
+
274
+ // Usage
275
+ <Suspense fallback={<Spinner />}>
276
+ <UserName userId='123' />
277
+ </Suspense>;
278
+ ```
279
+
280
+ ### `useSuspenseAtomicProps(specs, options)`
281
+
282
+ Multi-path Suspense selector.
283
+
284
+ ```tsx
285
+ const stats = useSuspenseAtomicProps(
286
+ [
287
+ { reducer: "orders", property: "items.**" },
288
+ { reducer: "users", property: "active" },
289
+ ],
290
+ { load: async (state) => computeDashboardStats(state) },
291
+ );
292
+ ```
293
+
294
+ ### Cache utilities
295
+
296
+ ```typescript
297
+ import {
298
+ invalidateAtomicProp,
299
+ invalidateAtomicPropsByReducer,
300
+ clearSuspenseCache,
301
+ } from "@yoltra/react";
302
+
303
+ // Invalidate a specific path's cache
304
+ invalidateAtomicProp("users", "byId.123.name");
305
+
306
+ // Invalidate all cache entries for a reducer
307
+ invalidateAtomicPropsByReducer("users");
308
+
309
+ // Clear everything
310
+ clearSuspenseCache();
311
+ ```
312
+
313
+ ---
314
+
315
+ ## `shallowEqual`
316
+
317
+ Shallow object equality comparator. Use as the `isEqual` argument when your derived value is a
318
+ plain object:
319
+
320
+ ```tsx
321
+ const todos = useAtomicProp(
322
+ { reducer: "todos", property: "items.**" },
323
+ (state) => state.items.map((t) => ({ id: t.id, title: t.title })),
324
+ shallowEqual,
325
+ );
326
+ ```
327
+
328
+ ---
329
+
330
+ ## Performance: Before and After
331
+
332
+ ### Before (coarse-grained)
333
+
334
+ ```tsx
335
+ // Every TodoItem re-renders when ANY todo changes
336
+ function TodoList() {
337
+ const todos = useSelector((state) => state.todos.items);
338
+ return todos.map((todo) => <TodoItem key={todo.id} todo={todo} />);
339
+ }
340
+ ```
341
+
342
+ ### After (fine-grained with yoltra)
343
+
344
+ ```tsx
345
+ // Each TodoItem re-renders ONLY when its own data changes
346
+ function TodoItem({ index }: { index: number }) {
347
+ const title = useAtomicProp({
348
+ reducer: "todos",
349
+ property: `items.${index}.title`,
350
+ });
351
+ const done = useAtomicProp({
352
+ reducer: "todos",
353
+ property: `items.${index}.done`,
354
+ });
355
+ return <div className={done ? "done" : ""}>{title}</div>;
356
+ }
357
+ ```
358
+
359
+ [See the full flamegraph comparison.](https://github.com/yoltra/yoltra/blob/main/examples/v0/yoltra-in-react/redux-yoltra-profiler.md)
360
+
361
+ ---
362
+
363
+ ## React 18+ Compatibility
364
+
365
+ - **Concurrent Mode:** Fully compatible. All hooks use `useSyncExternalStore`.
366
+ - **Strict Mode:** Event deduplication prevents double-processing.
367
+ - **Suspense:** `useSuspenseAtomicProp` and `useSuspenseAtomicProps` throw promises for
368
+ `<Suspense>` boundaries.
369
+
370
+ ---
371
+
372
+ ## Examples
373
+
374
+ - **[Todo App with Profiler](../../examples/v0/yoltra-in-react)** — Full CRUD with flamegraph
375
+ comparison
376
+ - **[Kinetic Logo (3000 particles)](../../examples/v0/yoltra-kinetic-logo)** — Independent
377
+ subscriptions per circle
378
+ - **[Next.js 15 App Router](../../examples/v0/yoltra-in-nextjs)** — SSR + theme switcher
379
+
380
+ ---
381
+
382
+ ## Documentation
383
+
384
+ - **[yoltra Root README](https://github.com/yoltra/yoltra/blob/main/README.md)** — Overview and
385
+ quick start
386
+ - **[@yoltra/core API](https://github.com/yoltra/yoltra/blob/main/packages/core/README.md)** —
387
+ Store, middleware, effects, `When` matchers
388
+ - **[Quick Start Guide](https://github.com/yoltra/yoltra/blob/main/docs/en/QUICK_START_GUIDE.md)**
389
+ — Five steps to a working app
390
+ - **[Library Comparison](https://github.com/yoltra/yoltra/blob/main/docs/en/design/state-management-library-comparison.md)**
391
+ — Architectural comparison
392
+
393
+ ---
394
+
395
+ ## Contributing
396
+
397
+ - [Monorepo Root](../../)
398
+ - [Contributing Guide](../../CONTRIBUTING.md)
399
+
400
+ ---
401
+
402
+ ## Status
403
+
404
+ **Release Candidate** — APIs are stable, used in production, minor changes possible before
405
+ v1.0.0.
406
+
407
+ ---
408
+
409
+ ## License
410
+
411
+ **MIT** — Free to use in commercial and open-source projects.
package/dist/index.cjs ADDED
@@ -0,0 +1,13 @@
1
+ /*!
2
+ * @yoltra/react v0.1.0
3
+ * (c) 2026 Manu Ramirez <@pixerael>
4
+ * License: MIT
5
+ * Homepage: https://yoltra.dev
6
+ */
7
+ "use strict";var ie=Object.defineProperty;var le=(t,r,n)=>r in t?ie(t,r,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[r]=n;var re=(t,r,n)=>le(t,typeof r!="symbol"?r+"":r,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),V=c.createContext(null);var z={exports:{}},I={};var te;function fe(){if(te)return I;te=1;var t=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function n(u,o,s){var d=null;if(s!==void 0&&(d=""+s),o.key!==void 0&&(d=""+o.key),"key"in o){s={};for(var a in o)a!=="key"&&(s[a]=o[a])}else s=o;return o=s.ref,{$$typeof:t,type:u,key:d,ref:o!==void 0?o:null,props:s}}return I.Fragment=r,I.jsx=n,I.jsxs=n,I}var $={};var ne;function pe(){return ne||(ne=1,process.env.NODE_ENV!=="production"&&(function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===ue?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case E:return"Fragment";case T:return"Profiler";case h:return"StrictMode";case C:return"Suspense";case g:return"SuspenseList";case se:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case v:return"Portal";case P:return(e.displayName||"Context")+".Provider";case j:return(e._context.displayName||"Context")+".Consumer";case x:var l=e.render;return e=e.displayName,e||(e=l.displayName||l.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case X:return l=e.displayName||null,l!==null?l:t(e.type)||"Memo";case D:l=e._payload,e=e._init;try{return t(e(l))}catch{}}return null}function r(e){return""+e}function n(e){try{r(e);var l=!1}catch{l=!0}if(l){l=console;var b=l.error,A=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return b.call(l,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",A),r(e)}}function u(e){if(e===E)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===D)return"<...>";try{var l=t(e);return l?"<"+l+">":"<...>"}catch{return"<...>"}}function o(){var e=W.A;return e===null?null:e.getOwner()}function s(){return Error("react-stack-top-frame")}function d(e){if(H.call(e,"key")){var l=Object.getOwnPropertyDescriptor(e,"key").get;if(l&&l.isReactWarning)return!1}return e.key!==void 0}function a(e,l){function b(){q||(q=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",l))}b.isReactWarning=!0,Object.defineProperty(e,"key",{get:b,configurable:!0})}function m(){var e=t(this.type);return Z[e]||(Z[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function f(e,l,b,A,w,k,L,G){return b=k.ref,e={$$typeof:S,type:e,key:l,props:k,_owner:w},(b!==void 0?b:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:m}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:L}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function i(e,l,b,A,w,k,L,G){var R=l.children;if(R!==void 0)if(A)if(ce(R)){for(A=0;A<R.length;A++)p(R[A]);Object.freeze&&Object.freeze(R)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else p(R);if(H.call(l,"key")){R=t(e);var N=Object.keys(l).filter(function(ae){return ae!=="key"});A=0<N.length?"{key: someKey, "+N.join(": ..., ")+": ...}":"{key: someKey}",ee[R+A]||(N=0<N.length?"{"+N.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
8
+ let props = %s;
9
+ <%s {...props} />
10
+ React keys must be passed directly to JSX without using spread:
11
+ let props = %s;
12
+ <%s key={someKey} {...props} />`,A,R,N,R),ee[R+A]=!0)}if(R=null,b!==void 0&&(n(b),R=""+b),d(l)&&(n(l.key),R=""+l.key),"key"in l){b={};for(var U in l)U!=="key"&&(b[U]=l[U])}else b=l;return R&&a(b,typeof e=="function"?e.displayName||e.name||"Unknown":e),f(e,R,k,w,o(),b,L,G)}function p(e){typeof e=="object"&&e!==null&&e.$$typeof===S&&e._store&&(e._store.validated=1)}var y=c,S=Symbol.for("react.transitional.element"),v=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),h=Symbol.for("react.strict_mode"),T=Symbol.for("react.profiler"),j=Symbol.for("react.consumer"),P=Symbol.for("react.context"),x=Symbol.for("react.forward_ref"),C=Symbol.for("react.suspense"),g=Symbol.for("react.suspense_list"),X=Symbol.for("react.memo"),D=Symbol.for("react.lazy"),se=Symbol.for("react.activity"),ue=Symbol.for("react.client.reference"),W=y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=Object.prototype.hasOwnProperty,ce=Array.isArray,J=console.createTask?console.createTask:function(){return null};y={react_stack_bottom_frame:function(e){return e()}};var q,Z={},Q=y.react_stack_bottom_frame.bind(y,s)(),K=J(u(s)),ee={};$.Fragment=E,$.jsx=function(e,l,b,A,w){var k=1e4>W.recentlyCreatedOwnerStacks++;return i(e,l,b,!1,A,w,k?Error("react-stack-top-frame"):Q,k?J(u(e)):K)},$.jsxs=function(e,l,b,A,w){var k=1e4>W.recentlyCreatedOwnerStacks++;return i(e,l,b,!0,A,w,k?Error("react-stack-top-frame"):Q,k?J(u(e)):K)}})()),$}var oe;function de(){return oe||(oe=1,process.env.NODE_ENV==="production"?z.exports=fe():z.exports=pe()),z.exports}var me=de();const ye=({store:t,children:r})=>me.jsx(V.Provider,{value:t,children:r});function Y(t){return t.includes("*")}function _(t){return t.replace(/^\./,"")}function Se(t){return _(t).split(".").filter(Boolean)}function F(t,r){if(!r)return t;let n=t;for(const u of Se(r)){if(n==null)return;n=n[u]}return n}function O(){const t=c.useContext(V);if(!t)throw new Error("useStore must be used inside <StoreProvider>");return t}function be(){return O().emit}function ve(t,r){if(Object.is(t,r))return!0;if(!t||!r)return!1;const n=Object.keys(t),u=Object.keys(r);if(n.length!==u.length)return!1;for(const o of n)if(!Object.is(t[o],r[o]))return!1;return!0}function Ee(t,r=Object.is){const n=O(),u=c.useMemo(()=>s=>n.subscribe(s),[n]),o=c.useMemo(()=>{let s=t(n.getState());return()=>{const d=t(n.getState());return r(s,d)?s:s=d}},[n,t,r]);return c.useSyncExternalStore(u,o,o)}function Ae(t){const r=O(),n=c.useMemo(()=>{const s=_(t.property);return{reducer:t.reducer,property:s}},[t.reducer,t.property]),u=c.useMemo(()=>s=>r.connect({reducer:n.reducer,property:n.property},()=>s()),[r,n]),o=c.useMemo(()=>{const s=Y(n.property),d=()=>{const f=r.getState()[n.reducer];return s?f:F(f,n.property)};let a=d();return()=>{const m=d();return Object.is(a,m)?a:a=m}},[r,n]);return c.useSyncExternalStore(u,o,o)}function Re(t,r,n=Object.is){const u=O(),o=c.useMemo(()=>{const a=_(t.property);return{reducer:t.reducer,property:a}},[t.reducer,t.property]),s=c.useMemo(()=>a=>u.connect({reducer:o.reducer,property:o.property},()=>a()),[u,o]),d=c.useMemo(()=>{const a=Y(o.property),m=()=>{const p=u.getState()[o.reducer],y=a?p:F(p,o.property);return r?r(y):y};let f=m();return()=>{const i=m();return n(f,i)?f:f=i}},[u,o,r,n]);return c.useSyncExternalStore(s,d,d)}function Pe(t,r,n=Object.is){return!r&&!Y(t.property)?Ae(t):Re(t,r,n)}function _e(t,r,n=Object.is){return he(t,r,n)}function he(t,r,n=Object.is){const u=O(),o=c.useRef(0),s=c.useRef(void 0),d=c.useRef(-1),a=c.useMemo(()=>t.map(i=>({reducer:i.reducer,property:Array.isArray(i.property)?i.property.map(p=>_(p)):_(i.property)})),[JSON.stringify(t)]),m=c.useMemo(()=>i=>{const p=()=>{o.current++,i()},y=a.flatMap(S=>(Array.isArray(S.property)?S.property:[S.property]).map(E=>u.connect({reducer:S.reducer,property:E},p)));return()=>{for(const S of y)S()}},[u,a]),f=c.useMemo(()=>()=>{if(d.current!==o.current){const i=r(u.getState()),p=s.current;(p===void 0||!n(p,i))&&(s.current=i),d.current=o.current}return s.current},[u,r,n]);return c.useSyncExternalStore(m,f,f)}function xe(t,r,n,u="committed"){const o=O(),s=c.useRef(n);s.current=n,c.useEffect(()=>o.onEvent(t,r,(d,a,m,f)=>{s.current(d,a,m,f)},u),[o,t,r,u])}class ge{constructor(){re(this,"store",new Map)}read(r,n,u){const o=Date.now(),s=this.store.get(r);if(s&&s.status==="ready"&&(s.expiresAt==null||s.expiresAt>o))return s.value;if(s&&s.status==="pending"&&(s.expiresAt==null||s.expiresAt>o))throw s.promise;if(s&&s.status==="error"&&(s.expiresAt==null||s.expiresAt>o))throw s.error;const d=Promise.resolve().then(n).then(a=>{this.store.set(r,{status:"ready",value:a,expiresAt:u==null?null:Date.now()+u})}).catch(a=>{this.store.set(r,{status:"error",error:a,expiresAt:u==null?null:Date.now()+u})});throw this.store.set(r,{status:"pending",promise:d,expiresAt:u==null?null:Date.now()+u}),d}invalidate(r){this.store.delete(r)}invalidatePrefix(r){for(const n of this.store.keys())n.startsWith(r)&&this.store.delete(n)}clear(){this.store.clear()}}const M=new ge;function B(t,r,n){const u=Array.isArray(r)?r.map(_).sort().join("|"):_(r);return n?`${t}::${u}::${n}`:`${t}::${u}`}function ke(t,r){return Oe(t,r)}function Oe(t,r){const n=O(),u=t.reducer,o=_(t.property),s=B(u,o,r.key),d=c.useMemo(()=>m=>n.connect({reducer:u,property:o},()=>{M.invalidate(s),m()}),[n,u,o,s]),a=c.useMemo(()=>{const m=Y(o);return()=>{var y;const i=n.getState()[u],p=m?i:F(i,o);return M.read(s,()=>r.load(p,i),(y=r.staleTime)!=null?y:0)}},[n,u,o,s,r]);return c.useSyncExternalStore(d,a,a)}function Te(t,r){return je(t,r)}function je(t,r){const n=O(),u=c.useMemo(()=>t.map(a=>({reducer:a.reducer,property:Array.isArray(a.property)?a.property.map(m=>_(m)):_(a.property)})),[JSON.stringify(t)]),o=c.useMemo(()=>{const a=u.map(m=>B(m.reducer,m.property)).sort().join("||");return r.key?`${a}::${r.key}`:a},[u,r.key]),s=c.useMemo(()=>a=>{const m=()=>{M.invalidate(o),a()},f=u.map(i=>n.connect(i,m));return()=>{for(const i of f)i()}},[n,u,o]),d=c.useMemo(()=>()=>{var m;const a=n.getState();return M.read(o,()=>r.load(a),(m=r.staleTime)!=null?m:0)},[n,o,r]);return c.useSyncExternalStore(s,d,d)}function we(t,r,n){M.invalidate(B(t,r,n))}function Me(t){M.invalidatePrefix(`${t}::`)}function Ce(){M.clear()}function Ne(t,r){if(Object.is(t,r))return!0;if(!t||!r)return!1;const n=Object.keys(t),u=Object.keys(r);if(n.length!==u.length)return!1;for(const o of n)if(!Object.is(t[o],r[o]))return!1;return!0}function Ie(t){function r(){const f=c.useContext(t);if(!f)throw new Error("useStore must be used inside <StoreProvider>");return f}function n(){return r().emit}function u(f,i=Object.is){const p=r(),y=c.useMemo(()=>v=>p.subscribe(v),[p]),S=c.useMemo(()=>{let v=f(p.getState());return()=>{const E=f(p.getState());return i(v,E)?v:v=E}},[p,f,i]);return c.useSyncExternalStore(y,S,S)}return{useStore:r,useEmit:n,useSelector:u,useAtomicProp:(f,i,p)=>{const y=r(),S=c.useMemo(()=>{const h=_(f.property);return{reducer:f.reducer,property:h}},[f.reducer,f.property]),v=c.useMemo(()=>h=>y.connect({reducer:S.reducer,property:S.property},()=>h()),[y,S]),E=c.useMemo(()=>{const h=Y(S.property),T=()=>{const C=y.getState()[S.reducer],g=h?C:F(C,S.property);return i?i(g):g},j=p!=null?p:Object.is;let P=T();return()=>{const x=T();return j(P,x)?P:P=x}},[y,S,i,p]);return c.useSyncExternalStore(v,E,E)},useAtomicProps:(f,i,p=Object.is)=>{const y=r(),S=c.useRef(0),v=c.useRef(void 0),E=c.useRef(-1),h=c.useMemo(()=>f.map(P=>({reducer:P.reducer,property:Array.isArray(P.property)?P.property.map(x=>_(x)):_(P.property)})),[JSON.stringify(f)]),T=c.useMemo(()=>P=>{const x=()=>{S.current++,P()},C=h.flatMap(g=>(Array.isArray(g.property)?g.property:[g.property]).map(D=>y.connect({reducer:g.reducer,property:D},x)));return()=>{for(const g of C)g()}},[y,h]),j=c.useMemo(()=>()=>{if(E.current!==S.current){const P=i(y.getState()),x=v.current;(x===void 0||!p(x,P))&&(v.current=P),E.current=S.current}return v.current},[y,i,p]);return c.useSyncExternalStore(T,j,j)},useEvent:(f,i,p,y="committed")=>{const S=r(),v=c.useRef(p);v.current=p,c.useEffect(()=>S.onEvent(f,i,(E,h,T,j)=>{v.current(E,h,T,j)},y),[S,f,i,y])},shallowEqual:Ne}}exports.StoreContext=V;exports.StoreProvider=ye;exports.clearSuspenseCache=Ce;exports.createHooks=Ie;exports.invalidateAtomicProp=we;exports.invalidateAtomicPropsByReducer=Me;exports.shallowEqual=ve;exports.suspenseCache=M;exports.useAtomicProp=Pe;exports.useAtomicProps=_e;exports.useEmit=be;exports.useEvent=xe;exports.useSelector=Ee;exports.useStore=O;exports.useSuspenseAtomicProp=ke;exports.useSuspenseAtomicProps=Te;
13
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/context/StoreContext.ts","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.production.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/cjs/react-jsx-runtime.development.js","../../../common/temp/node_modules/.pnpm/react@19.1.1/node_modules/react/jsx-runtime.js","../src/context/StoreProvider.tsx","../src/utils/path.ts","../src/hooks/hooks.ts","../src/hooks/suspense.ts","../src/hooks/createHooks.ts"],"sourcesContent":["/**\n * @module @yoltra/react\n */\n\nimport { createContext } from \"react\";\nimport type { StoreInstance } from \"@yoltra/core\";\n\n/**\n * React Context carrying a {@link StoreInstance} for yoltra React bindings.\n *\n * @remarks\n * - The default value is `null`. Consumers should either:\n * 1) Be wrapped with {@link StoreProvider}, or\n * 2) Use a helper hook that throws a friendly error when the context is `null`.\n * - You can scope multiple independent stores by nesting multiple providers.\n *\n * @example Basic usage\n * ```tsx\n * import { useContext } from \"react\";\n * import { StoreContext } from \"@yoltra/react\";\n *\n * export function Counter() {\n * const store = useContext(StoreContext);\n * if (!store) throw new Error(\"StoreProvider is missing\");\n * const state = store.getState();\n * return <span>{state.counter.value}</span>;\n * }\n * ```\n *\n * @public\n */\nexport const StoreContext = createContext<StoreInstance<any, any, any> | null>(null);","/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return (type.displayName || \"Context\") + \".Provider\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(\n type,\n key,\n self,\n source,\n owner,\n props,\n debugStack,\n debugTask\n ) {\n self = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== self ? self : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n source,\n self,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n self,\n source,\n getOwner(),\n maybeKey,\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_ELEMENT_TYPE &&\n node._store &&\n (node._store.validated = 1);\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\");\n Symbol.for(\"react.provider\");\n var REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","/**\n * @module @yoltra/react\n */\n\nimport type { StoreInstance } from \"@yoltra/core\";\nimport React, { type ReactNode } from \"react\";\n\nimport { StoreContext } from \"./StoreContext\";\n\n/**\n * React provider that places a {@link StoreInstance} into {@link StoreContext}.\n *\n * @param props.store - The yoltra store instance to expose to descendant components.\n * @param props.children - React subtree that will consume the store.\n *\n * @remarks\n * - Wrap your app (or a subtree) to make the store available via `useContext(StoreContext)`\n * or any higher-level hooks you expose (e.g., `useAtomicProp`, `useEmit`).\n * - You may nest multiple `StoreProvider`s to scope different stores to different subtrees.\n * - In Next.js App Router, this component must be used in a **client** boundary.\n *\n * @example App wrapper with createHooks (recommended)\n * ```tsx\n * // store.ts\n * import { createStore, eventKeys } from '@yoltra/core';\n * import { createContext } from 'react';\n * import { createHooks, StoreProvider } from '@yoltra/react';\n *\n * type AppEM = { ui: { increment: number } };\n * type AppState = { counter: { value: number } };\n *\n * export const store = createStore<AppState, AppEM>({\n * name: 'App',\n * reducer: {\n * counter: {\n * state: { value: 0 },\n * when: { keys: eventKeys<AppEM>()([['ui', 'increment']]) },\n * reducer: (s, evt) => evt.type === 'increment'\n * ? { value: s.value + evt.payload }\n * : s,\n * },\n * },\n * });\n *\n * const AppStoreContext = createContext<typeof store | null>(null);\n * export const { useAtomicProp, useEmit } = createHooks(AppStoreContext);\n *\n * // App.tsx\n * export function App({ children }: { children: React.ReactNode }) {\n * return <StoreProvider store={store}>{children}</StoreProvider>;\n * }\n * ```\n *\n * @public\n */\nexport const StoreProvider: React.FC<{\n /** yoltra store instance placed into context. */\n store: StoreInstance<any, any, any>;\n /** Descendant subtree that can consume the store. */\n children: ReactNode;\n}> = ({ store, children }) => (\n <StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n);\n","/** @internal */\nexport function hasWildcard(p: string): boolean {\n return p.includes(\"*\");\n}\n\n/** @internal */\nexport function normalizePath(p: string): string {\n return p.replace(/^\\./, \"\");\n}\n\n/** @internal */\nexport function splitPath(p: string): string[] {\n return normalizePath(p).split(\".\").filter(Boolean);\n}\n\n/**\n * Reads a dotted path from an object; returns `undefined` when a segment is missing.\n * @internal\n */\nexport function getAtPath(obj: any, path: string): any {\n if (!path) return obj;\n\n let cur = obj;\n for (const seg of splitPath(path)) {\n if (cur == null) return undefined;\n cur = cur[seg];\n }\n\n return cur;\n}\n","/**\n * @module @yoltra/react\n */\n\nimport type {\n DeepReadonly,\n Dotted,\n Emit,\n Event,\n EventMapBase,\n EventPhase,\n PathValue,\n StoreInstance,\n WithGlob,\n} from \"@yoltra/core\";\nimport { useContext, useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport { StoreContext } from \"../context/StoreContext\";\nimport { getAtPath, hasWildcard, normalizePath } from \"../utils/path\";\n\n/**\n * Re-export of {@link PathValue} from `@yoltra/core`.\n *\n * Resolves the TypeScript type at a dotted path `P` within object type `T`.\n * See the core definition for full documentation.\n *\n * @public\n */\nexport type { PathValue };\n\n/**\n * Accepts either a single value or a readonly array of that value.\n * Useful for APIs that take one-or-many keys.\n *\n * @example\n * ```ts\n * function takeIds(ids: OneOrMany<string>) { /* ... *\\/ }\n * takeIds('a');\n * takeIds(['a','b'] as const);\n * ```\n *\n * @public\n */\nexport type OneOrMany<T> = T | readonly T[];\n\n/**\n * Returns the current {@link StoreInstance} from {@link StoreContext}.\n * Throws if used outside of a `<StoreProvider>`.\n *\n * @typeParam EM - Event map type.\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const store = useStore<MyEM, 'counter' | 'todos', AppState>();\n * const state = store.getState();\n * ```\n *\n * @public\n */\nexport function useStore<\n EM extends EventMapBase,\n R extends string,\n S extends Record<R, any>,\n>(): StoreInstance<R, S, EM> {\n const ctx = useContext(StoreContext);\n if (!ctx) throw new Error(\"useStore must be used inside <StoreProvider>\");\n\n return ctx as StoreInstance<R, S, EM>;\n}\n\n/**\n * Returns the store's `emit` function (stable reference).\n *\n * @typeParam EM - Event map type.\n *\n * @example\n * ```tsx\n * const emit = useEmit<MyEM>();\n * await emit('ui', 'toggle', true);\n * ```\n *\n * @public\n */\nexport function useEmit<EM extends EventMapBase>(): Emit<EM> {\n return useStore<EM, any, any>().emit;\n}\n\n/**\n * Shallow object equality using `Object.is` per-key.\n *\n * Useful as the `isEqual` argument for `useAtomicProp` and `useAtomicProps`\n * when the derived value is a plain object. Also available from the object\n * returned by {@link createHooks}.\n *\n * @example\n * ```ts\n * shallowEqual({ a: 1 }, { a: 1 }); // true\n * shallowEqual({ a: 1 }, { a: 2 }); // false\n * ```\n *\n * @public\n */\nexport function shallowEqual<T extends Record<string, any>>(a: T, b: T) {\n if (Object.is(a, b)) return true;\n if (!a || !b) return false;\n\n const ka = Object.keys(a),\n kb = Object.keys(b);\n if (ka.length !== kb.length) return false;\n\n for (const k of ka) {\n if (!Object.is(a[k], (b as any)[k])) return false;\n }\n\n return true;\n}\n\n/**\n * Selects a derived value from the store using an external-store subscription.\n * Re-renders when the selected value changes per `isEqual`.\n *\n * @typeParam S - State type returned by `getState()`.\n * @typeParam T - Selected value type.\n * @param selector - `(state) => value` derived from the current state.\n * @param isEqual - Optional equality comparator (defaults to `Object.is`).\n *\n * @example\n * ```tsx\n * const total = useSelector((s: AppState) => s.todos.items.length);\n * ```\n *\n * @public\n */\nexport function useSelector<S extends Record<any, any>, T>(\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<any, any, S>();\n\n const subscribe = useMemo(() => (notify: () => void) => store.subscribe(notify), [store]);\n\n const getSnapshot = useMemo(() => {\n let last = selector(store.getState() as DeepReadonly<S>);\n return () => {\n const next = selector(store.getState() as DeepReadonly<S>);\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// Strongly-typed implementation for the common case\nfunction useAtomicPropImpl<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n>(spec: { reducer: R1; property: P }): PathValue<S[R1], P> {\n const store = useStore<any, R, S>();\n\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as S;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return source;\n };\n\n let last = read();\n return () => {\n const next = read();\n return Object.is(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot) as PathValue<S[R1], P>;\n}\n\n/** @internal */\nfunction _useAtomicPropImpl<R extends string, S extends Record<R, any>, T = any>(\n spec: { reducer: R; property: string },\n map?: (value: any) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<any, R, S>();\n\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as S;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return map ? map(source) : (source as unknown as T);\n };\n\n let last = read();\n return () => {\n const next = read();\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec, map, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot) as any;\n}\n\n/**\n * Fine-grained **single-path** selector for a reducer's state.\n *\n * Re-renders only when the specified `reducer.property` (dotted path) actually changes.\n * For most applications, prefer using the typed version from {@link createHooks}\n * which infers all type parameters automatically.\n *\n * **Supports**\n * - Exact root prop: `{ reducer: \"todo\", property: \"data\" }`\n * - Exact deep path: `{ reducer: \"todo\", property: \"data.123.title\" }`\n * - Wildcards (pattern): `{ reducer: \"todo\", property: \"data.*\" }` or `\"data.**\"`\n *\n * **Overloads**\n * - Exact path (no `*`): returns the precise `PathValue` when `map` is omitted\n * - Exact path + `map`: returns `T` from `map(value)`\n * - Glob path (with `*`/`**`): requires `map` and returns `T` from `map(state)`\n *\n * @example Via createHooks (recommended)\n * ```tsx\n * const { useAtomicProp } = createHooks(AppStoreContext);\n *\n * function TodoTitle({ index }: { index: number }) {\n * // Types are inferred — no explicit generics needed\n * const title = useAtomicProp({\n * reducer: 'todos',\n * property: `items.${index}.title`,\n * });\n * return <span>{title}</span>;\n * }\n * ```\n *\n * @example Standalone with explicit generics\n * ```tsx\n * const title = useAtomicProp<'todos', AppState, 'todos', 'items.0.title'>(\n * { reducer: 'todos', property: 'items.0.title' }\n * );\n * ```\n *\n * @example Map over exact path\n * ```tsx\n * const len = useAtomicProp(\n * { reducer: 'todos', property: 'items' },\n * items => items.length\n * );\n * ```\n *\n * @example Glob pattern over state\n * ```tsx\n * const titles = useAtomicProp(\n * { reducer: 'todos', property: 'items.**' },\n * state => state.items.map(x => x.title),\n * shallowEqual\n * );\n * ```\n *\n * @public\n */\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n>(spec: { reducer: R1; property: P }): PathValue<S[R1], P>;\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends Dotted<S[R1]>,\n T,\n>(\n spec: { reducer: R1; property: P },\n map: (value: PathValue<S[R1], P>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<\n R extends string,\n S extends Record<R, any>,\n R1 extends R,\n P extends WithGlob<Dotted<S[R1]>>,\n T,\n>(\n spec: { reducer: R1; property: P },\n map: (value: any) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<R extends string, S extends Record<R, any>>(spec: {\n reducer: R;\n property: string;\n}): unknown;\nexport function useAtomicProp<R extends string, S extends Record<R, any>, T>(\n spec: { reducer: R; property: string },\n map: (value: any) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProp<R extends string, S extends Record<R, any>, T = any>(\n spec: { reducer: R; property: string },\n map?: (value: any) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n if (!map && !hasWildcard(spec.property)) {\n return useAtomicPropImpl<R, S, any, any>(spec) as any;\n }\n return _useAtomicPropImpl<R, S, T>(spec, map, isEqual);\n}\n\n/**\n * **Multi-path** fine-grained selector.\n *\n * Subscribes to several `reducer.property` paths (supports deep & wildcard)\n * and recomputes `selector(state)` when any of them change.\n *\n * @typeParam R - Slice name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam T - Derived value type.\n *\n * @param specs - Array of `{ reducer, property }`, where `property` can be a string or array of strings. Supports `*`/`**`.\n * @param selector - `(state) => T` function run against the full state.\n * @param isEqual - Equality comparator for the derived value (defaults to `Object.is`).\n *\n * @example\n * ```tsx\n * const total = useAtomicProps<'todos' | 'filter', AppState, number>(\n * [\n * { reducer: 'todos', property: 'items.**' },\n * { reducer: 'filter', property: 'q' }\n * ],\n * (s) => s.todos.items.filter(x => x.title.includes(s.filter.q)).length\n * );\n * ```\n *\n * @public\n */\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: OneOrMany<WithGlob<Dotted<S[R]>>> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: OneOrMany<string> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n): T;\nexport function useAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: OneOrMany<string> | OneOrMany<WithGlob<Dotted<S[R]>>>;\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n return _useAtomicPropsImpl<R, S, T>(specs as any, selector, isEqual);\n}\n\n/** @internal */\nfunction _useAtomicPropsImpl<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: OneOrMany<string> | OneOrMany<WithGlob<Dotted<S[R]>>>;\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n const store = useStore<EventMapBase, R, S>();\n\n const versionRef = useRef(0);\n const lastSelRef = useRef<T | undefined>(undefined);\n const lastVerRef = useRef<number>(-1);\n\n const normalizedSpecs = useMemo(() => {\n return specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p as string))\n : normalizePath(sp.property as string),\n }));\n }, [JSON.stringify(specs)]);\n\n const subscribe = useMemo(\n () => (notify: () => void) => {\n const tick = () => {\n versionRef.current++;\n notify();\n };\n\n const unsubs = normalizedSpecs.flatMap((sp) => {\n const props = Array.isArray(sp.property) ? sp.property : [sp.property];\n return props.map((p) => store.connect({ reducer: sp.reducer, property: p }, tick));\n });\n\n return () => {\n for (const u of unsubs) u();\n };\n },\n [store, normalizedSpecs],\n );\n\n const getSnapshot = useMemo(() => {\n return () => {\n if (lastVerRef.current !== versionRef.current) {\n const next = selector(store.getState() as DeepReadonly<S>);\n const prev = lastSelRef.current as T | undefined;\n\n if (prev === undefined || !isEqual(prev, next)) {\n lastSelRef.current = next;\n }\n\n lastVerRef.current = versionRef.current;\n }\n\n return lastSelRef.current as T;\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Subscribe to store events from a React component.\n *\n * This hook enables reactive UI patterns by allowing components to respond\n * to specific events without selecting state. Useful for:\n * - Showing notifications on certain events\n * - Triggering animations\n * - Logging/analytics\n * - Responding to rejected (uncommitted) events\n *\n * **Phases:**\n * - `'committed'` (default): Events that passed middleware and reached reducers\n * - `'uncommitted'`: Events rejected by middleware\n * - `'all'`: Both committed and uncommitted events (handler receives phase parameter)\n *\n * @typeParam EM - Event map type.\n * @typeParam C - Channel key within `EM`.\n * @typeParam T - Event type key within channel `C`.\n *\n * @param channel - Event channel to subscribe to.\n * @param type - Event type to subscribe to.\n * @param handler - Handler called when the event fires. Receives `(event, getState, emit, phase)`.\n * @param phase - Event phase to subscribe to (default: `'committed'`).\n *\n * @example Committed events (default)\n * ```tsx\n * useEvent('ui', 'save', (event, getState, emit, phase) => {\n * showToast('Saved successfully!');\n * });\n * ```\n *\n * @example Rejected events\n * ```tsx\n * useEvent('ui', 'delete', (event, getState, emit, phase) => {\n * showToast('Delete was blocked by middleware');\n * }, 'uncommitted');\n * ```\n *\n * @example All events\n * ```tsx\n * useEvent('ui', 'action', (event, getState, emit, phase) => {\n * console.log('Action:', phase); // 'committed' or 'uncommitted'\n * }, 'all');\n * ```\n *\n * @public\n */\nexport function useEvent<\n EM extends EventMapBase,\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n>(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<any>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase: EventPhase = \"committed\",\n): void {\n const store = useStore<EM, any, any>();\n const handlerRef = useRef(handler);\n handlerRef.current = handler; // Always keep latest handler (solves stale closures)\n\n useEffect(() => {\n return store.onEvent(\n channel,\n type,\n (event, getState, emit, eventPhase) => {\n handlerRef.current(event as Event<EM, C, T>, getState, emit, eventPhase);\n },\n phase,\n );\n }, [store, channel, type, phase]);\n}\n","/**\n * @module @yoltra/react\n */\n\nimport { useMemo, useSyncExternalStore } from \"react\";\nimport type { EventMapBase, StoreInstance, Dotted, WithGlob } from \"@yoltra/core\";\n\nimport { useStore } from \"./hooks\";\nimport { hasWildcard, normalizePath, getAtPath } from \"../utils/path\";\n\n/** @internal */\ntype CacheKey = string;\n\n/** @internal */\ntype CacheEntry<T> =\n | { status: \"ready\"; value: T; expiresAt: number | null }\n | { status: \"pending\"; promise: Promise<void>; expiresAt: number | null }\n | { status: \"error\"; error: any; expiresAt: number | null };\n\n/** @internal */\nclass SuspenseCache {\n private store = new Map<CacheKey, CacheEntry<any>>();\n\n read<T>(key: CacheKey, load: () => T | Promise<T>, staleTime: number | null): T {\n const now = Date.now();\n const entry = this.store.get(key);\n\n if (entry && entry.status === \"ready\" && (entry.expiresAt == null || entry.expiresAt > now)) {\n return entry.value as T;\n }\n if (\n entry &&\n entry.status === \"pending\" &&\n (entry.expiresAt == null || entry.expiresAt > now)\n ) {\n throw entry.promise;\n }\n if (entry && entry.status === \"error\" && (entry.expiresAt == null || entry.expiresAt > now)) {\n throw entry.error;\n }\n\n const promise = Promise.resolve()\n .then(load)\n .then((value) => {\n this.store.set(key, {\n status: \"ready\",\n value,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n })\n .catch((err) => {\n this.store.set(key, {\n status: \"error\",\n error: err,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n });\n\n this.store.set(key, {\n status: \"pending\",\n promise,\n expiresAt: staleTime == null ? null : Date.now() + staleTime,\n });\n throw promise;\n }\n\n invalidate(key: CacheKey) {\n this.store.delete(key);\n }\n invalidatePrefix(prefix: string) {\n for (const k of this.store.keys()) {\n if (k.startsWith(prefix)) this.store.delete(k);\n }\n }\n clear() {\n this.store.clear();\n }\n}\n\n/**\n * Default Suspense cache instance shared by all `useSuspense*` hooks.\n *\n * Use {@link invalidateAtomicProp}, {@link invalidateAtomicPropsByReducer},\n * or {@link clearSuspenseCache} to manage the cache from outside hooks.\n *\n * @public\n */\nexport const suspenseCache = new SuspenseCache();\n\n/** @internal */\nfunction buildKey(reducer: string, props: string[] | string, extraKey?: string): string {\n const p = Array.isArray(props) ? props.map(normalizePath).sort().join(\"|\") : normalizePath(props);\n return extraKey ? `${reducer}::${p}::${extraKey}` : `${reducer}::${p}`;\n}\n\n/**\n * Options for {@link useSuspenseAtomicProp}.\n *\n * @typeParam T - The resolved value type after loading.\n * @typeParam S - Store state record.\n *\n * @example\n * ```ts\n * const options: SuspenseAtomicPropOptions<User, AppState> = {\n * load: async (userId) => fetchUser(userId),\n * staleTime: 30_000, // cache for 30 seconds\n * key: 'user-detail',\n * };\n * ```\n *\n * @public\n */\nexport interface SuspenseAtomicPropOptions<T, S> {\n /** Async loader that receives the value at the path and the full slice. */\n load: (valueAtPath: any, slice: S[keyof S]) => Promise<T> | T;\n /** Time in ms before the cached value is considered stale (default: 0). */\n staleTime?: number;\n /** Optional extra key to differentiate cache entries for the same path. */\n key?: string;\n}\n\n/**\n * Suspense-compatible version of `useAtomicProp` that throws a promise while loading.\n *\n * Subscribes to a single dotted path and calls `options.load` to produce the\n * resolved value. While the promise is pending, React Suspense catches it and\n * renders the nearest `<Suspense>` fallback.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam P - Dotted path within `S[R]`.\n * @typeParam T - Resolved value type.\n *\n * @param storeSpec - `{ reducer, property }` identifying the path to subscribe to.\n * @param options - Loading options (see {@link SuspenseAtomicPropOptions}).\n * @returns The resolved value of type `T`.\n *\n * @throws A `Promise` while loading (caught by React Suspense).\n * @throws If called outside a `<StoreProvider>`.\n *\n * @example\n * ```tsx\n * function UserName({ userId }: { userId: string }) {\n * const name = useSuspenseAtomicProp(\n * { reducer: 'users', property: `byId.${userId}.name` },\n * { load: async (name) => name ?? (await fetchUser(userId)).name },\n * );\n * return <span>{name}</span>;\n * }\n *\n * // Wrap with Suspense\n * <Suspense fallback={<Spinner />}>\n * <UserName userId=\"123\" />\n * </Suspense>\n * ```\n *\n * @public\n */\nexport function useSuspenseAtomicProp<\n R extends string,\n S extends Record<R, any>,\n P extends Dotted<S[R]>,\n T,\n>(storeSpec: { reducer: R; property: P }, options: SuspenseAtomicPropOptions<T, S>): T;\nexport function useSuspenseAtomicProp<R extends string, S extends Record<R, any>, T>(\n storeSpec: { reducer: R; property: string },\n options: SuspenseAtomicPropOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProp<R extends string, S extends Record<R, any>, T>(\n storeSpec: { reducer: R; property: string },\n options: SuspenseAtomicPropOptions<T, S>,\n): T {\n return _useSuspenseAtomicPropImpl<R, S, any, T>(storeSpec as any, options);\n}\n\n/** @internal */\nfunction _useSuspenseAtomicPropImpl<\n R extends string,\n S extends Record<R, any>,\n P extends Dotted<S[R]>,\n T,\n>(storeSpec: { reducer: R; property: P }, options: SuspenseAtomicPropOptions<T, S>): T {\n const store = useStore<EventMapBase, R, S>() as StoreInstance<R, S, EventMapBase>;\n const reducer = storeSpec.reducer;\n const path = normalizePath(storeSpec.property as string);\n const key = buildKey(reducer, path, options.key);\n\n const subscribe = useMemo(() => {\n return (notify: () => void) =>\n store.connect({ reducer, property: path }, () => {\n suspenseCache.invalidate(key);\n notify();\n });\n }, [store, reducer, path, key]);\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(path);\n return () => {\n const state = store.getState() as S;\n const slice = state[reducer];\n const val = isGlob ? slice : getAtPath(slice, path);\n return suspenseCache.read<T>(key, () => options.load(val, slice), options.staleTime ?? 0);\n };\n }, [store, reducer, path, key, options]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Options for {@link useSuspenseAtomicProps}.\n *\n * @typeParam T - The resolved value type after loading.\n * @typeParam S - Store state record.\n *\n * @public\n */\nexport interface SuspenseAtomicPropsOptions<T, S> {\n /** Async loader that receives the full store state. */\n load: (state: S) => Promise<T> | T;\n /** Time in ms before the cached value is considered stale (default: 0). */\n staleTime?: number;\n /** Optional extra key to differentiate cache entries. */\n key?: string;\n}\n\n/**\n * Suspense-compatible version of `useAtomicProps` that throws a promise while loading.\n *\n * Subscribes to multiple dotted paths and calls `options.load` with the full state\n * to produce the resolved value. While the promise is pending, React Suspense\n * renders the nearest `<Suspense>` fallback.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam T - Resolved value type.\n *\n * @param specs - Array of `{ reducer, property }` paths to subscribe to.\n * @param options - Loading options (see {@link SuspenseAtomicPropsOptions}).\n * @returns The resolved value of type `T`.\n *\n * @throws A `Promise` while loading (caught by React Suspense).\n * @throws If called outside a `<StoreProvider>`.\n *\n * @example\n * ```tsx\n * function Dashboard() {\n * const stats = useSuspenseAtomicProps(\n * [\n * { reducer: 'orders', property: 'items.**' },\n * { reducer: 'users', property: 'active' },\n * ],\n * { load: async (state) => computeDashboardStats(state) },\n * );\n * return <StatsGrid data={stats} />;\n * }\n * ```\n *\n * @public\n */\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property: Dotted<S[R]> | WithGlob<Dotted<S[R]>> | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{ reducer: R; property: string | readonly string[] }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T;\nexport function useSuspenseAtomicProps<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property:\n | string\n | readonly string[]\n | Dotted<S[R]>\n | WithGlob<Dotted<S[R]>>\n | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T {\n return _useSuspenseAtomicPropsImpl<R, S, T>(specs as any, options);\n}\n\n/** @internal */\nfunction _useSuspenseAtomicPropsImpl<R extends string, S extends Record<R, any>, T>(\n specs: Array<{\n reducer: R;\n property:\n | string\n | readonly string[]\n | Dotted<S[R]>\n | WithGlob<Dotted<S[R]>>\n | ReadonlyArray<WithGlob<Dotted<S[R]>>>;\n }>,\n options: SuspenseAtomicPropsOptions<T, S>,\n): T {\n const store = useStore<EventMapBase, R, S>() as StoreInstance<R, S, EventMapBase>;\n\n const normalized = useMemo(\n () =>\n specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p as string))\n : normalizePath(sp.property as string),\n })),\n [JSON.stringify(specs)],\n );\n\n const key = useMemo(() => {\n const parts = normalized\n .map((sp) => buildKey(sp.reducer, sp.property))\n .sort()\n .join(\"||\");\n return options.key ? `${parts}::${options.key}` : parts;\n }, [normalized, options.key]);\n\n const subscribe = useMemo(() => {\n return (notify: () => void) => {\n const wrapped = () => {\n suspenseCache.invalidate(key);\n notify();\n };\n const unsubs = normalized.map((sp) => store.connect(sp as any, wrapped));\n return () => {\n for (const u of unsubs) u();\n };\n };\n }, [store, normalized, key]);\n\n const getSnapshot = useMemo(() => {\n return () => {\n const state = store.getState() as S;\n return suspenseCache.read<T>(key, () => options.load(state), options.staleTime ?? 0);\n };\n }, [store, key, options]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Invalidates the Suspense cache entry for a specific `reducer.property` path.\n *\n * @param reducer - Reducer (slice) name.\n * @param property - Dotted property path.\n * @param extraKey - Optional extra key if the hook was created with `options.key`.\n *\n * @example\n * ```ts\n * invalidateAtomicProp('users', 'byId.123.name');\n * ```\n *\n * @public\n */\nexport function invalidateAtomicProp(reducer: string, property: string, extraKey?: string) {\n suspenseCache.invalidate(buildKey(reducer, property, extraKey));\n}\n\n/**\n * Invalidates all Suspense cache entries for a given reducer (slice).\n *\n * @param reducer - Reducer (slice) name whose cache entries should be cleared.\n *\n * @example\n * ```ts\n * invalidateAtomicPropsByReducer('users');\n * ```\n *\n * @public\n */\nexport function invalidateAtomicPropsByReducer(reducer: string) {\n suspenseCache.invalidatePrefix(`${reducer}::`);\n}\n\n/**\n * Clears the entire Suspense cache, forcing all `useSuspense*` hooks to re-load.\n *\n * @example\n * ```ts\n * // After a logout, clear all cached data\n * clearSuspenseCache();\n * ```\n *\n * @public\n */\nexport function clearSuspenseCache() {\n suspenseCache.clear();\n}","/**\n * @module @yoltra/react\n */\n\nimport type {\n DeepReadonly,\n Dotted,\n Emit,\n Event,\n EventMapBase,\n EventPhase,\n PathValue,\n StoreInstance,\n WithGlob,\n} from \"@yoltra/core\";\nimport * as React from \"react\";\nimport { useContext, useEffect, useMemo, useRef, useSyncExternalStore } from \"react\";\nimport { getAtPath, hasWildcard, normalizePath } from \"../utils/path\";\n\n/**\n * Call signature for the typed `useAtomicProp` hook returned by {@link createHooks}.\n *\n * Subscribes to a specific dotted path in a reducer's state and re-renders\n * only when that path changes. All type parameters are inferred automatically\n * from the store context — no explicit generics needed.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const { useAtomicProp } = createHooks(AppStoreContext);\n *\n * function TodoTitle({ index }: { index: number }) {\n * const title = useAtomicProp({\n * reducer: 'todos',\n * property: `items.${index}.title`,\n * });\n * return <span>{title}</span>;\n * }\n * ```\n *\n * @public\n */\nexport type UseAtomicProp<R extends string, S extends Record<R, any>> = {\n <R1 extends R, P extends Dotted<S[R1]>>(spec: {\n reducer: R1;\n property: P;\n }): PathValue<S[R1], P>;\n <R1 extends R, P extends Dotted<S[R1]>, T>(\n spec: { reducer: R1; property: P },\n map: (value: PathValue<S[R1], P>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R, P extends WithGlob<Dotted<S[R1]>>, T>(\n spec: { reducer: R1; property: P },\n map: (value: unknown) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R>(spec: { reducer: R1; property: string }): unknown;\n <R1 extends R, T>(\n spec: { reducer: R1; property: string },\n map: (value: unknown) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n};\n\n/**\n * Call signature for the typed `useAtomicProps` hook returned by {@link createHooks}.\n *\n * Subscribes to multiple dotted paths across one or more reducers and recomputes\n * a derived value when any of them change.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n *\n * @example\n * ```tsx\n * const { useAtomicProps } = createHooks(AppStoreContext);\n *\n * function FilteredCount() {\n * const count = useAtomicProps(\n * [\n * { reducer: 'todos', property: 'items.**' },\n * { reducer: 'filter', property: 'q' },\n * ],\n * (s) => s.todos.items.filter(x => x.title.includes(s.filter.q)).length,\n * );\n * return <span>{count}</span>;\n * }\n * ```\n *\n * @public\n */\nexport type UseAtomicProps<R extends string, S extends Record<R, any>> = {\n <R1 extends R, T>(\n specs: Array<{\n reducer: R1;\n property: WithGlob<Dotted<S[R1]>> | readonly WithGlob<Dotted<S[R1]>>[];\n }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n <R1 extends R, T>(\n specs: Array<{ reducer: R1; property: string | readonly string[] }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual?: (a: T, b: T) => boolean,\n ): T;\n};\n\n/**\n * Call signature for the typed `useEvent` hook returned by {@link createHooks}.\n *\n * Subscribes to store events from a React component. Useful for notifications,\n * animations, analytics, and responding to rejected (uncommitted) events.\n *\n * @typeParam EM - Event map type.\n * @typeParam S - Store state type.\n *\n * @example\n * ```tsx\n * const { useEvent } = createHooks(AppStoreContext);\n *\n * function SaveNotifier() {\n * useEvent('ui', 'save', (event) => {\n * showToast('Saved!');\n * });\n * return null;\n * }\n * ```\n *\n * @public\n */\nexport type UseEvent<EM extends EventMapBase, S> = <\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n>(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<S>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase?: EventPhase,\n) => void;\n\n/**\n * Shallow object equality using `Object.is` per-key.\n *\n * Useful as the `isEqual` argument for `useAtomicProp` and `useAtomicProps`\n * when the derived value is a plain object. Also available as a standalone\n * export from `@yoltra/react` via {@link shallowEqual | hooks.shallowEqual}.\n *\n * @example\n * ```ts\n * shallowEqual({ a: 1 }, { a: 1 }); // true\n * shallowEqual({ a: 1 }, { a: 2 }); // false\n * ```\n *\n * @public\n */\nexport function shallowEqual<T extends Record<string, unknown>>(a: T, b: T) {\n if (Object.is(a, b)) return true;\n if (!a || !b) return false;\n const ka = Object.keys(a),\n kb = Object.keys(b);\n if (ka.length !== kb.length) return false;\n for (const k of ka) {\n if (!Object.is(a[k], (b as Record<string, unknown>)[k])) return false;\n }\n return true;\n}\n\n/**\n * Factory that creates fully-typed React hooks bound to a specific store context.\n *\n * This is the **recommended** setup pattern for yoltra + React. It eliminates\n * the need for explicit type parameters on every hook call — all types are\n * inferred from the store context once, at creation time.\n *\n * @typeParam R - Reducer name union.\n * @typeParam S - State record keyed by `R`.\n * @typeParam EM - Event map.\n *\n * @param StoreContext - A React context carrying a `StoreInstance<R, S, EM>`.\n * @returns An object with typed hooks: `useStore`, `useEmit`, `useSelector`,\n * `useAtomicProp`, `useAtomicProps`, `useEvent`, and `shallowEqual`.\n *\n * @throws If any returned hook is called outside a `<StoreProvider>`.\n *\n * @example Complete setup\n * ```tsx\n * // 1. Define your event map and state\n * type AppEM = { ui: { increment: number; decrement: number } };\n * type AppState = { counter: { value: number } };\n *\n * // 2. Create a typed context\n * import { createContext } from 'react';\n * import { StoreInstance } from '@yoltra/core';\n * const AppStoreContext = createContext<\n * StoreInstance<'counter', AppState, AppEM> | null\n * >(null);\n *\n * // 3. Create typed hooks (do this once, export from a shared module)\n * const { useAtomicProp, useEmit, useEvent } = createHooks(AppStoreContext);\n *\n * // 4. Use in components — no explicit generics needed\n * function Counter() {\n * const value = useAtomicProp({ reducer: 'counter', property: 'value' });\n * const emit = useEmit();\n * return (\n * <button onClick={() => emit('ui', 'increment', 1)}>\n * Count: {value}\n * </button>\n * );\n * }\n * ```\n *\n * @public\n */\nexport function createHooks<\n R extends string,\n S extends Record<R, any>,\n EM extends EventMapBase,\n>(StoreContext: React.Context<StoreInstance<R, S, EM> | null>) {\n function useStore(): StoreInstance<R, S, EM> {\n const ctx = useContext(StoreContext);\n if (!ctx) throw new Error(\"useStore must be used inside <StoreProvider>\");\n return ctx;\n }\n\n function useEmit(): Emit<EM> {\n return useStore().emit;\n }\n\n function useSelector<T>(\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n ): T {\n const store = useStore();\n const subscribe = useMemo(() => (notify: () => void) => store.subscribe(notify), [store]);\n const getSnapshot = useMemo(() => {\n let last = selector(store.getState());\n return () => {\n const next = selector(store.getState());\n return isEqual(last, next) ? last : (last = next);\n };\n }, [store, selector, isEqual]);\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n type UseAtomicPropOverloads = UseAtomicProp<R, S>;\n\n const useAtomicPropImpl = (\n spec: { reducer: R; property: string },\n map?: (value: unknown) => unknown,\n isEqual?: (a: unknown, b: unknown) => boolean,\n ): unknown => {\n const store = useStore();\n const normalizedSpec = useMemo(() => {\n const prop = normalizePath(spec.property);\n return { reducer: spec.reducer, property: prop } as const;\n }, [spec.reducer, spec.property]);\n\n const subscribe = useMemo(\n () => (notify: () => void) =>\n store.connect(\n { reducer: normalizedSpec.reducer, property: normalizedSpec.property },\n () => notify(),\n ),\n [store, normalizedSpec],\n );\n\n const getSnapshot = useMemo(() => {\n const isGlob = hasWildcard(normalizedSpec.property);\n const read = () => {\n const full = store.getState() as DeepReadonly<S>;\n const slice = (full as any)[normalizedSpec.reducer];\n const source = isGlob ? slice : getAtPath(slice, normalizedSpec.property);\n return map ? map(source) : source;\n };\n const eq = isEqual ?? Object.is;\n let last = read();\n return () => {\n const next = read();\n return eq(last, next) ? last : (last = next);\n };\n }, [store, normalizedSpec, map, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n };\n\n const useAtomicProp = useAtomicPropImpl as unknown as UseAtomicPropOverloads;\n\n type OneOrMany<T> = T | readonly T[];\n type UseAtomicPropsOverloads = UseAtomicProps<R, S>;\n\n const useAtomicPropsImpl = <T>(\n specs: Array<{ reducer: R; property: OneOrMany<string> }>,\n selector: (state: DeepReadonly<S>) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n ): T => {\n const store = useStore();\n const versionRef = useRef(0);\n const lastSelRef = useRef<T | undefined>(undefined);\n const lastVerRef = useRef<number>(-1);\n\n const normalizedSpecs = useMemo(() => {\n return specs.map((sp) => ({\n reducer: sp.reducer,\n property: Array.isArray(sp.property)\n ? (sp.property as readonly string[]).map((p) => normalizePath(p))\n : normalizePath(sp.property as string),\n }));\n }, [JSON.stringify(specs)]);\n\n const subscribe = useMemo(\n () => (notify: () => void) => {\n const tick = () => {\n versionRef.current++;\n notify();\n };\n const unsubs = normalizedSpecs.flatMap((sp) => {\n const props = Array.isArray(sp.property) ? sp.property : [sp.property];\n return props.map((p) => store.connect({ reducer: sp.reducer, property: p }, tick));\n });\n return () => {\n for (const u of unsubs) u();\n };\n },\n [store, normalizedSpecs],\n );\n\n const getSnapshot = useMemo(() => {\n return () => {\n if (lastVerRef.current !== versionRef.current) {\n const next = selector(store.getState());\n const prev = lastSelRef.current;\n if (prev === undefined || !isEqual(prev, next)) lastSelRef.current = next;\n lastVerRef.current = versionRef.current;\n }\n return lastSelRef.current as T;\n };\n }, [store, selector, isEqual]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n };\n\n const useAtomicProps = useAtomicPropsImpl as unknown as UseAtomicPropsOverloads;\n\n type UseEventOverloads = UseEvent<EM, S>;\n\n const useEvent: UseEventOverloads = <\n C extends keyof EM & string,\n T extends keyof EM[C] & string,\n >(\n channel: C,\n type: T,\n handler: (\n event: Event<EM, C, T>,\n getState: () => DeepReadonly<S>,\n emit: Emit<EM>,\n phase: \"committed\" | \"uncommitted\",\n ) => void | Promise<void>,\n phase: EventPhase = \"committed\",\n ): void => {\n const store = useStore();\n const handlerRef = useRef(handler);\n handlerRef.current = handler; // Always keep latest handler (solves stale closures)\n\n useEffect(() => {\n return store.onEvent(\n channel,\n type,\n (event, getState, emit, eventPhase) => {\n handlerRef.current(\n event as Event<EM, C, T>,\n getState as () => DeepReadonly<S>,\n emit,\n eventPhase,\n );\n },\n phase,\n );\n }, [store, channel, type, phase]);\n };\n\n return {\n useStore,\n useEmit,\n useSelector,\n useAtomicProp,\n useAtomicProps,\n useEvent,\n shallowEqual,\n };\n}\n"],"names":["require$$0","StoreContext","createContext","jsxRuntime","reactJsxRuntime_production","REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","self","source","owner","debugStack","debugTask","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","React","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","StoreProvider","store","jsx","hasWildcard","p","normalizePath","splitPath","getAtPath","obj","path","cur","seg","useStore","ctx","useContext","useEmit","shallowEqual","a","b","ka","kb","useSelector","selector","isEqual","subscribe","useMemo","notify","getSnapshot","last","next","useSyncExternalStore","useAtomicPropImpl","spec","normalizedSpec","prop","isGlob","read","slice","_useAtomicPropImpl","map","useAtomicProp","useAtomicProps","specs","_useAtomicPropsImpl","versionRef","useRef","lastSelRef","lastVerRef","normalizedSpecs","sp","tick","unsubs","u","prev","useEvent","channel","handler","phase","handlerRef","useEffect","event","getState","emit","eventPhase","SuspenseCache","__publicField","load","staleTime","now","entry","promise","err","prefix","suspenseCache","buildKey","reducer","extraKey","useSuspenseAtomicProp","storeSpec","options","_useSuspenseAtomicPropImpl","_a","val","useSuspenseAtomicProps","_useSuspenseAtomicPropsImpl","normalized","parts","wrapped","state","invalidateAtomicProp","property","invalidateAtomicPropsByReducer","clearSuspenseCache","createHooks","eq","shallowEqual$1"],"mappings":"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","x_google_ignoreList":[1,2,3]}