@yoltra/react 0.1.0 β 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.es.md +60 -55
- package/README.md +59 -57
- package/dist/index.cjs +6 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +483 -453
- package/dist/index.mjs.map +1 -1
- package/dist/types/createYoltra.d.ts +79 -0
- package/dist/types/hooks/createHooks.d.ts +27 -19
- package/dist/types/hooks/hooks.d.ts +1 -16
- package/dist/types/hooks/suspense.d.ts +24 -2
- package/dist/types/index.d.ts +3 -1
- package/dist/types/utils/shallowEqual.d.ts +19 -0
- package/dist/types/utils/useStableSnapshot.d.ts +4 -0
- package/package.json +4 -4
package/README.es.md
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
# @yoltra/react
|
|
4
4
|
|
|
5
5
|
> π π²π½ VersiΓ³n en EspaΓ±ol |
|
|
6
|
-
> [ πΊπΈ English Version](
|
|
6
|
+
> [ πΊπΈ English Version](./README.md)
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
**Hooks de React para [yoltra](
|
|
11
|
+
**Hooks de React para [yoltra](../../README.md) con
|
|
12
12
|
suscripciones de grano fino por ruta.**
|
|
13
13
|
|
|
14
14
|
Suscribete a `"items.0.title"` o `"items.*.done"` -- el componente se re-renderiza solo cuando
|
|
@@ -28,24 +28,24 @@ npm install @yoltra/core @yoltra/react
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Configuracion con `
|
|
31
|
+
## Configuracion con `createYoltra` (recomendado)
|
|
32
32
|
|
|
33
|
-
`
|
|
34
|
-
|
|
33
|
+
`createYoltra` crea el store **y** todos los hooks tipados en una sola llamada β sin archivo de
|
|
34
|
+
context aparte, sin cableado de `createHooks`, sin provider obligatorio. Todos los parametros de
|
|
35
|
+
tipo se infieren de tu reducer, asi que los componentes no necesitan generics explicitos.
|
|
35
36
|
|
|
36
|
-
### 1.
|
|
37
|
+
### 1. Crea el store y los hooks
|
|
37
38
|
|
|
38
|
-
```
|
|
39
|
-
//
|
|
40
|
-
import {
|
|
39
|
+
```tsx
|
|
40
|
+
// yoltra.ts
|
|
41
|
+
import { eventKeys } from "@yoltra/core";
|
|
42
|
+
import { createYoltra } from "@yoltra/react";
|
|
41
43
|
|
|
42
44
|
export type AppEM = {
|
|
43
45
|
counter: { increment: number; decrement: number; reset: null };
|
|
44
46
|
};
|
|
45
47
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
export const store = createStore<AppState, AppEM>({
|
|
48
|
+
export const { store, useAtomicProp, useEmit, StoreProvider } = createYoltra({
|
|
49
49
|
name: "App",
|
|
50
50
|
reducer: {
|
|
51
51
|
counter: {
|
|
@@ -74,39 +74,19 @@ export const store = createStore<AppState, AppEM>({
|
|
|
74
74
|
});
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
### 2.
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
// hooks.ts
|
|
81
|
-
import { createContext } from "react";
|
|
82
|
-
import { createHooks } from "@yoltra/react";
|
|
83
|
-
import type { StoreInstance } from "@yoltra/core";
|
|
84
|
-
import type { AppState, AppEM } from "./store";
|
|
85
|
-
|
|
86
|
-
export const AppStoreContext = createContext<StoreInstance<"counter", AppState, AppEM> | null>(
|
|
87
|
-
null,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
export const {
|
|
91
|
-
useStore,
|
|
92
|
-
useEmit,
|
|
93
|
-
useSelector,
|
|
94
|
-
useAtomicProp,
|
|
95
|
-
useAtomicProps,
|
|
96
|
-
useEvent,
|
|
97
|
-
shallowEqual,
|
|
98
|
-
} = createHooks(AppStoreContext);
|
|
99
|
-
```
|
|
77
|
+
### 2. Usa los hooks β sin provider
|
|
100
78
|
|
|
101
|
-
|
|
79
|
+
Los hooks usan por defecto el store de arriba, asi que puedes renderizar componentes directamente.
|
|
80
|
+
Suscribete con un **accessor tipado**: `s` autocompleta la forma de tu estado y el tipo de retorno
|
|
81
|
+
se infiere.
|
|
102
82
|
|
|
103
83
|
```tsx
|
|
104
|
-
//
|
|
105
|
-
import {
|
|
106
|
-
import { AppStoreContext, useAtomicProp, useEmit } from "./hooks";
|
|
84
|
+
// Counter.tsx
|
|
85
|
+
import { useAtomicProp, useEmit } from "./yoltra";
|
|
107
86
|
|
|
108
|
-
function Counter() {
|
|
109
|
-
|
|
87
|
+
export function Counter() {
|
|
88
|
+
// Accessor tipado β se re-renderiza solo cuando counter.value cambia. Sin selectores, sin memo.
|
|
89
|
+
const value = useAtomicProp("counter", (s) => s.value);
|
|
110
90
|
const emit = useEmit();
|
|
111
91
|
|
|
112
92
|
return (
|
|
@@ -118,27 +98,52 @@ function Counter() {
|
|
|
118
98
|
</div>
|
|
119
99
|
);
|
|
120
100
|
}
|
|
101
|
+
```
|
|
121
102
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
103
|
+
Un `<StoreProvider>` solo se necesita para acotar una instancia **diferente** del store a un
|
|
104
|
+
subarbol (p. ej. un store nuevo por test) β `createYoltra` devuelve uno justo para eso.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Avanzado: cableado manual con `createHooks`
|
|
109
|
+
|
|
110
|
+
Cuando necesites un mismo conjunto de hooks compartido entre varias instancias de store a traves
|
|
111
|
+
de tu propio context de React, vinculalos tu mismo con `createHooks(context)`. `createYoltra` es
|
|
112
|
+
este mismo cableado colapsado en una sola llamada.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// hooks.ts
|
|
116
|
+
import { createContext } from "react";
|
|
117
|
+
import { createHooks } from "@yoltra/react";
|
|
118
|
+
import type { StoreInstance } from "@yoltra/core";
|
|
119
|
+
import type { AppState, AppEM } from "./store";
|
|
120
|
+
|
|
121
|
+
export const AppStoreContext = createContext<StoreInstance<"counter", AppState, AppEM> | null>(
|
|
122
|
+
null,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
export const { useStore, useEmit, useSelector, useAtomicProp, useAtomicProps, useEvent, shallowEqual } =
|
|
126
|
+
createHooks(AppStoreContext);
|
|
129
127
|
```
|
|
130
128
|
|
|
129
|
+
Provee el store con `<AppStoreContext.Provider value={store}>` en tu raiz.
|
|
130
|
+
|
|
131
131
|
---
|
|
132
132
|
|
|
133
133
|
## API de Hooks
|
|
134
134
|
|
|
135
|
-
### `useAtomicProp({ reducer, property }, map?, isEqual?)`
|
|
135
|
+
### `useAtomicProp(reducer, accessor)` β o `useAtomicProp({ reducer, property }, map?, isEqual?)`
|
|
136
136
|
|
|
137
|
-
Selector de ruta unica con grano fino. Se re-renderiza solo cuando la
|
|
137
|
+
Selector de ruta unica con grano fino. Se re-renderiza solo cuando la hoja especificada cambia.
|
|
138
|
+
Prefiere la forma de **accessor tipado** β autocompleta la forma del estado e infiere el tipo de
|
|
139
|
+
retorno; usa la forma string para rutas dinamicas o con comodines.
|
|
138
140
|
|
|
139
141
|
```tsx
|
|
140
|
-
//
|
|
141
|
-
const title = useAtomicProp(
|
|
142
|
+
// Accessor tipado (recomendado) β autocompleta items[0].title, infiere string
|
|
143
|
+
const title = useAtomicProp("todos", (s) => s.items[0].title);
|
|
144
|
+
|
|
145
|
+
// Forma string β misma suscripcion, para rutas dinamicas
|
|
146
|
+
const sameTitle = useAtomicProp({
|
|
142
147
|
reducer: "todos",
|
|
143
148
|
property: "items.0.title",
|
|
144
149
|
});
|
|
@@ -375,15 +380,15 @@ function TodoItem({ index }: { index: number }) {
|
|
|
375
380
|
comparacion de flamegraph
|
|
376
381
|
- **[Logo Cinetico (3000 particulas)](../../examples/v0/yoltra-kinetic-logo)** -- Suscripciones
|
|
377
382
|
independientes por circulo SVG
|
|
378
|
-
- **[Next.js
|
|
383
|
+
- **[Next.js (Pages Router)](../../examples/v0/yoltra-in-nextjs)** -- estado de cliente + cambio de tema
|
|
379
384
|
|
|
380
385
|
---
|
|
381
386
|
|
|
382
387
|
## Documentacion
|
|
383
388
|
|
|
384
|
-
- **[README raiz de yoltra](
|
|
389
|
+
- **[README raiz de yoltra](../../README.md)** --
|
|
385
390
|
Descripcion general y configuracion rapida
|
|
386
|
-
- **[API de @yoltra/core](
|
|
391
|
+
- **[API de @yoltra/core](../core/README.md)**
|
|
387
392
|
-- Store, middleware, efectos, matchers `When`
|
|
388
393
|
- **[Guia de Inicio Rapido](https://github.com/yoltra/yoltra/blob/main/docs/en/QUICK_START_GUIDE.md)**
|
|
389
394
|
-- Cinco pasos hacia una app funcional
|
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# @yoltra/react
|
|
4
4
|
|
|
5
|
-
> [ π²π½ VersiΓ³n en EspaΓ±ol](
|
|
5
|
+
> [ π²π½ VersiΓ³n en EspaΓ±ol](./README.es.md)
|
|
6
6
|
> | π πΊπΈ English Version
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
**React hooks for [yoltra](
|
|
11
|
+
**React hooks for [yoltra](../../README.md) with
|
|
12
12
|
fine-grained path subscriptions.**
|
|
13
13
|
|
|
14
14
|
Subscribe to `"items.0.title"` or `"items.*.done"` β the component re-renders only when that
|
|
@@ -28,24 +28,24 @@ npm install @yoltra/core @yoltra/react
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## Setup with `
|
|
31
|
+
## Setup with `createYoltra` (recommended)
|
|
32
32
|
|
|
33
|
-
`
|
|
34
|
-
no
|
|
33
|
+
`createYoltra` creates the store **and** every fully-typed hook in one call β no separate context
|
|
34
|
+
file, no `createHooks` wiring, no required provider. All type parameters are inferred from your
|
|
35
|
+
reducer, so components need no explicit generics.
|
|
35
36
|
|
|
36
|
-
### 1.
|
|
37
|
+
### 1. Create the store and hooks
|
|
37
38
|
|
|
38
|
-
```
|
|
39
|
-
//
|
|
40
|
-
import {
|
|
39
|
+
```tsx
|
|
40
|
+
// yoltra.ts
|
|
41
|
+
import { eventKeys } from "@yoltra/core";
|
|
42
|
+
import { createYoltra } from "@yoltra/react";
|
|
41
43
|
|
|
42
44
|
export type AppEM = {
|
|
43
45
|
counter: { increment: number; decrement: number; reset: null };
|
|
44
46
|
};
|
|
45
47
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
export const store = createStore<AppState, AppEM>({
|
|
48
|
+
export const { store, useAtomicProp, useEmit, StoreProvider } = createYoltra({
|
|
49
49
|
name: "App",
|
|
50
50
|
reducer: {
|
|
51
51
|
counter: {
|
|
@@ -74,41 +74,18 @@ export const store = createStore<AppState, AppEM>({
|
|
|
74
74
|
});
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
### 2.
|
|
77
|
+
### 2. Use the hooks β no provider required
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
79
|
+
The hooks default to the store above, so you can render components directly. Subscribe with a
|
|
80
|
+
**typed accessor**: `s` autocompletes your state shape and the return type is inferred.
|
|
104
81
|
|
|
105
82
|
```tsx
|
|
106
|
-
//
|
|
107
|
-
import {
|
|
108
|
-
import { AppStoreContext, useAtomicProp, useEmit } from "./hooks";
|
|
83
|
+
// Counter.tsx
|
|
84
|
+
import { useAtomicProp, useEmit } from "./yoltra";
|
|
109
85
|
|
|
110
|
-
function Counter() {
|
|
111
|
-
|
|
86
|
+
export function Counter() {
|
|
87
|
+
// Typed accessor β re-renders only when counter.value changes. No selectors, no memo.
|
|
88
|
+
const value = useAtomicProp("counter", (s) => s.value);
|
|
112
89
|
const emit = useEmit();
|
|
113
90
|
|
|
114
91
|
return (
|
|
@@ -120,27 +97,52 @@ function Counter() {
|
|
|
120
97
|
</div>
|
|
121
98
|
);
|
|
122
99
|
}
|
|
100
|
+
```
|
|
123
101
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
102
|
+
A `<StoreProvider>` is only needed to scope a **different** store instance to a subtree (e.g. a
|
|
103
|
+
fresh store per test) β `createYoltra` returns one for exactly that.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Advanced: manual wiring with `createHooks`
|
|
108
|
+
|
|
109
|
+
When you need one set of hooks shared across several store instances through your own React
|
|
110
|
+
context, bind them yourself with `createHooks(context)`. `createYoltra` is this same wiring
|
|
111
|
+
collapsed into a single call.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// hooks.ts
|
|
115
|
+
import { createContext } from "react";
|
|
116
|
+
import { createHooks } from "@yoltra/react";
|
|
117
|
+
import type { StoreInstance } from "@yoltra/core";
|
|
118
|
+
import type { AppState, AppEM } from "./store";
|
|
119
|
+
|
|
120
|
+
export const AppStoreContext = createContext<StoreInstance<"counter", AppState, AppEM> | null>(
|
|
121
|
+
null,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
export const { useStore, useEmit, useSelector, useAtomicProp, useAtomicProps, useEvent, shallowEqual } =
|
|
125
|
+
createHooks(AppStoreContext);
|
|
131
126
|
```
|
|
132
127
|
|
|
128
|
+
Provide the store with `<AppStoreContext.Provider value={store}>` at your root.
|
|
129
|
+
|
|
133
130
|
---
|
|
134
131
|
|
|
135
132
|
## Hooks API
|
|
136
133
|
|
|
137
|
-
### `useAtomicProp({ reducer, property }, map?, isEqual?)`
|
|
134
|
+
### `useAtomicProp(reducer, accessor)` β or `useAtomicProp({ reducer, property }, map?, isEqual?)`
|
|
138
135
|
|
|
139
|
-
Fine-grained single-path selector. Re-renders only when the specified
|
|
136
|
+
Fine-grained single-path selector. Re-renders only when the specified leaf changes. Prefer the
|
|
137
|
+
**typed accessor** form β it autocompletes the state shape and infers the return type; use the
|
|
138
|
+
string form for dynamic or wildcard paths.
|
|
140
139
|
|
|
141
140
|
```tsx
|
|
142
|
-
//
|
|
143
|
-
const title = useAtomicProp(
|
|
141
|
+
// Typed accessor (recommended) β autocompletes items[0].title, infers string
|
|
142
|
+
const title = useAtomicProp("todos", (s) => s.items[0].title);
|
|
143
|
+
|
|
144
|
+
// String form β same subscription, for dynamic paths
|
|
145
|
+
const sameTitle = useAtomicProp({
|
|
144
146
|
reducer: "todos",
|
|
145
147
|
property: "items.0.title",
|
|
146
148
|
});
|
|
@@ -375,15 +377,15 @@ function TodoItem({ index }: { index: number }) {
|
|
|
375
377
|
comparison
|
|
376
378
|
- **[Kinetic Logo (3000 particles)](../../examples/v0/yoltra-kinetic-logo)** β Independent
|
|
377
379
|
subscriptions per circle
|
|
378
|
-
- **[Next.js
|
|
380
|
+
- **[Next.js (Pages Router)](../../examples/v0/yoltra-in-nextjs)** β client-side state + theme switcher
|
|
379
381
|
|
|
380
382
|
---
|
|
381
383
|
|
|
382
384
|
## Documentation
|
|
383
385
|
|
|
384
|
-
- **[yoltra Root README](
|
|
386
|
+
- **[yoltra Root README](../../README.md)** β Overview and
|
|
385
387
|
quick start
|
|
386
|
-
- **[@yoltra/core API](
|
|
388
|
+
- **[@yoltra/core API](../core/README.md)** β
|
|
387
389
|
Store, middleware, effects, `When` matchers
|
|
388
390
|
- **[Quick Start Guide](https://github.com/yoltra/yoltra/blob/main/docs/en/QUICK_START_GUIDE.md)**
|
|
389
391
|
β Five steps to a working app
|
package/dist/index.cjs
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @yoltra/react v0.
|
|
2
|
+
* @yoltra/react v0.2.0
|
|
3
3
|
* (c) 2026 Manu Ramirez <@pixerael>
|
|
4
4
|
* License: MIT
|
|
5
5
|
* Homepage: https://yoltra.dev
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree
|
|
6
9
|
*/
|
|
7
|
-
"use strict";var
|
|
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:
|
|
8
11
|
let props = %s;
|
|
9
12
|
<%s {...props} />
|
|
10
13
|
React keys must be passed directly to JSX without using spread:
|
|
11
14
|
let props = %s;
|
|
12
|
-
<%s key={someKey} {...props} />`,A,
|
|
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;
|
|
13
16
|
//# sourceMappingURL=index.cjs.map
|