@yoltra/react 0.3.0 → 0.5.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 +63 -4
- package/README.md +62 -4
- package/dist/index.cjs +19 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +442 -358
- package/dist/index.mjs.map +1 -1
- package/dist/types/context/StoreContext.d.ts +1 -1
- package/dist/types/createYoltra.d.ts +20 -3
- package/dist/types/entity/useEntity.d.ts +32 -0
- package/dist/types/hooks/createHooks.d.ts +7 -1
- package/dist/types/hooks/hooks.d.ts +14 -1
- package/dist/types/hooks/suspense.d.ts +66 -0
- package/dist/types/index.d.ts +12 -10
- package/dist/types/utils/declaredProjection.d.ts +40 -0
- package/package.json +25 -9
package/README.es.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
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 {
|
|
126
|
-
|
|
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
|
-
|
|
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
|
-

|
|
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 {
|
|
125
|
-
|
|
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
|
-
|
|
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.
|
|
2
|
+
* @yoltra/react v0.5.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
|
|
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 ce=(t,e,n)=>Re(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react"),Ae=require("@yoltra/core"),K=u.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 ue;function Pe(){if(ue)return D;ue=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(o,s,c){var a=null;if(c!==void 0&&(a=""+c),s.key!==void 0&&(a=""+s.key),"key"in s){c={};for(var h in s)h!=="key"&&(c[h]=s[h])}else c=s;return s=c.ref,{$$typeof:t,type:o,key:a,ref:s!==void 0?s:null,props:c}}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 y: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===y)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=w.A;return r===null?null:r.getOwner()}function c(){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 S(){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,x,X,H){return p=x.ref,r={$$typeof:f,type:r,key:i,props:x,_owner:C},(p!==void 0?p:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:S}):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,x,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,x,C,s(),p,X,H)}function l(r){typeof r=="object"&&r!==null&&r.$$typeof===f&&r._store&&(r._store.validated=1)}var m=u,f=Symbol.for("react.transitional.element"),v=Symbol.for("react.portal"),y=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"),w=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,c)(),oe=q(o(c)),se={};F.Fragment=y,F.jsx=function(r,i,p,E,C){var x=1e4>w.recentlyCreatedOwnerStacks++;return d(r,i,p,!1,E,C,x?Error("react-stack-top-frame"):ne,x?q(o(r)):oe)},F.jsxs=function(r,i,p,E,C){var x=1e4>w.recentlyCreatedOwnerStacks++;return d(r,i,p,!0,E,C,x?Error("react-stack-top-frame"):ne,x?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 we=({store:t,children:e})=>de.jsx(K.Provider,{value:t,children:e}),le=new Set;function xe(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===""&&xe("yoltra.toDottedPath.empty","[yoltra] A typed path accessor recorded no property access, so it subscribed to the slice root. That fires only when the slice's whole value is replaced — which for a slice holding an object means never, since its changes are reported at their leaves. 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 dynamic subscription, or for a slice whose state is a single value, 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=u.useRef(t);o.current=t;const s=u.useRef(e);s.current=e;const c=u.useMemo(()=>({has:!1,value:void 0}),n);return u.useCallback(()=>{const a=o.current();return(!c.has||!s.current(c.value,a))&&(c.has=!0,c.value=a),c.value},[c])}function ye(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=u.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=u.useMemo(()=>c=>n.subscribe(c),[n]),s=U(()=>t(n.getState()),e,[n]);return u.useSyncExternalStore(o,s,s)}function Ne(t,e,n=Object.is){const o=z(),s=u.useMemo(()=>{const S=T(t.property);return{reducer:t.reducer,property:S}},[t.reducer,t.property]),c=u.useMemo(()=>S=>o.connect({reducer:s.reducer,property:s.property},()=>S()),[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 u.useSyncExternalStore(c,h,h)}function Q(t,e,n=Object.is){return Ne(t,e,n)}function Me(t,e,n,o="committed"){const s=z(),c=u.useRef(n);c.current=n,u.useEffect(()=>s.onEvent(t,e,(a,h,S,g)=>{c.current(a,h,S,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(){ce(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 c=Date.now(),a=this.store.get(e);if(a&&a.status==="ready"&&(a.expiresAt==null||a.expiresAt>c))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>c)throw a.error;this.store.delete(e)}const h=Promise.resolve().then(n).then(S=>{this.store.set(e,{status:"ready",value:S,expiresAt:$e(o)})}).catch(S=>{this.store.set(e,{status:"error",error:S,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 Se(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,c=T(e.property),a=`${Se(o)}::${ee(s,c,n.key)}`,h=u.useMemo(()=>l=>o.connect({reducer:s,property:c},()=>{N.invalidate(a),l()}),[o,s,c,a]),S=u.useRef(n);S.current=n;const g=u.useMemo(()=>{const l=G(c);return()=>{var b;const f=o.getState()[s],v=l?f:L(f,c),y=S.current;return N.read(a,()=>y.load(v,f),(b=y.staleTime)!=null?b:0,y.errorTtlMs)}},[o,s,c,a]),d=u.useMemo(()=>{const l=G(c);return()=>{const f=o.getState()[s];return l?f:L(f,c)}},[o,s,c]);return u.useSyncExternalStore(h,g,d)}function We(t,e,n){const o=t(),s=u.useMemo(()=>e.map(d=>({reducer:d.reducer,property:Array.isArray(d.property)?d.property.map(l=>T(l)):T(d.property)})),[JSON.stringify(e)]),c=u.useMemo(()=>{const d=s.map(l=>ee(l.reducer,l.property)).sort().join("||");return`${Se(o)}::${n.key?`${d}::${n.key}`:d}`},[o,s,n.key]),a=u.useMemo(()=>d=>{const l=()=>{N.invalidate(c),d()},m=s.map(f=>o.connect(f,l));return()=>{for(const f of m)f()}},[o,s,c]),h=u.useRef(n);h.current=n;const S=u.useMemo(()=>()=>{var m;const d=o.getState(),l=h.current;return N.read(c,()=>l.load(d),(m=l.staleTime)!=null?m:0,l.errorTtlMs)},[o,c]),g=()=>{const d=h.current.load(o.getState());return d instanceof Promise?void 0:d};return u.useSyncExternalStore(a,S,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=u.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=u.useMemo(()=>b=>f.subscribe(b),[f]),y=U(()=>l(f.getState()),m,[f]);return u.useSyncExternalStore(v,y,y)}const c=(l,m,f)=>{const v=e(),y=typeof l=="string",b=y?l:l.reducer,k=y?je(m):l.property,_=y?void 0:m,P=u.useMemo(()=>({reducer:b,property:T(k)}),[b,k]),j=u.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 u.useSyncExternalStore(j,I,I)},h=(l,m,f=Object.is)=>{const v=e(),y=u.useRef(0),b=u.useRef(void 0),k=u.useRef(-1),_=u.useRef(!1),P=u.useRef(m);P.current=m;const j=u.useRef(f);j.current=f;const $=u.useMemo(()=>l.map(A=>({reducer:A.reducer,property:Array.isArray(A.property)?A.property.map(O=>T(O)):T(A.property)})),[ke(l)]),I=u.useMemo(()=>A=>{const O=()=>{y.current++,A()},V=$.flatMap(w=>(Array.isArray(w.property)?w.property:[w.property]).map(J=>v.connect({reducer:w.reducer,property:J},O)));return()=>{for(const w of V)w()}},[v,$]),M=u.useCallback(()=>{if(k.current!==y.current||!_.current){const A=P.current(v.getState());(!_.current||!j.current(b.current,A))&&(b.current=A,_.current=!0),k.current=y.current}return b.current},[v]);return u.useSyncExternalStore(I,M,M)},S=(l,m,f,v="committed")=>{const y=e(),b=u.useRef(f);b.current=f,u.useEffect(()=>y.onEvent(l,m,(k,_,P,j)=>{b.current(k,_,P,j)},v),[y,l,m,v])},{useSuspenseAtomicProp:g,useSuspenseAtomicProps:d}=Ve(e);return{useStore:e,useEmit:n,useSelector:o,useAtomicProp:c,useAtomicProps:h,useEvent:S,useSuspenseAtomicProp:g,useSuspenseAtomicProps:d,shallowEqual:ye}}function Be(t){const e=Ae.createStore(t),n=u.createContext(e),o=ve(n);return{store:e,StoreContext:n,StoreProvider:({store:c,children:a})=>de.jsx(n.Provider,{value:c!=null?c: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=we;exports.clearSuspenseCache=Ue;exports.createHooks=ve;exports.createYoltra=Be;exports.invalidateAtomicProp=Ge;exports.invalidateAtomicPropsByReducer=Le;exports.shallowEqual=ye;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
|