@yoltra/react 0.3.0 → 0.4.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.es.md CHANGED
@@ -1,4 +1,4 @@
1
- ![yoltra logo](../../assets/yoltra-logo.png)
1
+ ![Yoltra logo](https://yoltra.dev/assets/yoltra-logo.png)
2
2
 
3
3
  # @yoltra/react
4
4
 
@@ -122,8 +122,17 @@ export const AppStoreContext = createContext<StoreInstance<"counter", AppState,
122
122
  null,
123
123
  );
124
124
 
125
- export const { useStore, useEmit, useSelector, useAtomicProp, useAtomicProps, useEvent, shallowEqual } =
126
- createHooks(AppStoreContext);
125
+ export const {
126
+ useStore,
127
+ useEmit,
128
+ useSelector,
129
+ useAtomicProp,
130
+ useAtomicProps,
131
+ useEvent,
132
+ useSuspenseAtomicProp,
133
+ useSuspenseAtomicProps,
134
+ shallowEqual,
135
+ } = createHooks(AppStoreContext);
127
136
  ```
128
137
 
129
138
  Provee el store con `<AppStoreContext.Provider value={store}>` en tu raiz.
@@ -252,9 +261,19 @@ Retorna la instancia del store. Lanza error si se llama fuera de un provider.
252
261
 
253
262
  ```tsx
254
263
  const store = useStore();
255
- const state = store.getState();
264
+
265
+ // ✅ En un callback o un efecto: lee el valor en el momento en que se quiere.
266
+ const onSave = () => save(store.getState());
267
+
268
+ // ❌ En el cuerpo del render: esto no se suscribe a nada.
269
+ const value = store.getState().counter.value;
256
270
  ```
257
271
 
272
+ `getState()` es una lectura, no una suscripción. Llamado durante el render, el componente se
273
+ renderiza una vez con ese valor y nunca más — nada le avisó de que el valor cambió. Parece que
274
+ funciona hasta que el estado cambia y la pantalla no. Lee con `useAtomicProp` o `useSelector` lo
275
+ que vayas a renderizar, y deja `getState()` para callbacks y efectos, que es para lo que es.
276
+
258
277
  ---
259
278
 
260
279
  ## Hooks de Suspense
@@ -296,6 +315,27 @@ const stats = useSuspenseAtomicProps(
296
315
  );
297
316
  ```
298
317
 
318
+ ### Importalos de tu conjunto de hooks, no del barrel
319
+
320
+ `createYoltra` y `createHooks` devuelven estos dos junto con el resto, ligados al mismo contexto.
321
+ Deliberadamente **no** se exportan desde el barrel del paquete: una copia a nivel de paquete seria
322
+ identica en forma y aun asi lanzaria `useStore must be used inside <StoreProvider>` en tiempo de
323
+ ejecucion cuando el contexto que lee nunca se lleno — un error que los tipos no podian atrapar.
324
+ Importarlos desde cualquier sitio que no sea el resultado de tu propio `createYoltra`/`createHooks`
325
+ es ahora un error de compilacion, que es el mismo aviso llegando en el momento correcto.
326
+
327
+ ```tsx
328
+ // store.ts
329
+ export const { store, useAtomicProp, useSuspenseAtomicProp } = createYoltra({ ... });
330
+
331
+ // Forecast.tsx
332
+ import { useSuspenseAtomicProp } from "./store"; // ✅ conoce el store
333
+ ```
334
+
335
+ Los valores en cache tienen alcance por store, asi que dos stores que compartan nombre de reducer
336
+ y ruta mantienen entradas separadas; las utilidades de invalidacion de abajo reciben una ruta y la
337
+ limpian en todos los stores que la hayan cacheado.
338
+
299
339
  ### Utilidades de cache
300
340
 
301
341
  ```typescript
@@ -411,6 +451,25 @@ antes de v1.0.0.
411
451
 
412
452
  ---
413
453
 
454
+ ## Colecciones normalizadas
455
+
456
+ `useEntityIds`, `useEntity` y `useEntityField` se emparejan con `createEntityAdapter` de
457
+ `@yoltra/core`. Son envoltorios delgados sobre `useAtomicProp`; el valor esta en que la ruta viene
458
+ del adapter en vez de escribirse a mano en un componente, donde nada la verifica.
459
+
460
+ ```tsx
461
+ function List() {
462
+ const ids = useEntityIds('todos', todos);
463
+ return <>{ids.map((id) => <Row key={id} id={id} />)}</>;
464
+ }
465
+
466
+ function Row({ id }: { id: string }) {
467
+ // Despierta cuando cambia este titulo, y no cuando cambia el de otra fila.
468
+ const title = useEntityField('todos', todos, id, 'title');
469
+ return <li>{title}</li>;
470
+ }
471
+ ```
472
+
414
473
  ## Licencia
415
474
 
416
475
  **MIT** -- Libre para usar en proyectos comerciales y de codigo abierto.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![yoltra logo](../../assets/yoltra-logo.png)
1
+ ![Yoltra logo](https://yoltra.dev/assets/yoltra-logo.png)
2
2
 
3
3
  # @yoltra/react
4
4
 
@@ -121,8 +121,17 @@ export const AppStoreContext = createContext<StoreInstance<"counter", AppState,
121
121
  null,
122
122
  );
123
123
 
124
- export const { useStore, useEmit, useSelector, useAtomicProp, useAtomicProps, useEvent, shallowEqual } =
125
- createHooks(AppStoreContext);
124
+ export const {
125
+ useStore,
126
+ useEmit,
127
+ useSelector,
128
+ useAtomicProp,
129
+ useAtomicProps,
130
+ useEvent,
131
+ useSuspenseAtomicProp,
132
+ useSuspenseAtomicProps,
133
+ shallowEqual,
134
+ } = createHooks(AppStoreContext);
126
135
  ```
127
136
 
128
137
  Provide the store with `<AppStoreContext.Provider value={store}>` at your root.
@@ -248,9 +257,19 @@ Returns the store instance. Throws if called outside a provider.
248
257
 
249
258
  ```tsx
250
259
  const store = useStore();
251
- const state = store.getState();
260
+
261
+ // ✅ In a callback or an effect: read the value at the moment it is wanted.
262
+ const onSave = () => save(store.getState());
263
+
264
+ // ❌ In the render body: this subscribes to nothing.
265
+ const value = store.getState().counter.value;
252
266
  ```
253
267
 
268
+ `getState()` is a read, not a subscription. Called while rendering, the component renders once
269
+ with that value and never again — nothing told it the value moved. It looks like it works right
270
+ up until the state changes and the screen does not. Read what you render with `useAtomicProp` or
271
+ `useSelector`, and keep `getState()` for callbacks and effects, which is what it is for.
272
+
254
273
  ---
255
274
 
256
275
  ## Suspense Hooks
@@ -292,6 +311,26 @@ const stats = useSuspenseAtomicProps(
292
311
  );
293
312
  ```
294
313
 
314
+ ### Import them from your hook set, not the barrel
315
+
316
+ `createYoltra` and `createHooks` return these two alongside the rest, bound to the same context.
317
+ They are deliberately **not** exported from the package barrel: a package-level copy would be
318
+ identical in shape and still throw `useStore must be used inside <StoreProvider>` at runtime
319
+ whenever the context it reads was never filled — a mistake the types could not catch. Importing
320
+ them from anywhere but your own `createYoltra`/`createHooks` result is now a compile error,
321
+ which is the same warning arriving at the right time.
322
+
323
+ ```tsx
324
+ // store.ts
325
+ export const { store, useAtomicProp, useSuspenseAtomicProp } = createYoltra({ ... });
326
+
327
+ // Forecast.tsx
328
+ import { useSuspenseAtomicProp } from "./store"; // ✅ knows the store
329
+ ```
330
+
331
+ Cached values are scoped per store, so two stores sharing a reducer name and path keep separate
332
+ entries; the invalidation helpers below take a path and clear it in every store that cached it.
333
+
295
334
  ### Cache utilities
296
335
 
297
336
  ```typescript
@@ -407,6 +446,25 @@ v1.0.0.
407
446
 
408
447
  ---
409
448
 
449
+ ## Normalised collections
450
+
451
+ `useEntityIds`, `useEntity` and `useEntityField` pair with `createEntityAdapter` from
452
+ `@yoltra/core`. They are thin wrappers over `useAtomicProp`; the value is that the path comes
453
+ from the adapter rather than being typed into a component, where nothing checks it.
454
+
455
+ ```tsx
456
+ function List() {
457
+ const ids = useEntityIds('todos', todos);
458
+ return <>{ids.map((id) => <Row key={id} id={id} />)}</>;
459
+ }
460
+
461
+ function Row({ id }: { id: string }) {
462
+ // Wakes when this title changes, and not when any other row does.
463
+ const title = useEntityField('todos', todos, id, 'title');
464
+ return <li>{title}</li>;
465
+ }
466
+ ```
467
+
410
468
  ## License
411
469
 
412
470
  **MIT** — Free to use in commercial and open-source projects.
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @yoltra/react v0.3.0
2
+ * @yoltra/react v0.4.0
3
3
  * (c) 2026 Manu Ramirez <@pixerael>
4
4
  * License: MIT
5
5
  * Homepage: https://yoltra.dev
@@ -7,10 +7,26 @@
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree
9
9
  */
10
- "use strict";var be=Object.defineProperty;var ve=(t,e,n)=>e in t?be(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var oe=(t,e,n)=>ve(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),he=require("@yoltra/core"),H=c.createContext(null);var z={exports:{}},D={};var se;function Re(){if(se)return D;se=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(o,s,u){var m=null;if(u!==void 0&&(m=""+u),s.key!==void 0&&(m=""+s.key),"key"in s){u={};for(var y in s)y!=="key"&&(u[y]=s[y])}else u=s;return s=u.ref,{$$typeof:t,type:o,key:m,ref:s!==void 0?s:null,props:u}}return D.Fragment=e,D.jsx=n,D.jsxs=n,D}var F={};var ce;function Ee(){return ce||(ce=1,process.env.NODE_ENV!=="production"&&(function(){function t(r){if(r==null)return null;if(typeof r=="function")return r.$$typeof===Z?null:r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case R:return"Fragment";case P:return"Profiler";case v:return"StrictMode";case M:return"Suspense";case g:return"SuspenseList";case T:return"Activity"}if(typeof r=="object")switch(typeof r.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),r.$$typeof){case b:return"Portal";case N:return(r.displayName||"Context")+".Provider";case k:return(r._context.displayName||"Context")+".Consumer";case $:var i=r.render;return r=r.displayName,r||(r=i.displayName||i.name||"",r=r!==""?"ForwardRef("+r+")":"ForwardRef"),r;case w:return i=r.displayName||null,i!==null?i:t(r.type)||"Memo";case W:i=r._payload,r=r._init;try{return t(r(i))}catch{}}return null}function e(r){return""+r}function n(r){try{e(r);var i=!1}catch{i=!0}if(i){i=console;var S=i.error,E=typeof Symbol=="function"&&Symbol.toStringTag&&r[Symbol.toStringTag]||r.constructor.name||"Object";return S.call(i,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",E),e(r)}}function o(r){if(r===R)return"<>";if(typeof r=="object"&&r!==null&&r.$$typeof===W)return"<...>";try{var i=t(r);return i?"<"+i+">":"<...>"}catch{return"<...>"}}function s(){var r=Y.A;return r===null?null:r.getOwner()}function u(){return Error("react-stack-top-frame")}function m(r){if(Q.call(r,"key")){var i=Object.getOwnPropertyDescriptor(r,"key").get;if(i&&i.isReactWarning)return!1}return r.key!==void 0}function y(r,i){function S(){K||(K=!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)",i))}S.isReactWarning=!0,Object.defineProperty(r,"key",{get:S,configurable:!0})}function h(){var r=t(this.type);return ee[r]||(ee[r]=!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.")),r=this.props.ref,r!==void 0?r:null}function a(r,i,S,E,j,x,J,q){return S=x.ref,r={$$typeof:p,type:r,key:i,props:x,_owner:j},(S!==void 0?S:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:h}):Object.defineProperty(r,"ref",{enumerable:!1,value:null}),r._store={},Object.defineProperty(r._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(r,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(r,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:J}),Object.defineProperty(r,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:q}),Object.freeze&&(Object.freeze(r.props),Object.freeze(r)),r}function l(r,i,S,E,j,x,J,q){var A=i.children;if(A!==void 0)if(E)if(ye(A)){for(E=0;E<A.length;E++)d(A[E]);Object.freeze&&Object.freeze(A)}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 d(A);if(Q.call(i,"key")){A=t(r);var I=Object.keys(i).filter(function(Se){return Se!=="key"});E=0<I.length?"{key: someKey, "+I.join(": ..., ")+": ...}":"{key: someKey}",ne[A+E]||(I=0<I.length?"{"+I.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
10
+ "use strict";var Ee=Object.defineProperty;var Re=(t,e,n)=>e in t?Ee(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var ue=(t,e,n)=>Re(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),Ae=require("@yoltra/core"),K=c.createContext(null);var W={exports:{}},D={};/**
11
+ * @license React
12
+ * react-jsx-runtime.production.js
13
+ *
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ */var ce;function Pe(){if(ce)return D;ce=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(o,s,u){var a=null;if(u!==void 0&&(a=""+u),s.key!==void 0&&(a=""+s.key),"key"in s){u={};for(var h in s)h!=="key"&&(u[h]=s[h])}else u=s;return s=u.ref,{$$typeof:t,type:o,key:a,ref:s!==void 0?s:null,props:u}}return D.Fragment=e,D.jsx=n,D.jsxs=n,D}var F={};/**
19
+ * @license React
20
+ * react-jsx-runtime.development.js
21
+ *
22
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
23
+ *
24
+ * This source code is licensed under the MIT license found in the
25
+ * LICENSE file in the root directory of this source tree.
26
+ */var ae;function ge(){return ae||(ae=1,process.env.NODE_ENV!=="production"&&(function(){function t(r){if(r==null)return null;if(typeof r=="function")return r.$$typeof===V?null:r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case S:return"Fragment";case k:return"Profiler";case b:return"StrictMode";case $:return"Suspense";case I:return"SuspenseList";case O:return"Activity"}if(typeof r=="object")switch(typeof r.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),r.$$typeof){case v:return"Portal";case P:return(r.displayName||"Context")+".Provider";case _:return(r._context.displayName||"Context")+".Consumer";case j:var i=r.render;return r=r.displayName,r||(r=i.displayName||i.name||"",r=r!==""?"ForwardRef("+r+")":"ForwardRef"),r;case M:return i=r.displayName||null,i!==null?i:t(r.type)||"Memo";case A:i=r._payload,r=r._init;try{return t(r(i))}catch{}}return null}function e(r){return""+r}function n(r){try{e(r);var i=!1}catch{i=!0}if(i){i=console;var p=i.error,E=typeof Symbol=="function"&&Symbol.toStringTag&&r[Symbol.toStringTag]||r.constructor.name||"Object";return p.call(i,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",E),e(r)}}function o(r){if(r===S)return"<>";if(typeof r=="object"&&r!==null&&r.$$typeof===A)return"<...>";try{var i=t(r);return i?"<"+i+">":"<...>"}catch{return"<...>"}}function s(){var r=x.A;return r===null?null:r.getOwner()}function u(){return Error("react-stack-top-frame")}function a(r){if(B.call(r,"key")){var i=Object.getOwnPropertyDescriptor(r,"key").get;if(i&&i.isReactWarning)return!1}return r.key!==void 0}function h(r,i){function p(){te||(te=!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)",i))}p.isReactWarning=!0,Object.defineProperty(r,"key",{get:p,configurable:!0})}function y(){var r=t(this.type);return re[r]||(re[r]=!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.")),r=this.props.ref,r!==void 0?r:null}function g(r,i,p,E,C,w,X,H){return p=w.ref,r={$$typeof:f,type:r,key:i,props:w,_owner:C},(p!==void 0?p:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:y}):Object.defineProperty(r,"ref",{enumerable:!1,value:null}),r._store={},Object.defineProperty(r._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(r,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(r,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:X}),Object.defineProperty(r,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:H}),Object.freeze&&(Object.freeze(r.props),Object.freeze(r)),r}function d(r,i,p,E,C,w,X,H){var R=i.children;if(R!==void 0)if(E)if(J(R)){for(E=0;E<R.length;E++)l(R[E]);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 l(R);if(B.call(i,"key")){R=t(r);var Y=Object.keys(i).filter(function(be){return be!=="key"});E=0<Y.length?"{key: someKey, "+Y.join(": ..., ")+": ...}":"{key: someKey}",se[R+E]||(Y=0<Y.length?"{"+Y.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
11
27
  let props = %s;
12
28
  <%s {...props} />
13
29
  React keys must be passed directly to JSX without using spread:
14
30
  let props = %s;
15
- <%s key={someKey} {...props} />`,E,A,I,A),ne[A+E]=!0)}if(A=null,S!==void 0&&(n(S),A=""+S),m(i)&&(n(i.key),A=""+i.key),"key"in i){S={};for(var B in i)B!=="key"&&(S[B]=i[B])}else S=i;return A&&y(S,typeof r=="function"?r.displayName||r.name||"Unknown":r),a(r,A,x,j,s(),S,J,q)}function d(r){typeof r=="object"&&r!==null&&r.$$typeof===p&&r._store&&(r._store.validated=1)}var f=c,p=Symbol.for("react.transitional.element"),b=Symbol.for("react.portal"),R=Symbol.for("react.fragment"),v=Symbol.for("react.strict_mode"),P=Symbol.for("react.profiler"),k=Symbol.for("react.consumer"),N=Symbol.for("react.context"),$=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),g=Symbol.for("react.suspense_list"),w=Symbol.for("react.memo"),W=Symbol.for("react.lazy"),T=Symbol.for("react.activity"),Z=Symbol.for("react.client.reference"),Y=f.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Q=Object.prototype.hasOwnProperty,ye=Array.isArray,U=console.createTask?console.createTask:function(){return null};f={react_stack_bottom_frame:function(r){return r()}};var K,ee={},re=f.react_stack_bottom_frame.bind(f,u)(),te=U(o(u)),ne={};F.Fragment=R,F.jsx=function(r,i,S,E,j){var x=1e4>Y.recentlyCreatedOwnerStacks++;return l(r,i,S,!1,E,j,x?Error("react-stack-top-frame"):re,x?U(o(r)):te)},F.jsxs=function(r,i,S,E,j){var x=1e4>Y.recentlyCreatedOwnerStacks++;return l(r,i,S,!0,E,j,x?Error("react-stack-top-frame"):re,x?U(o(r)):te)}})()),F}var ue;function Ae(){return ue||(ue=1,process.env.NODE_ENV==="production"?z.exports=Re():z.exports=Ee()),z.exports}var ie=Ae();const Pe=({store:t,children:e})=>ie.jsx(H.Provider,{value:t,children:e}),ae=new Set;function ge(t,e){process.env.NODE_ENV!=="production"&&(ae.has(t)||(ae.add(t),console.warn(e)))}function V(t){return t.includes("*")}function _(t){return t.replace(/^\./,"")}function _e(t){return _(t).split(".").filter(Boolean)}function le(t){const e=n=>`${n.length}:${n}`;return t.map(n=>{const o=Array.isArray(n.property)?n.property:[n.property];return e(n.reducer)+e(String(o.length))+o.map(e).join("")}).join("")}const fe=Symbol("yoltra.pathSegments");function pe(t){const e=()=>{};return new Proxy(e,{get(n,o){if(o===fe)return t;if(typeof o!="symbol")return pe([...t,String(o)])},apply(){throw new Error(`[yoltra] A typed path accessor called a method (near "${t.join(".")}"). The accessor must be a plain member chain like \`p => p.items[0].title\` — it cannot call functions such as \`.map()\` or \`.toString()\`. Compute derived values in the component or a selector, or use the \`{ reducer, property }\` string form.`)}})}function ke(t){const e=t(pe([])),n=e!=null?e[fe]:void 0,s=(Array.isArray(n)?n:[]).join(".");return s===""&&ge("yoltra.toDottedPath.empty","[yoltra] A typed path accessor recorded no property access, so it will subscribe to the entire slice. The accessor must be a plain member chain like `p => p.items[0].title` and cannot return a computed value or a default. For a whole-slice or dynamic subscription, use the `{ reducer, property }` string form instead."),s}function G(t,e){if(!e)return t;let n=t;for(const o of _e(e)){if(n==null)return;n=n[o]}return n}function L(t,e,n){const o=c.useRef(t);o.current=t;const s=c.useRef(e);s.current=e;const u=c.useMemo(()=>({has:!1,value:void 0}),n);return c.useCallback(()=>{const m=o.current();return(!u.has||!s.current(u.value,m))&&(u.has=!0,u.value=m),u.value},[u])}function me(t,e){if(Object.is(t,e))return!0;if(!t||!e)return!1;const n=Object.keys(t),o=Object.keys(e);if(n.length!==o.length)return!1;for(const s of n)if(!Object.is(t[s],e[s]))return!1;return!0}function C(){const t=c.useContext(H);if(!t)throw new Error("useStore must be used inside <StoreProvider>");return t}function xe(){return C().emit}function we(t,e=Object.is){const n=C(),o=c.useMemo(()=>u=>n.subscribe(u),[n]),s=L(()=>t(n.getState()),e,[n]);return c.useSyncExternalStore(o,s,s)}function Te(t,e,n=Object.is){const o=C(),s=c.useMemo(()=>{const h=_(t.property);return{reducer:t.reducer,property:h}},[t.reducer,t.property]),u=c.useMemo(()=>h=>o.connect({reducer:s.reducer,property:s.property},()=>h()),[o,s]),m=V(s.property),y=L(()=>{const a=o.getState()[s.reducer],l=m?a:G(a,s.property);return e?e(l):l},n,[o,s]);return c.useSyncExternalStore(u,y,y)}function je(t,e,n=Object.is){return Te(t,e,n)}function Oe(t,e,n=Object.is){return Ce(t,e,n)}function Ce(t,e,n=Object.is){const o=C(),s=c.useRef(0),u=c.useRef(void 0),m=c.useRef(-1),y=c.useRef(!1),h=c.useRef(e);h.current=e;const a=c.useRef(n);a.current=n;const l=c.useMemo(()=>t.map(p=>({reducer:p.reducer,property:Array.isArray(p.property)?p.property.map(b=>_(b)):_(p.property)})),[le(t)]),d=c.useMemo(()=>p=>{const b=()=>{s.current++,p()},R=l.flatMap(v=>(Array.isArray(v.property)?v.property:[v.property]).map(k=>o.connect({reducer:v.reducer,property:k},b)));return()=>{for(const v of R)v()}},[o,l]),f=c.useCallback(()=>{if(m.current!==s.current||!y.current){const p=h.current(o.getState());(!y.current||!a.current(u.current,p))&&(u.current=p,y.current=!0),m.current=s.current}return u.current},[o]);return c.useSyncExternalStore(d,f,f)}function Me(t,e,n,o="committed"){const s=C(),u=c.useRef(n);u.current=n,c.useEffect(()=>s.onEvent(t,e,(m,y,h,a)=>{u.current(m,y,h,a)},o),[s,t,e,o])}function Ne(t){return t==null||t<=0?null:Date.now()+t}class $e{constructor(){oe(this,"store",new Map)}read(e,n,o){const s=Date.now(),u=this.store.get(e);if(u&&u.status==="ready"&&(u.expiresAt==null||u.expiresAt>s))return u.value;if(u&&u.status==="pending")throw u.promise;if(u&&u.status==="error")throw u.error;const m=Promise.resolve().then(n).then(y=>{this.store.set(e,{status:"ready",value:y,expiresAt:Ne(o)})}).catch(y=>{this.store.set(e,{status:"error",error:y,expiresAt:null})});throw this.store.set(e,{status:"pending",promise:m,expiresAt:null}),m}invalidate(e){this.store.delete(e)}invalidatePrefix(e){for(const n of this.store.keys())n.startsWith(e)&&this.store.delete(n)}clear(){this.store.clear()}}const O=new $e;function X(t,e,n){const o=Array.isArray(e)?e.map(_).sort().join("|"):_(e);return n?`${t}::${o}::${n}`:`${t}::${o}`}function Ie(t,e){return Ye(t,e)}function Ye(t,e){const n=C(),o=t.reducer,s=_(t.property),u=X(o,s,e.key),m=c.useMemo(()=>l=>n.connect({reducer:o,property:s},()=>{O.invalidate(u),l()}),[n,o,s,u]),y=c.useRef(e);y.current=e;const h=c.useMemo(()=>{const l=V(s);return()=>{var R;const f=n.getState()[o],p=l?f:G(f,s),b=y.current;return O.read(u,()=>b.load(p,f),(R=b.staleTime)!=null?R:0)}},[n,o,s,u]),a=c.useMemo(()=>{const l=V(s);return()=>{const f=n.getState()[o];return l?f:G(f,s)}},[n,o,s]);return c.useSyncExternalStore(m,h,a)}function De(t,e){return Fe(t,e)}function Fe(t,e){const n=C(),o=c.useMemo(()=>t.map(a=>({reducer:a.reducer,property:Array.isArray(a.property)?a.property.map(l=>_(l)):_(a.property)})),[JSON.stringify(t)]),s=c.useMemo(()=>{const a=o.map(l=>X(l.reducer,l.property)).sort().join("||");return e.key?`${a}::${e.key}`:a},[o,e.key]),u=c.useMemo(()=>a=>{const l=()=>{O.invalidate(s),a()},d=o.map(f=>n.connect(f,l));return()=>{for(const f of d)f()}},[n,o,s]),m=c.useRef(e);m.current=e;const y=c.useMemo(()=>()=>{var d;const a=n.getState(),l=m.current;return O.read(s,()=>l.load(a),(d=l.staleTime)!=null?d:0)},[n,s]),h=()=>{const a=m.current.load(n.getState());return a instanceof Promise?void 0:a};return c.useSyncExternalStore(u,y,h)}function We(t,e,n){O.invalidate(X(t,e,n))}function ze(t){O.invalidatePrefix(`${t}::`)}function Ve(){O.clear()}function de(t){function e(){const a=c.useContext(t);if(!a)throw new Error("[yoltra] No store in context. Wrap your tree in <StoreProvider store={...}>, or use the hooks returned by createYoltra (which default to their own store).");return a}function n(){return e().emit}function o(a,l=Object.is){const d=e(),f=c.useMemo(()=>b=>d.subscribe(b),[d]),p=L(()=>a(d.getState()),l,[d]);return c.useSyncExternalStore(f,p,p)}return{useStore:e,useEmit:n,useSelector:o,useAtomicProp:(a,l,d)=>{const f=e(),p=typeof a=="string",b=p?a:a.reducer,R=p?ke(l):a.property,v=p?void 0:l,P=c.useMemo(()=>({reducer:b,property:_(R)}),[b,R]),k=c.useMemo(()=>M=>f.connect({reducer:P.reducer,property:P.property},()=>M()),[f,P]),N=V(P.property),$=L(()=>{const g=f.getState()[P.reducer],w=N?g:G(g,P.property);return v?v(w):w},d!=null?d:Object.is,[f,P]);return c.useSyncExternalStore(k,$,$)},useAtomicProps:(a,l,d=Object.is)=>{const f=e(),p=c.useRef(0),b=c.useRef(void 0),R=c.useRef(-1),v=c.useRef(!1),P=c.useRef(l);P.current=l;const k=c.useRef(d);k.current=d;const N=c.useMemo(()=>a.map(g=>({reducer:g.reducer,property:Array.isArray(g.property)?g.property.map(w=>_(w)):_(g.property)})),[le(a)]),$=c.useMemo(()=>g=>{const w=()=>{p.current++,g()},W=N.flatMap(T=>(Array.isArray(T.property)?T.property:[T.property]).map(Y=>f.connect({reducer:T.reducer,property:Y},w)));return()=>{for(const T of W)T()}},[f,N]),M=c.useCallback(()=>{if(R.current!==p.current||!v.current){const g=P.current(f.getState());(!v.current||!k.current(b.current,g))&&(b.current=g,v.current=!0),R.current=p.current}return b.current},[f]);return c.useSyncExternalStore($,M,M)},useEvent:(a,l,d,f="committed")=>{const p=e(),b=c.useRef(d);b.current=d,c.useEffect(()=>p.onEvent(a,l,(R,v,P,k)=>{b.current(R,v,P,k)},f),[p,a,l,f])},shallowEqual:me}}function Ge(t){const e=he.createStore(t),n=c.createContext(e),o=de(n);return{store:e,StoreContext:n,StoreProvider:({store:u,children:m})=>ie.jsx(n.Provider,{value:u!=null?u:e,children:m}),...o}}exports.StoreContext=H;exports.StoreProvider=Pe;exports.clearSuspenseCache=Ve;exports.createHooks=de;exports.createYoltra=Ge;exports.invalidateAtomicProp=We;exports.invalidateAtomicPropsByReducer=ze;exports.shallowEqual=me;exports.suspenseCache=O;exports.useAtomicProp=je;exports.useAtomicProps=Oe;exports.useEmit=xe;exports.useEvent=Me;exports.useSelector=we;exports.useStore=C;exports.useSuspenseAtomicProp=Ie;exports.useSuspenseAtomicProps=De;
31
+ <%s key={someKey} {...props} />`,E,R,Y,R),se[R+E]=!0)}if(R=null,p!==void 0&&(n(p),R=""+p),a(i)&&(n(i.key),R=""+i.key),"key"in i){p={};for(var Z in i)Z!=="key"&&(p[Z]=i[Z])}else p=i;return R&&h(p,typeof r=="function"?r.displayName||r.name||"Unknown":r),g(r,R,w,C,s(),p,X,H)}function l(r){typeof r=="object"&&r!==null&&r.$$typeof===f&&r._store&&(r._store.validated=1)}var m=c,f=Symbol.for("react.transitional.element"),v=Symbol.for("react.portal"),S=Symbol.for("react.fragment"),b=Symbol.for("react.strict_mode"),k=Symbol.for("react.profiler"),_=Symbol.for("react.consumer"),P=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),$=Symbol.for("react.suspense"),I=Symbol.for("react.suspense_list"),M=Symbol.for("react.memo"),A=Symbol.for("react.lazy"),O=Symbol.for("react.activity"),V=Symbol.for("react.client.reference"),x=m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,B=Object.prototype.hasOwnProperty,J=Array.isArray,q=console.createTask?console.createTask:function(){return null};m={react_stack_bottom_frame:function(r){return r()}};var te,re={},ne=m.react_stack_bottom_frame.bind(m,u)(),oe=q(o(u)),se={};F.Fragment=S,F.jsx=function(r,i,p,E,C){var w=1e4>x.recentlyCreatedOwnerStacks++;return d(r,i,p,!1,E,C,w?Error("react-stack-top-frame"):ne,w?q(o(r)):oe)},F.jsxs=function(r,i,p,E,C){var w=1e4>x.recentlyCreatedOwnerStacks++;return d(r,i,p,!0,E,C,w?Error("react-stack-top-frame"):ne,w?q(o(r)):oe)}})()),F}var ie;function _e(){return ie||(ie=1,process.env.NODE_ENV==="production"?W.exports=Pe():W.exports=ge()),W.exports}var de=_e();const xe=({store:t,children:e})=>de.jsx(K.Provider,{value:t,children:e}),le=new Set;function we(t,e){process.env.NODE_ENV!=="production"&&(le.has(t)||(le.add(t),console.warn(e)))}function G(t){return t.includes("*")}function T(t){return t.replace(/^\./,"")}function Te(t){return T(t).split(".").filter(Boolean)}function ke(t){const e=n=>`${n.length}:${n}`;return t.map(n=>{const o=Array.isArray(n.property)?n.property:[n.property];return e(n.reducer)+e(String(o.length))+o.map(e).join("")}).join("")}const me=Symbol("yoltra.pathSegments");function he(t){const e=()=>{};return new Proxy(e,{get(n,o){if(o===me)return t;if(typeof o!="symbol")return he([...t,String(o)])},apply(){throw new Error(`[yoltra] A typed path accessor called a method (near "${t.join(".")}"). The accessor must be a plain member chain like \`p => p.items[0].title\` — it cannot call functions such as \`.map()\` or \`.toString()\`. Compute derived values in the component or a selector, or use the \`{ reducer, property }\` string form.`)}})}function je(t){const e=t(he([])),n=e!=null?e[me]:void 0,s=(Array.isArray(n)?n:[]).join(".");return s===""&&we("yoltra.toDottedPath.empty","[yoltra] A typed path accessor recorded no property access, so it will subscribe to the entire slice. The accessor must be a plain member chain like `p => p.items[0].title` and cannot return a computed value or a default. For a whole-slice or dynamic subscription, use the `{ reducer, property }` string form instead."),s}function L(t,e){if(!e)return t;let n=t;for(const o of Te(e)){if(n==null)return;n=n[o]}return n}function U(t,e,n){const o=c.useRef(t);o.current=t;const s=c.useRef(e);s.current=e;const u=c.useMemo(()=>({has:!1,value:void 0}),n);return c.useCallback(()=>{const a=o.current();return(!u.has||!s.current(u.value,a))&&(u.has=!0,u.value=a),u.value},[u])}function Se(t,e){if(Object.is(t,e))return!0;if(!t||!e)return!1;const n=Object.keys(t),o=Object.keys(e);if(n.length!==o.length)return!1;for(const s of n)if(!Object.is(t[s],e[s]))return!1;return!0}function z(){const t=c.useContext(K);if(!t)throw new Error("useStore must be used inside <StoreProvider>");return t}function Oe(){return z().emit}function Ce(t,e=Object.is){const n=z(),o=c.useMemo(()=>u=>n.subscribe(u),[n]),s=U(()=>t(n.getState()),e,[n]);return c.useSyncExternalStore(o,s,s)}function Ne(t,e,n=Object.is){const o=z(),s=c.useMemo(()=>{const y=T(t.property);return{reducer:t.reducer,property:y}},[t.reducer,t.property]),u=c.useMemo(()=>y=>o.connect({reducer:s.reducer,property:s.property},()=>y()),[o,s]),a=G(s.property),h=U(()=>{const g=o.getState()[s.reducer];return a?g:L(g,s.property)},n,[o,s]);return c.useSyncExternalStore(u,h,h)}function Q(t,e,n=Object.is){return Ne(t,e,n)}function Me(t,e,n,o="committed"){const s=z(),u=c.useRef(n);u.current=n,c.useEffect(()=>s.onEvent(t,e,(a,h,y,g)=>{u.current(a,h,y,g)},o),[s,t,e,o])}function $e(t){return t==null||t<=0?null:Date.now()+t}function Ie(t){return t===null?null:t===void 0||t<=0?0:Date.now()+t}const Ye=2e3;class De{constructor(){ue(this,"store",new Map)}touch(e){this.store.has(e)&&this.store.delete(e)}evict(){for(;this.store.size>Ye;){const e=this.store.keys().next();if(e.done===!0)return;const n=this.store.get(e.value);if((n==null?void 0:n.status)==="pending"){this.store.delete(e.value),this.store.set(e.value,n);continue}this.store.delete(e.value)}}get size(){return this.store.size}read(e,n,o,s){const u=Date.now(),a=this.store.get(e);if(a&&a.status==="ready"&&(a.expiresAt==null||a.expiresAt>u))return this.touch(e),this.store.set(e,a),a.value;if(a&&a.status==="pending")throw a.promise;if(a&&a.status==="error"){if(a.delivered!==!0)throw this.store.set(e,{...a,delivered:!0}),a.error;if(a.expiresAt===null||a.expiresAt>u)throw a.error;this.store.delete(e)}const h=Promise.resolve().then(n).then(y=>{this.store.set(e,{status:"ready",value:y,expiresAt:$e(o)})}).catch(y=>{this.store.set(e,{status:"error",error:y,expiresAt:Ie(s)})});throw this.store.set(e,{status:"pending",promise:h,expiresAt:null}),this.evict(),h}invalidate(e){this.store.delete(e)}invalidatePathKey(e){for(const n of this.store.keys())pe(n)===e&&this.store.delete(n)}invalidateReducer(e){const n=`${e}::`;for(const o of this.store.keys())pe(o).split("||").some(s=>s.startsWith(n))&&this.store.delete(o)}clear(){this.store.clear()}}const N=new De,fe=new WeakMap;let Fe=0;function ye(t){let e=fe.get(t);return e===void 0&&(e=`s${++Fe}`,fe.set(t,e)),e}function pe(t){return t.slice(t.indexOf("::")+2)}function ee(t,e,n){const o=Array.isArray(e)?e.map(T).sort().join("|"):T(e);return n?`${t}::${o}::${n}`:`${t}::${o}`}function ze(t,e,n){const o=t(),s=e.reducer,u=T(e.property),a=`${ye(o)}::${ee(s,u,n.key)}`,h=c.useMemo(()=>l=>o.connect({reducer:s,property:u},()=>{N.invalidate(a),l()}),[o,s,u,a]),y=c.useRef(n);y.current=n;const g=c.useMemo(()=>{const l=G(u);return()=>{var b;const f=o.getState()[s],v=l?f:L(f,u),S=y.current;return N.read(a,()=>S.load(v,f),(b=S.staleTime)!=null?b:0,S.errorTtlMs)}},[o,s,u,a]),d=c.useMemo(()=>{const l=G(u);return()=>{const f=o.getState()[s];return l?f:L(f,u)}},[o,s,u]);return c.useSyncExternalStore(h,g,d)}function We(t,e,n){const o=t(),s=c.useMemo(()=>e.map(d=>({reducer:d.reducer,property:Array.isArray(d.property)?d.property.map(l=>T(l)):T(d.property)})),[JSON.stringify(e)]),u=c.useMemo(()=>{const d=s.map(l=>ee(l.reducer,l.property)).sort().join("||");return`${ye(o)}::${n.key?`${d}::${n.key}`:d}`},[o,s,n.key]),a=c.useMemo(()=>d=>{const l=()=>{N.invalidate(u),d()},m=s.map(f=>o.connect(f,l));return()=>{for(const f of m)f()}},[o,s,u]),h=c.useRef(n);h.current=n;const y=c.useMemo(()=>()=>{var m;const d=o.getState(),l=h.current;return N.read(u,()=>l.load(d),(m=l.staleTime)!=null?m:0,l.errorTtlMs)},[o,u]),g=()=>{const d=h.current.load(o.getState());return d instanceof Promise?void 0:d};return c.useSyncExternalStore(a,y,g)}function Ge(t,e,n){N.invalidatePathKey(ee(t,e,n))}function Le(t){N.invalidateReducer(t)}function Ue(){N.clear()}function Ve(t){return{useSuspenseAtomicProp:(o,s)=>ze(t,o,s),useSuspenseAtomicProps:(o,s)=>We(t,o,s)}}function ve(t){function e(){const l=c.useContext(t);if(!l)throw new Error("[yoltra] No store in context. Wrap your tree in <StoreProvider store={...}>, or use the hooks returned by createYoltra (which default to their own store).");return l}function n(){return e().emit}function o(l,m=Object.is){const f=e(),v=c.useMemo(()=>b=>f.subscribe(b),[f]),S=U(()=>l(f.getState()),m,[f]);return c.useSyncExternalStore(v,S,S)}const u=(l,m,f)=>{const v=e(),S=typeof l=="string",b=S?l:l.reducer,k=S?je(m):l.property,_=S?void 0:m,P=c.useMemo(()=>({reducer:b,property:T(k)}),[b,k]),j=c.useMemo(()=>M=>v.connect({reducer:P.reducer,property:P.property},()=>M()),[v,P]),$=G(P.property),I=U(()=>{const A=v.getState()[P.reducer],O=$?A:L(A,P.property);return _?_(O):O},f!=null?f:Object.is,[v,P]);return c.useSyncExternalStore(j,I,I)},h=(l,m,f=Object.is)=>{const v=e(),S=c.useRef(0),b=c.useRef(void 0),k=c.useRef(-1),_=c.useRef(!1),P=c.useRef(m);P.current=m;const j=c.useRef(f);j.current=f;const $=c.useMemo(()=>l.map(A=>({reducer:A.reducer,property:Array.isArray(A.property)?A.property.map(O=>T(O)):T(A.property)})),[ke(l)]),I=c.useMemo(()=>A=>{const O=()=>{S.current++,A()},V=$.flatMap(x=>(Array.isArray(x.property)?x.property:[x.property]).map(J=>v.connect({reducer:x.reducer,property:J},O)));return()=>{for(const x of V)x()}},[v,$]),M=c.useCallback(()=>{if(k.current!==S.current||!_.current){const A=P.current(v.getState());(!_.current||!j.current(b.current,A))&&(b.current=A,_.current=!0),k.current=S.current}return b.current},[v]);return c.useSyncExternalStore(I,M,M)},y=(l,m,f,v="committed")=>{const S=e(),b=c.useRef(f);b.current=f,c.useEffect(()=>S.onEvent(l,m,(k,_,P,j)=>{b.current(k,_,P,j)},v),[S,l,m,v])},{useSuspenseAtomicProp:g,useSuspenseAtomicProps:d}=Ve(e);return{useStore:e,useEmit:n,useSelector:o,useAtomicProp:u,useAtomicProps:h,useEvent:y,useSuspenseAtomicProp:g,useSuspenseAtomicProps:d,shallowEqual:Se}}function Be(t){const e=Ae.createStore(t),n=c.createContext(e),o=ve(n);return{store:e,StoreContext:n,StoreProvider:({store:u,children:a})=>de.jsx(n.Provider,{value:u!=null?u:e,children:a}),...o}}function Je(t,e){return Q({reducer:t,property:e.idsPath})}function qe(t,e,n){return Q({reducer:t,property:e.pathTo(n)})}function Xe(t,e,n,o){return Q({reducer:t,property:e.pathTo(n,o)})}exports.StoreContext=K;exports.StoreProvider=xe;exports.clearSuspenseCache=Ue;exports.createHooks=ve;exports.createYoltra=Be;exports.invalidateAtomicProp=Ge;exports.invalidateAtomicPropsByReducer=Le;exports.shallowEqual=Se;exports.suspenseCache=N;exports.useEmit=Oe;exports.useEntity=qe;exports.useEntityField=Xe;exports.useEntityIds=Je;exports.useEvent=Me;exports.useSelector=Ce;exports.useStore=z;
16
32
  //# sourceMappingURL=index.cjs.map