@yakocloud/state-vocab 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,7 +117,7 @@ npm install @yakocloud/state-vocab react react-dom
117
117
 
118
118
  ## Quick Start
119
119
 
120
- Wrap your app with `StateVocabProvider` at the root this initializes an isolated store for the component tree. Then define and use state anywhere inside it.
120
+ Define your storage tree once (`setupStorage`/`defineState`), call `clientify` to attach React hooks. If you use react server components (RSC) wrap your app with `StateVocabProvider` at the root and call `serverify` to attach RSC-methods. Use state anywhere in the tree
121
121
 
122
122
  Library SSR-requirements:
123
123
  - `Per-request store`: A Next.js server can handle multiple requests simultaneously. This means that the store should be created per request and should not be shared across requests.
@@ -125,11 +125,11 @@ Library SSR-requirements:
125
125
 
126
126
  ```tsx
127
127
  import { setupStorage, defineState } from '@yakocloud/state-vocab'
128
- import { clientify, StateVocabProvider } from '@yakocloud/state-vocab/client'
128
+ import { clientify } from '@yakocloud/state-vocab/client'
129
129
 
130
130
  type Theme = 'Dark' | 'White' | 'System'
131
131
 
132
- const storage = clientify(setupStorage({
132
+ const storage = setupStorage({
133
133
  path: {
134
134
  to: {
135
135
  theme: defineState<Theme>({
@@ -138,18 +138,14 @@ const storage = clientify(setupStorage({
138
138
  }),
139
139
  },
140
140
  },
141
- }))
141
+ }, {
142
+ ssr: false // by default true
143
+ })
142
144
 
143
- function App() {
144
- return (
145
- <StateVocabProvider>
146
- <Settings />
147
- </StateVocabProvider>
148
- )
149
- }
145
+ const clientStorage = clientify(storage)
150
146
 
151
147
  function Settings() {
152
- const [theme, setTheme] = storage.path.to.theme.useState()
148
+ const [theme, setTheme] = clientStorage.path.to.theme.useState()
153
149
 
154
150
  return (
155
151
  <select value={theme} onChange={(e) => setTheme(e.target.value as Theme)}>
@@ -161,37 +157,6 @@ function Settings() {
161
157
  }
162
158
  ```
163
159
 
164
- ## Setup
165
-
166
- ### `StateVocabProvider`
167
-
168
- All components that call `.useState()` must be descendants of `StateVocabProvider`. It creates an isolated `VocabStore` instance for its subtree — multiple providers can coexist in the same app without sharing state.
169
-
170
- ```tsx
171
- import { StateVocabProvider } from '@yakocloud/state-vocab/client'
172
-
173
- createRoot(document.getElementById('root')!).render(
174
- <React.StrictMode>
175
- <StateVocabProvider>
176
- <App />
177
- </StateVocabProvider>
178
- </React.StrictMode>
179
- )
180
- ```
181
-
182
- You can mount multiple independent providers — each gets its own store:
183
-
184
- ```tsx
185
- // Two isolated state trees — state does not bleed between them
186
- <StateVocabProvider>
187
- <WidgetA />
188
- </StateVocabProvider>
189
-
190
- <StateVocabProvider>
191
- <WidgetB />
192
- </StateVocabProvider>
193
- ```
194
-
195
160
  ## Core Concepts
196
161
 
197
162
  ### `defineState(options?)`
@@ -237,7 +202,7 @@ Wraps a nested object of `defineState()` nodes and injects dot-separated paths i
237
202
  |---|---|---|---|
238
203
  | `verbose` | `boolean \| undefined` | Log current state to the browser console on every change | `false` |
239
204
  | `verbosePath` | `string \| undefined` | Narrow verbose logging to a specific subtree (dot-separated path). When set, only that subtree is logged instead of the entire state. TypeScript will autocomplete valid paths based on your tree. | `undefined` |
240
- | `ssr` | `boolean \| undefined` | Defer storage reads until after hydration (Next.js / SSR) | `false` |
205
+ | `ssr` | `boolean \| undefined` | Defer storage reads until after hydration (Next.js / SSR) | `true` |
241
206
 
242
207
  ```ts
243
208
  const storage = setupStorage({
@@ -286,10 +251,10 @@ const storage = setupStorage({
286
251
  preference: {
287
252
  theme: defineState<Theme>({ storage: localStorage, defaultValue: 'Dark' }),
288
253
  },
289
- }, { ssr: true })
254
+ })
290
255
  ```
291
256
 
292
- With `ssr: true`:
257
+ By default `ssr: true`:
293
258
  - **Server & first client render** — always use `defaultValue`, storage is not read
294
259
  - **After hydration** — `useLayoutEffect` fires synchronously before paint, reads storage and updates state
295
260
 
@@ -304,7 +269,7 @@ For Next.js apps using the App Router, state-vocab provides dedicated server and
304
269
  | Import path | Use in |
305
270
  |---|---|
306
271
  | `@yakocloud/state-vocab` | Shared files — `defineState`, `setupStorage` |
307
- | `@yakocloud/state-vocab/server` | Server Components — `serverify`, `StateVocabProvider` |
272
+ | `@yakocloud/state-vocab/server` | Server Components — `serverify` |
308
273
  | `@yakocloud/state-vocab/client` | Client Components — `clientify` |
309
274
 
310
275
  **1. Define the shared storage schema** (used on both server and client):
@@ -323,7 +288,7 @@ export const storage = setupStorage({
323
288
  city: defineState<string>(),
324
289
  },
325
290
  },
326
- }, { ssr: true })
291
+ })
327
292
  ```
328
293
 
329
294
  **2. Create server and client storage handles:**
@@ -351,7 +316,8 @@ export const clientStorage = clientify(storage)
351
316
  ```tsx
352
317
  // app/page.tsx (Server Component)
353
318
  import { serverStorage } from '@/storage.server'
354
- import { StateVocabProvider } from '@yakocloud/state-vocab/server'
319
+
320
+ const { StateVocabProvider } = serverStorage
355
321
 
356
322
  export default async function Page() {
357
323
  // Fetch data from DB / API
@@ -359,10 +325,10 @@ export default async function Page() {
359
325
 
360
326
  return (
361
327
  <StateVocabProvider
362
- value={serverStorage({
328
+ value={{
363
329
  user: { name: user.name, role: user.role },
364
330
  person: { address: { city: user.city } },
365
- })}
331
+ }}
366
332
  >
367
333
  <UserInfo />
368
334
  </StateVocabProvider>
@@ -398,35 +364,24 @@ export default function UserInfoClient() {
398
364
 
399
365
  #### `serverify(storage)`
400
366
 
401
- Converts a storage tree into its server-side counterpart. Each leaf gains a `.getState()` method that reads the value seeded into the nearest `StateVocabProvider`. All namespace nodes become callable functions that build the `value` shape expected by `StateVocabProvider`.
367
+ Converts a storage tree into its server-side counterpart. Each leaf gains a `.getState()` method that reads the value seeded into the nearest `StateVocabProvider`. Each namespace node (including the root) gains a `.seed()` method that returns the input wrapped under its full ancestor path. This method is optional for using. The result also exposes `StateVocabProvider` — a server-aware provider that accepts a plain object `value` prop to pre-seed the store.
402
368
 
403
- **Namespace callable syntax:**
369
+ **`.seed()` syntax:**
404
370
 
405
371
  ```ts
406
- // Full tree at once — root call is identity (returns input as-is)
407
- serverStorage({ user: { name: 'Alice', role: 'Admin' } })
372
+ // Full tree at once — root .seed() returns input as-is
373
+ serverStorage.seed({ user: { name: 'Alice', role: 'Admin' } })
408
374
  // → { user: { name: 'Alice', role: 'Admin' } }
409
375
 
410
376
  // Single namespace — wraps input under its key
411
- serverStorage.user({ name: 'Alice', role: 'Admin' })
377
+ serverStorage.user.seed({ name: 'Alice', role: 'Admin' })
412
378
  // → { user: { name: 'Alice', role: 'Admin' } }
413
379
 
414
380
  // Nested namespace — wraps up to the root
415
- serverStorage.person.address({ city: 'NY' })
381
+ serverStorage.person.address.seed({ city: 'NY' })
416
382
  // → { person: { address: { city: 'NY' } } }
417
383
  ```
418
384
 
419
- All three forms return a value ready to pass as `StateVocabProvider`'s `value` prop. They can be combined by spreading:
420
-
421
- ```tsx
422
- <StateVocabProvider
423
- value={{
424
- ...serverStorage.user({ name: 'Alice', role: 'Admin' }),
425
- ...serverStorage.person.address({ city: 'NY' }),
426
- }}
427
- >
428
- ```
429
-
430
385
  **`node.getState()`** reads the value for that leaf from the surrounding `StateVocabProvider`. Throws if called outside one.
431
386
 
432
387
  #### `clientify(storage)`
@@ -521,11 +476,11 @@ const storage = setupStorage({
521
476
  import React from 'react'
522
477
  import { createRoot } from 'react-dom/client'
523
478
  import { setupStorage, defineState } from '@yakocloud/state-vocab'
524
- import { clientify, StateVocabProvider } from '@yakocloud/state-vocab/client'
479
+ import { clientify } from '@yakocloud/state-vocab/client'
525
480
 
526
481
  type Theme = 'Dark' | 'White' | 'System'
527
482
 
528
- const storage = clientify(setupStorage({
483
+ const storage = setupStorage({
529
484
  preference: {
530
485
  theme: defineState<Theme>({ storage: localStorage, defaultValue: 'Dark' }),
531
486
  nightMode: defineState({ storage: sessionStorage, defaultValue: false }),
@@ -547,11 +502,15 @@ const storage = clientify(setupStorage({
547
502
  storage: localStorage,
548
503
  }),
549
504
  },
550
- }))
505
+ }, {
506
+ ssr: false // by default true
507
+ })
508
+
509
+ const clientStorage = clientify(storage)
551
510
 
552
511
  // Root — initializes shared state for the whole subtree
553
512
  function Page() {
554
- storage.demo.pageProps.useState({
513
+ clientStorage.demo.pageProps.useState({
555
514
  defaultValue: { title: 'Hello', count: 42 },
556
515
  })
557
516
 
@@ -560,15 +519,15 @@ function Page() {
560
519
 
561
520
  // Deep child — reads without re-specifying defaults
562
521
  function PageHeader() {
563
- const [pageProps] = storage.demo.pageProps.useState()
522
+ const [pageProps] = clientStorage.demo.pageProps.useState()
564
523
  return <h1>{pageProps.title} ({pageProps.count})</h1>
565
524
  }
566
525
 
567
526
  function Dashboard() {
568
- const [theme, setTheme] = storage.preference.theme.useState()
569
- const [nightMode, setNightMode] = storage.preference.nightMode.useState()
570
- const [counter, setCounter, resetCounter] = storage.stats.counter.useState()
571
- const [note, setNote] = storage.personal.note.useState({
527
+ const [theme, setTheme] = clientStorage.preference.theme.useState()
528
+ const [nightMode, setNightMode] = clientStorage.preference.nightMode.useState()
529
+ const [counter, setCounter, resetCounter] = clientStorage.stats.counter.useState()
530
+ const [note, setNote] = clientStorage.personal.note.useState({
572
531
  delayedSet: 500,
573
532
  onSet: (v) => console.log('Saving note:', v),
574
533
  })
@@ -607,9 +566,7 @@ function Dashboard() {
607
566
 
608
567
  createRoot(document.getElementById('root')!).render(
609
568
  <React.StrictMode>
610
- <StateVocabProvider>
611
- <Page />
612
- </StateVocabProvider>
569
+ <Page />
613
570
  </React.StrictMode>
614
571
  )
615
572
  ```
@@ -632,24 +589,20 @@ createRoot(document.getElementById('root')!).render(
632
589
  |---|---|---|
633
590
  | `verbose` | `boolean \| undefined` | `false` |
634
591
  | `verbosePath` | `Path<T> \| undefined` | `undefined` |
635
- | `ssr` | `boolean \| undefined` | `false` |
592
+ | `ssr` | `boolean \| undefined` | `true` |
636
593
 
637
594
  Returns a proxied copy of `tree` with paths injected into all leaf nodes.
638
595
 
639
596
  ### `StateVocabProvider`
640
597
 
641
- A React context provider that initializes a `VocabStore` for its subtree. Required all components calling `.useState()` must be descendants of this provider.
598
+ A React context provider that initializes a `VocabStore` for its subtree. Only required in RSC / Next.js App Router contexts (where `ssr: true`). For standard SPAs without SSR, no provider is needed — hooks use a module-level store automatically.
642
599
 
643
- ```tsx
644
- <StateVocabProvider>
645
- <App />
646
- </StateVocabProvider>
647
- ```
648
-
649
- Accepts an optional `value` prop (imported from `@yakocloud/state-vocab/server` in RSC contexts) to pre-seed the store with server-fetched data:
600
+ In RSC contexts, `StateVocabProvider` is available on the `serverify()` result — it accepts an optional `value` prop to pre-seed the store with server-fetched data:
650
601
 
651
602
  ```tsx
652
- <StateVocabProvider value={serverStorage({ user: { name: 'Alice' } })}>
603
+ const { StateVocabProvider } = serverStorage
604
+
605
+ <StateVocabProvider value={{ user: { name: 'Alice' } }}>
653
606
  <App />
654
607
  </StateVocabProvider>
655
608
  ```
@@ -658,16 +611,18 @@ Accepts an optional `value` prop (imported from `@yakocloud/state-vocab/server`
658
611
 
659
612
  Converts a storage tree to its server-side counterpart. Available from `@yakocloud/state-vocab/server`.
660
613
 
661
- Each leaf gains `.getState()` — reads the value from the nearest `StateVocabProvider`. Each namespace node becomes callable, returning the input wrapped under its full ancestor path (ready for `StateVocabProvider`'s `value` prop).
614
+ Each leaf gains `.getState()` — reads the value from the nearest `StateVocabProvider`. Each namespace node gains `.seed()`, which returns the input wrapped under its full ancestor path. The result also includes `StateVocabProvider` use it instead of importing from `@yakocloud/state-vocab/server`.
662
615
 
663
616
  ```ts
664
617
  import { serverify } from '@yakocloud/state-vocab/server'
665
618
  const serverStorage = serverify(storage)
666
619
 
667
- serverStorage.user.name.getState() // reads "user.name" from context
668
- serverStorage.user({ name: 'Alice' }) // → { user: { name: 'Alice' } }
669
- serverStorage.person.address({ city: 'NY' }) // { person: { address: { city: 'NY' } } }
670
- serverStorage({ user: { name: 'Alice' } }) // → { user: { name: 'Alice' } } (identity)
620
+ const { StateVocabProvider } = serverStorage // server-aware provider
621
+
622
+ serverStorage.user.name.getState() // reads "user.name" from context
623
+ serverStorage.user.seed({ name: 'Alice' }) // → { user: { name: 'Alice' } }
624
+ serverStorage.person.address.seed({ city: 'NY' }) // → { person: { address: { city: 'NY' } } }
625
+ serverStorage.seed({ user: { name: 'Alice' } }) // → { user: { name: 'Alice' } } (identity)
671
626
  ```
672
627
 
673
628
  ### `clientify<T>(storage: T)`
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),t=require("./utils-33NqsZoR.js"),z=require("./provider.client--OPImdtY.js");function D(s,e,o=[]){return c.useMemo(()=>t.debounce(s,e),o)}const O=typeof window>"u",w=O?c.useEffect:c.useLayoutEffect;function _(s){s??={};const e=O?void 0:t.valueOrFactory(s.storage),o=t.valueOrFactory(s.defaultValue),l=s.bidirectional,n=this[t.STATE_PATH],y=this[t.STATE_VERBOSE],V=this[t.STATE_VERBOSE_PATH],T=this[t.STATE_SSR],r=z.useStateVocabClientContext({verbose:y});if(!(r instanceof z.VocabStore))throw new Error("Make sure your component is wrapped in StateVocabProvider");const d=s.serialize??JSON.stringify,E=s.deserialize??JSON.parse,a=(i,f,m)=>{const v=f.getItem(i);v===null?t.isValueDefined(m)&&f.setItem(i,d(m)):r.set(i,E(v))},u=D(s.onSet??(()=>{}),s.delayedSet,[]),S=c.useRef(void 0),g=c.useRef(!1);if(!g.current){g.current=!0;let i=r.get(n);t.isValueDefined(i)||(i=o,t.isValueDefined(i)&&r.set(n,i)),!T&&e&&a(n,e,i)}const b=c.useSyncExternalStore(r.subscribe.bind(r),r.getClientSnapshot.bind(r),r.getServerSnapshot.bind(r));if(y)if(V){const i=t.get(b,V);i&&t.logStyled(i)}else t.logStyled(b);const h=t.get(b,n,o);S.current=h,w(()=>{!T||!e||a(n,e,h)},[]);const R=c.useEffectEvent(i=>{if(i.key!==n)return;const f=i.newValue,v=(f===null?null:E(f))??o;t.isValueDefined(v)&&(r.set(n,v),u(v,S.current))});c.useEffect(()=>{if(l)return window.addEventListener("storage",R),()=>window.removeEventListener("storage",R)},[l]);const I=c.useCallback(i=>{const f=t.isTransformer(i)?i(S.current):i;r.set(n,f),u(f,S.current),e&&e.setItem(n,d(f))},[r,n,u,e,d]),C=c.useCallback(()=>{const i=o;if(!t.isValueDefined(i)){e?.removeItem(n);return}r.set(n,i),u(i,S.current),e&&e.setItem(n,d(i))},[o,r,n,u,e,d]);return[h,I,C]}function p(s){s??={};const e=O?void 0:t.valueOrFactory(s.storage),o=t.valueOrFactory(s.defaultValue),l=this[t.STATE_PATH],n=this[t.STATE_VERBOSE],y=this[t.STATE_SSR],V=z.useStateVocabClientContext({verbose:n}),T=s.serialize??JSON.stringify,r=s.deserialize??JSON.parse,d=(u,S,g)=>{const b=S.getItem(u);b===null?t.isValueDefined(g)&&S.setItem(u,T(g)):V.set(u,r(b))},E=c.useRef(!1);let a;E.current||(E.current=!0,a=V.get(l),t.isValueDefined(a)||(a=o,t.isValueDefined(a)&&V.set(l,a)),!y&&e&&d(l,e,a)),w(()=>{!y||!e||d(l,e,a)},[])}function P(s){return typeof s=="object"&&s!==null&&"clientSlot"in s}function A(s){const e={};for(const o in s){const l=s[o];P(l)?(e[o]=l.clientSlot({useState(...n){return _.apply(this,n)},useInitialState(...n){p.apply(this,n)}}),delete e[o].serverSlot,delete e[o].clientSlot):l!==null&&typeof l=="object"?e[o]=A(l):e[o]=l}return e}exports.StateVocabProvider=z.StateVocabClientProvider;exports.clientify=A;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react"),v=require("./constants-CbsduCZ7.js"),a=require("./utils-0CTNJ4ZE.js"),y=require("./provider-client-B4XQ24JB.js");function D(t,e,n=[]){return u.useMemo(()=>a.debounce(t,e),n)}const g=t=>{const{vocabStore:e,storage:n,statePath:o,value:s,deserialize:S,serialize:l}=t,f=n.getItem(o);f===null?a.isValueDefined(s)&&n.setItem(o,l(s)):e.set(o,S(f))},z=typeof window>"u",m=z?u.useEffect:u.useLayoutEffect,A=new y.VocabStore,C="Make sure your component is wrapped in StateVocabProvider (RSC) or disable ssr option in setupStorage for SPA (RCC only)";function I(t){t??={};const e=z?void 0:a.valueOrFactory(t.storage),n=a.valueOrFactory(t.defaultValue),o=t.bidirectional,s=this[v.STATE_PATH],S=this[v.STATE_VERBOSE],l=this[v.STATE_VERBOSE_PATH],f=this[v.STATE_SSR];let i=y.useStateVocabClientContext({verbose:S});if(!(i instanceof y.VocabStore)){if(f)throw new Error(C);i=A}const d=t.serialize??JSON.stringify,c=t.deserialize??JSON.parse,V=D(t.onSet??(()=>{}),t.delayedSet,[]),E=u.useRef(void 0),w=u.useRef(!1);if(!w.current){w.current=!0;let r=i.get(s);a.isValueDefined(r)||(r=n,a.isValueDefined(r)&&i.set(s,r)),!f&&e&&g({vocabStore:i,storage:e,statePath:s,value:r,serialize:d,deserialize:c})}const h=u.useSyncExternalStore(i.subscribe.bind(i),i.getClientSnapshot.bind(i),i.getServerSnapshot.bind(i));if(S)if(l){const r=a.get(h,l);r&&a.logStyled(r)}else a.logStyled(h);const T=a.get(h,s,n);E.current=T,m(()=>{!f||!e||g({vocabStore:i,storage:e,statePath:s,value:T,serialize:d,deserialize:c})},[]);const O=u.useEffectEvent(r=>{if(r.key!==s)return;const b=r.newValue,R=(b===null?null:c(b))??n;a.isValueDefined(R)&&(i.set(s,R),V(R,E.current))});u.useEffect(()=>{if(o)return window.addEventListener("storage",O),()=>window.removeEventListener("storage",O)},[o]);const p=u.useCallback(r=>{const b=a.isTransformer(r)?r(E.current):r;i.set(s,b),V(b,E.current),e&&e.setItem(s,d(b))},[i,s,V,e,d]),_=u.useCallback(()=>{const r=n;if(!a.isValueDefined(r)){e?.removeItem(s);return}i.set(s,r),V(r,E.current),e&&e.setItem(s,d(r))},[n,i,s,V,e,d]);return[T,p,_]}function k(t){t??={};const e=z?void 0:a.valueOrFactory(t.storage),n=a.valueOrFactory(t.defaultValue),o=this[v.STATE_PATH],s=this[v.STATE_VERBOSE],S=this[v.STATE_SSR];let l=y.useStateVocabClientContext({verbose:s});if(!(l instanceof y.VocabStore)){if(S)throw new Error(C);l=A}const f=t.serialize??JSON.stringify,i=t.deserialize??JSON.parse,d=u.useRef(!1);let c;d.current||(d.current=!0,c=l.get(o),a.isValueDefined(c)||(c=n,a.isValueDefined(c)&&l.set(o,c)),!S&&e&&g({vocabStore:l,storage:e,statePath:o,value:c,serialize:f,deserialize:i})),m(()=>{!S||!e||g({vocabStore:l,storage:e,statePath:o,value:c,serialize:f,deserialize:i})},[])}function q(t){return typeof t=="object"&&t!==null&&"clientSlot"in t}function P(t){const e={};for(const n in t){const o=t[n];q(o)?(e[n]=o.clientSlot({useState(...s){return I.apply(this,s)},useInitialState(...s){k.apply(this,s)}}),delete e[n].serverSlot,delete e[n].clientSlot):o!==null&&typeof o=="object"?e[n]=P(o):e[n]=o}return e}exports.clientify=P;
package/dist/client.es.js CHANGED
@@ -1,107 +1,149 @@
1
1
  "use client";
2
- import { useMemo as j, useRef as T, useSyncExternalStore as x, useEffectEvent as B, useEffect as A, useCallback as I, useLayoutEffect as D } from "react";
3
- import { d as H, v as E, S as C, a as _, b as k, i as d, c as M, g as O, l as R, e as F } from "./utils-t8tYdd6B.mjs";
4
- import { u as J, V as q } from "./provider.client-CtAC9tPr.mjs";
5
- import { S as te } from "./provider.client-CtAC9tPr.mjs";
6
- function G(s, e, n = []) {
7
- return j(
8
- () => H(s, e),
2
+ import { useMemo as B, useRef as V, useSyncExternalStore as D, useEffectEvent as H, useEffect as I, useCallback as T, useLayoutEffect as x } from "react";
3
+ import { S as O, a as P, b as _, c as F } from "./constants-BB1YAX6c.mjs";
4
+ import { a as d, d as G, v as g, g as A, l as C, i as q } from "./utils-xV3x3fTc.mjs";
5
+ import { V as z, u as k } from "./provider-client-C2Aw0Lmi.mjs";
6
+ function K(t, e, n = []) {
7
+ return B(
8
+ () => G(t, e),
9
9
  // eslint-disable-next-line react-hooks/exhaustive-deps
10
10
  n
11
11
  );
12
12
  }
13
- const p = typeof window > "u", L = p ? A : D;
14
- function K(s) {
15
- s ??= {};
16
- const e = p ? void 0 : E(s.storage), n = E(s.defaultValue), o = s.bidirectional, r = this[C], m = this[_], S = this[M], g = this[k], i = J({ verbose: m });
17
- if (!(i instanceof q))
18
- throw new Error("Make sure your component is wrapped in StateVocabProvider");
19
- const u = s.serialize ?? JSON.stringify, y = s.deserialize ?? JSON.parse, a = (t, l, h) => {
20
- const v = l.getItem(t);
21
- v === null ? d(h) && l.setItem(t, u(h)) : i.set(t, y(v));
22
- }, c = G(
23
- s.onSet ?? (() => {
13
+ const E = (t) => {
14
+ const {
15
+ vocabStore: e,
16
+ storage: n,
17
+ statePath: o,
18
+ value: s,
19
+ deserialize: f,
20
+ serialize: a
21
+ } = t, c = n.getItem(o);
22
+ c === null ? d(s) && n.setItem(o, a(s)) : e.set(o, f(c));
23
+ }, w = typeof window > "u", J = w ? I : x, L = new z(), N = "Make sure your component is wrapped in StateVocabProvider (RSC) or disable ssr option in setupStorage for SPA (RCC only)";
24
+ function Q(t) {
25
+ t ??= {};
26
+ const e = w ? void 0 : g(t.storage), n = g(t.defaultValue), o = t.bidirectional, s = this[O], f = this[P], a = this[F], c = this[_];
27
+ let r = k({ verbose: f });
28
+ if (!(r instanceof z)) {
29
+ if (c)
30
+ throw new Error(N);
31
+ r = L;
32
+ }
33
+ const u = t.serialize ?? JSON.stringify, l = t.deserialize ?? JSON.parse, v = K(
34
+ t.onSet ?? (() => {
24
35
  }),
25
- s.delayedSet,
36
+ t.delayedSet,
26
37
  []
27
- ), f = T(void 0), V = T(!1);
28
- if (!V.current) {
29
- V.current = !0;
30
- let t = i.get(r);
31
- d(t) || (t = n, d(t) && i.set(r, t)), !g && e && a(r, e, t);
38
+ ), b = V(void 0), p = V(!1);
39
+ if (!p.current) {
40
+ p.current = !0;
41
+ let i = r.get(s);
42
+ d(i) || (i = n, d(i) && r.set(s, i)), !c && e && E({
43
+ vocabStore: r,
44
+ storage: e,
45
+ statePath: s,
46
+ value: i,
47
+ serialize: u,
48
+ deserialize: l
49
+ });
32
50
  }
33
- const b = x(
34
- i.subscribe.bind(i),
35
- i.getClientSnapshot.bind(i),
36
- i.getServerSnapshot.bind(i)
51
+ const h = D(
52
+ r.subscribe.bind(r),
53
+ r.getClientSnapshot.bind(r),
54
+ r.getServerSnapshot.bind(r)
37
55
  );
38
- if (m)
39
- if (S) {
40
- const t = O(b, S);
41
- t && R(t);
56
+ if (f)
57
+ if (a) {
58
+ const i = A(h, a);
59
+ i && C(i);
42
60
  } else
43
- R(b);
44
- const z = O(b, r, n);
45
- f.current = z, L(() => {
46
- !g || !e || a(r, e, z);
61
+ C(h);
62
+ const m = A(h, s, n);
63
+ b.current = m, J(() => {
64
+ !c || !e || E({
65
+ vocabStore: r,
66
+ storage: e,
67
+ statePath: s,
68
+ value: m,
69
+ serialize: u,
70
+ deserialize: l
71
+ });
47
72
  }, []);
48
- const w = B((t) => {
49
- if (t.key !== r)
73
+ const R = H((i) => {
74
+ if (i.key !== s)
50
75
  return;
51
- const l = t.newValue, v = (l === null ? null : y(l)) ?? n;
52
- d(v) && (i.set(r, v), c(v, f.current));
76
+ const S = i.newValue, y = (S === null ? null : l(S)) ?? n;
77
+ d(y) && (r.set(s, y), v(y, b.current));
53
78
  });
54
- A(() => {
79
+ I(() => {
55
80
  if (o)
56
- return window.addEventListener("storage", w), () => window.removeEventListener("storage", w);
81
+ return window.addEventListener("storage", R), () => window.removeEventListener("storage", R);
57
82
  }, [o]);
58
- const N = I((t) => {
59
- const l = F(t) ? t(f.current) : t;
60
- i.set(r, l), c(l, f.current), e && e.setItem(r, u(l));
61
- }, [i, r, c, e, u]), P = I(() => {
62
- const t = n;
63
- if (!d(t)) {
64
- e?.removeItem(r);
83
+ const M = T((i) => {
84
+ const S = q(i) ? i(b.current) : i;
85
+ r.set(s, S), v(S, b.current), e && e.setItem(s, u(S));
86
+ }, [r, s, v, e, u]), j = T(() => {
87
+ const i = n;
88
+ if (!d(i)) {
89
+ e?.removeItem(s);
65
90
  return;
66
91
  }
67
- i.set(r, t), c(t, f.current), e && e.setItem(r, u(t));
68
- }, [n, i, r, c, e, u]);
92
+ r.set(s, i), v(i, b.current), e && e.setItem(s, u(i));
93
+ }, [n, r, s, v, e, u]);
69
94
  return [
70
- z,
71
- N,
72
- P
95
+ m,
96
+ M,
97
+ j
73
98
  ];
74
99
  }
75
- function Q(s) {
76
- s ??= {};
77
- const e = p ? void 0 : E(s.storage), n = E(s.defaultValue), o = this[C], r = this[_], m = this[k], S = J({ verbose: r }), g = s.serialize ?? JSON.stringify, i = s.deserialize ?? JSON.parse, u = (c, f, V) => {
78
- const b = f.getItem(c);
79
- b === null ? d(V) && f.setItem(c, g(V)) : S.set(c, i(b));
80
- }, y = T(!1);
81
- let a;
82
- y.current || (y.current = !0, a = S.get(o), d(a) || (a = n, d(a) && S.set(o, a)), !m && e && u(o, e, a)), L(() => {
83
- !m || !e || u(o, e, a);
100
+ function U(t) {
101
+ t ??= {};
102
+ const e = w ? void 0 : g(t.storage), n = g(t.defaultValue), o = this[O], s = this[P], f = this[_];
103
+ let a = k({ verbose: s });
104
+ if (!(a instanceof z)) {
105
+ if (f)
106
+ throw new Error(N);
107
+ a = L;
108
+ }
109
+ const c = t.serialize ?? JSON.stringify, r = t.deserialize ?? JSON.parse, u = V(!1);
110
+ let l;
111
+ u.current || (u.current = !0, l = a.get(o), d(l) || (l = n, d(l) && a.set(o, l)), !f && e && E({
112
+ vocabStore: a,
113
+ storage: e,
114
+ statePath: o,
115
+ value: l,
116
+ serialize: c,
117
+ deserialize: r
118
+ })), J(() => {
119
+ !f || !e || E({
120
+ vocabStore: a,
121
+ storage: e,
122
+ statePath: o,
123
+ value: l,
124
+ serialize: c,
125
+ deserialize: r
126
+ });
84
127
  }, []);
85
128
  }
86
- function U(s) {
87
- return typeof s == "object" && s !== null && "clientSlot" in s;
129
+ function W(t) {
130
+ return typeof t == "object" && t !== null && "clientSlot" in t;
88
131
  }
89
- function W(s) {
132
+ function X(t) {
90
133
  const e = {};
91
- for (const n in s) {
92
- const o = s[n];
93
- U(o) ? (e[n] = o.clientSlot({
94
- useState(...r) {
95
- return K.apply(this, r);
134
+ for (const n in t) {
135
+ const o = t[n];
136
+ W(o) ? (e[n] = o.clientSlot({
137
+ useState(...s) {
138
+ return Q.apply(this, s);
96
139
  },
97
- useInitialState(...r) {
98
- Q.apply(this, r);
140
+ useInitialState(...s) {
141
+ U.apply(this, s);
99
142
  }
100
- }), delete e[n].serverSlot, delete e[n].clientSlot) : o !== null && typeof o == "object" ? e[n] = W(o) : e[n] = o;
143
+ }), delete e[n].serverSlot, delete e[n].clientSlot) : o !== null && typeof o == "object" ? e[n] = X(o) : e[n] = o;
101
144
  }
102
145
  return e;
103
146
  }
104
147
  export {
105
- te as StateVocabProvider,
106
- W as clientify
148
+ X as clientify
107
149
  };
@@ -0,0 +1,8 @@
1
+ const s = /* @__PURE__ */ Symbol("state-def"), t = /* @__PURE__ */ Symbol("state-path"), S = /* @__PURE__ */ Symbol("state-verbose"), a = /* @__PURE__ */ Symbol("state-verbose-path"), o = /* @__PURE__ */ Symbol("state-ssr");
2
+ export {
3
+ t as S,
4
+ S as a,
5
+ o as b,
6
+ a as c,
7
+ s as d
8
+ };
@@ -0,0 +1 @@
1
+ "use strict";const T=Symbol("state-def"),S=Symbol("state-path"),E=Symbol("state-verbose"),t=Symbol("state-verbose-path"),s=Symbol("state-ssr");exports.STATE_DEFINITION=T;exports.STATE_PATH=S;exports.STATE_SSR=s;exports.STATE_VERBOSE=E;exports.STATE_VERBOSE_PATH=t;
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./utils-33NqsZoR.js");function V(t={}){return{[a.STATE_DEFINITION]:!0,[a.STATE_PATH]:"",[a.STATE_VERBOSE]:!1,[a.STATE_VERBOSE_PATH]:"",[a.STATE_SSR]:!1,serverSlot(r){return Object.assign(this,{getState(...e){return r.getState.apply(this,e)}})},clientSlot(r){return Object.assign(this,{useState(e){return e??={},r.useState.apply(this,[{defaultValue:a.valueOrFactory(e.defaultValue)??a.valueOrFactory(t.defaultValue),bidirectional:e.bidirectional??t.bidirectional,storage:e.storage??t.storage,serialize:t.serialize??JSON.stringify,deserialize:t.deserialize??JSON.parse,delayedSet:e.delayedSet,onSet(...u){e.onSet&&e.onSet(...u)}}])},useInitialState(e){r.useInitialState.apply(this,[{defaultValue:e.defaultValue,storage:t.storage,serialize:t.serialize,deserialize:t.deserialize}])}})},toString(){return this[a.STATE_PATH]}}}function h(t,r){const{path:e="",verbose:u,verbosePath:y,ssr:A,cache:S}=r;let s=S.proxy.get(t);s||(s=new Map,S.proxy.set(t,s));const d=s.get(e);if(d)return d;const o=new Proxy(t,{get(b,T){const l=b[T],c=e?`${e}.${String(T)}`:String(T);if(l&&typeof l=="object"&&a.STATE_DEFINITION in l){const i=l;let n=S.leaf.get(i);n||(n=new Map,S.leaf.set(i,n));const g=n.get(c);if(g)return g;const P=Reflect.ownKeys(i).filter(f=>typeof i[f]=="function"),_=Object.fromEntries(P.map(f=>[f,(...v)=>i[f].call({...i,[a.STATE_PATH]:c,[a.STATE_VERBOSE]:u,[a.STATE_VERBOSE_PATH]:y,[a.STATE_SSR]:A},...v)])),E={...i,..._};return n.set(c,E),E}return l&&typeof l=="object"?h(l,{...r,path:c}):l}});return s.set(e,o),o}function z(t,r){return h(t,{...r,ssr:r?.ssr??!0,verbosePath:r?.verbosePath??"",cache:{proxy:new WeakMap,leaf:new WeakMap}})}exports.defineState=V;exports.setupStorage=z;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./constants-CbsduCZ7.js"),h=require("./utils-0CTNJ4ZE.js");function z(t={}){return{[r.STATE_DEFINITION]:!0,[r.STATE_PATH]:"",[r.STATE_VERBOSE]:!1,[r.STATE_VERBOSE_PATH]:"",[r.STATE_SSR]:!1,serverSlot(a){return Object.assign(this,{getState(...e){return a.getState.apply(this,e)}})},clientSlot(a){return Object.assign(this,{useState(e){return e??={},a.useState.apply(this,[{defaultValue:h.valueOrFactory(e.defaultValue)??h.valueOrFactory(t.defaultValue),bidirectional:e.bidirectional??t.bidirectional,storage:e.storage??t.storage,serialize:t.serialize??JSON.stringify,deserialize:t.deserialize??JSON.parse,delayedSet:e.delayedSet,onSet(...f){e.onSet&&e.onSet(...f)}}])},useInitialState(e){a.useInitialState.apply(this,[{defaultValue:e.defaultValue,storage:t.storage,serialize:t.serialize,deserialize:t.deserialize}])}})},toString(){return this[r.STATE_PATH]}}}function y(t,a){const{path:e="",verbose:f,verbosePath:A,ssr:b,cache:c}=a;let s=c.proxy.get(t);s||(s=new Map,c.proxy.set(t,s));const o=s.get(e);if(o)return o;const d=new Proxy(t,{get(P,T){const l=P[T],S=e?`${e}.${String(T)}`:String(T);if(l&&typeof l=="object"&&r.STATE_DEFINITION in l){const i=l;let n=c.leaf.get(i);n||(n=new Map,c.leaf.set(i,n));const g=n.get(S);if(g)return g;const _=Reflect.ownKeys(i).filter(u=>typeof i[u]=="function"),v=Object.fromEntries(_.map(u=>[u,(...V)=>i[u].call({...i,[r.STATE_PATH]:S,[r.STATE_VERBOSE]:f,[r.STATE_VERBOSE_PATH]:A,[r.STATE_SSR]:b},...V)])),E={...i,...v};return n.set(S,E),E}return l&&typeof l=="object"?y(l,{...a,path:S}):l}});return s.set(e,d),d}function I(t,a){return y(t,{...a,ssr:a?.ssr??!0,verbosePath:a?.verbosePath??"",cache:{proxy:new WeakMap,leaf:new WeakMap}})}exports.defineState=z;exports.setupStorage=I;
package/dist/index.es.js CHANGED
@@ -1,5 +1,6 @@
1
- import { S as d, v as b, b as T, c as E, a as P, f as v } from "./utils-t8tYdd6B.mjs";
2
- function m(t = {}) {
1
+ import { S as d, b as T, c as E, a as P, d as v } from "./constants-BB1YAX6c.mjs";
2
+ import { v as b } from "./utils-xV3x3fTc.mjs";
3
+ function M(t = {}) {
3
4
  return {
4
5
  [v]: !0,
5
6
  // marks this object as a leaf in the router tree
@@ -62,10 +63,10 @@ function z(t, a) {
62
63
  } = a;
63
64
  let s = n.proxy.get(t);
64
65
  s || (s = /* @__PURE__ */ new Map(), n.proxy.set(t, s));
65
- const h = s.get(e);
66
- if (h)
67
- return h;
68
- const o = new Proxy(t, {
66
+ const o = s.get(e);
67
+ if (o)
68
+ return o;
69
+ const h = new Proxy(t, {
69
70
  get(V, u) {
70
71
  const r = V[u], c = e ? `${e}.${String(u)}` : String(u);
71
72
  if (r && typeof r == "object" && v in r) {
@@ -77,10 +78,10 @@ function z(t, a) {
77
78
  return g;
78
79
  const j = Reflect.ownKeys(l).filter(
79
80
  (f) => typeof l[f] == "function"
80
- ), w = Object.fromEntries(
81
+ ), m = Object.fromEntries(
81
82
  j.map((f) => [
82
83
  f,
83
- (..._) => l[f].call(
84
+ (...w) => l[f].call(
84
85
  {
85
86
  ...l,
86
87
  [d]: c,
@@ -88,10 +89,10 @@ function z(t, a) {
88
89
  [E]: x,
89
90
  [T]: A
90
91
  },
91
- ..._
92
+ ...w
92
93
  )
93
94
  ])
94
- ), y = { ...l, ...w };
95
+ ), y = { ...l, ...m };
95
96
  return i.set(c, y), y;
96
97
  }
97
98
  return r && typeof r == "object" ? z(r, {
@@ -100,9 +101,9 @@ function z(t, a) {
100
101
  }) : r;
101
102
  }
102
103
  });
103
- return s.set(e, o), o;
104
+ return s.set(e, h), h;
104
105
  }
105
- function M(t, a) {
106
+ function N(t, a) {
106
107
  return z(t, {
107
108
  ...a,
108
109
  ssr: a?.ssr ?? !0,
@@ -114,6 +115,6 @@ function M(t, a) {
114
115
  });
115
116
  }
116
117
  export {
117
- m as defineState,
118
- M as setupStorage
118
+ M as defineState,
119
+ N as setupStorage
119
120
  };
@@ -0,0 +1 @@
1
+ "use client";"use strict";const h=require("react/jsx-runtime"),r=require("react"),s=require("./utils-0CTNJ4ZE.js"),c=r.createContext({});function S(o){const t=r.useContext(c);return o.verbose&&console.log(`[Store uid]: ${t.uid}`),t}class u{#t;#e;constructor(t){this.uid=Math.random().toString(36).slice(2),this.#t=t??{},this.#e=new Set}subscribe(t){return this.#e.add(t),()=>this.#e.delete(t)}getClientSnapshot(){return this.#t}getServerSnapshot(){return this.#t}get(t){return s.get(this.#t,t)}set(t,e){const n=s.get(this.#t,t),a=s.isTransformer(e)?e(n):e,i={...this.#t};s.set(i,t,a),this.#t=i,this.#e.forEach(l=>l())}}function b(o){const{children:t,value:e}=o,[n]=r.useState(()=>new u(e));return h.jsx(c.Provider,{value:n,children:t})}exports.StateVocabClientProvider=b;exports.VocabStore=u;exports.useStateVocabClientContext=S;
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsx as u } from "react/jsx-runtime";
3
3
  import { createContext as h, useContext as l, useState as S } from "react";
4
- import { g as n, e as d, s as b } from "./utils-t8tYdd6B.mjs";
4
+ import { g as n, i as d, s as b } from "./utils-xV3x3fTc.mjs";
5
5
  const i = h({});
6
- function V(s = {}) {
6
+ function V(s) {
7
7
  const t = l(i);
8
8
  return s.verbose && console.log(`[Store uid]: ${t.uid}`), t;
9
9
  }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),v=require("react"),b=require("node:async_hooks"),y=require("./provider.client--OPImdtY.js"),u=require("./utils-33NqsZoR.js");function g(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const P=g(b),l=e=>{if(v.useState)throw new Error(`${e} only intended for Server Components`)};let i=null;try{l("StateVocabServerContext"),i=new P.AsyncLocalStorage}catch{i=null}const h=({value:e})=>(i?.enterWith({value:e}),null),j=({children:e})=>e,x=async e=>{l("StateVocabServerContext.Provider");const{value:t,children:r}=e;return c.jsxs(c.Fragment,{children:[c.jsx(h,{value:t}),r]})},V=()=>(l("getStateVocab"),i?.getStore()?.value),m={Provider:i?x:j},p=({value:e,children:t})=>c.jsx(m.Provider,{value:e,children:t});function w(e){const{children:t,value:r={}}=e;return c.jsx(p,{value:r,children:c.jsx(y.StateVocabClientProvider,{value:r,children:t})})}function O(){const e=this[u.STATE_PATH],t=V();if(!t)throw new Error("Make sure your component is wrapped in StateVocabProvider");return u.get(t,e)}function f(e,t){return new Proxy(e,{get(r,n,o){return n in t?Reflect.get(t,n,o):Reflect.get(r,n,o)},has(r,n){return n in t||n in r}})}function k(e){return typeof e=="object"&&e!==null&&"serverSlot"in e}function S(e,t){const r={};for(const n in e){const o=e[n];if(k(o))r[n]=o.serverSlot({getState(...s){return O.apply(this,s)}}),delete r[n].serverSlot,delete r[n].clientSlot;else if(o!==null&&typeof o=="object"){const s=a=>t({[n]:a}),d=S(o,s);r[n]=f(a=>s(a),d)}else r[n]=o}return f(n=>t(n),r)}function C(e){return S(e,t=>t)}exports.StateVocabProvider=w;exports.serverify=C;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),S=require("./constants-CbsduCZ7.js"),d=require("react"),v=require("node:async_hooks"),f=require("./provider-client-B4XQ24JB.js"),b=require("./utils-0CTNJ4ZE.js");function y(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const p=y(v),a=e=>{if(d.useState)throw new Error(`${e} only intended for Server Components`)};let s=null;try{a("StateVocabServerContext"),s=new p.AsyncLocalStorage}catch{s=null}const g=({value:e})=>(s?.enterWith({value:e}),null),P=({children:e})=>e,j=async e=>{a("StateVocabServerContext.Provider");const{value:t,children:r}=e;return o.jsxs(o.Fragment,{children:[o.jsx(g,{value:t}),r]})},h=()=>(a("getStateVocab"),s?.getStore()?.value),x={Provider:s?j:P},V=({value:e,children:t})=>o.jsx(x.Provider,{value:e,children:t});function m(e){const{children:t,value:r={}}=e;return o.jsx(V,{value:r,children:o.jsx(f.StateVocabClientProvider,{value:r,children:t})})}const O="Make sure your component is wrapped in StateVocabProvider";function C(){const e=this[S.STATE_PATH],t=h();if(!t)throw new Error(O);return b.get(t,e)}function E(e){return typeof e=="object"&&e!==null&&"serverSlot"in e}function l(e,t){const r={};for(const n in e){const c=e[n];if(E(c))r[n]=c.serverSlot({getState(...i){return C.apply(this,i)}}),delete r[n].serverSlot,delete r[n].clientSlot;else if(c!==null&&typeof c=="object"){const i=u=>t({[n]:u});r[n]=l(c,i)}else r[n]=c}return r.seed=n=>t(n),r}function k(e){return{...l(e,t=>t),StateVocabProvider({children:t,value:r}){return o.jsx(m,{value:r,children:t})}}}exports.serverify=k;
package/dist/server.es.js CHANGED
@@ -1,77 +1,70 @@
1
- import { jsxs as v, Fragment as d, jsx as a } from "react/jsx-runtime";
2
- import h from "react";
3
- import * as y from "node:async_hooks";
4
- import { S as b } from "./provider.client-CtAC9tPr.mjs";
5
- import { S as g, g as m } from "./utils-t8tYdd6B.mjs";
6
- const l = (e) => {
7
- if (h.useState)
1
+ import { jsxs as u, Fragment as v, jsx as c } from "react/jsx-runtime";
2
+ import { S as d } from "./constants-BB1YAX6c.mjs";
3
+ import f from "react";
4
+ import * as p from "node:async_hooks";
5
+ import { S as m } from "./provider-client-C2Aw0Lmi.mjs";
6
+ import { g as b } from "./utils-xV3x3fTc.mjs";
7
+ const i = (e) => {
8
+ if (f.useState)
8
9
  throw new Error(`${e} only intended for Server Components`);
9
10
  };
10
- let c = null;
11
+ let s = null;
11
12
  try {
12
- l("StateVocabServerContext"), c = new y.AsyncLocalStorage();
13
+ i("StateVocabServerContext"), s = new p.AsyncLocalStorage();
13
14
  } catch {
14
- c = null;
15
+ s = null;
15
16
  }
16
- const P = ({ value: e }) => (c?.enterWith({ value: e }), null), V = ({ children: e }) => e, x = async (e) => {
17
- l("StateVocabServerContext.Provider");
18
- const { value: t, children: n } = e;
19
- return /* @__PURE__ */ v(d, { children: [
20
- /* @__PURE__ */ a(P, { value: t }),
21
- n
17
+ const h = ({ value: e }) => (s?.enterWith({ value: e }), null), y = ({ children: e }) => e, P = async (e) => {
18
+ i("StateVocabServerContext.Provider");
19
+ const { value: t, children: r } = e;
20
+ return /* @__PURE__ */ u(v, { children: [
21
+ /* @__PURE__ */ c(h, { value: t }),
22
+ r
22
23
  ] });
23
- }, w = () => (l("getStateVocab"), c?.getStore()?.value), C = {
24
- Provider: c ? x : V
25
- }, p = ({ value: e, children: t }) => /* @__PURE__ */ a(C.Provider, { value: e, children: t });
26
- function H(e) {
27
- const { children: t, value: n = {} } = e;
28
- return /* @__PURE__ */ a(p, { value: n, children: /* @__PURE__ */ a(b, { value: n, children: t }) });
24
+ }, g = () => (i("getStateVocab"), s?.getStore()?.value), V = {
25
+ Provider: s ? P : y
26
+ }, E = ({ value: e, children: t }) => /* @__PURE__ */ c(V.Provider, { value: e, children: t });
27
+ function x(e) {
28
+ const { children: t, value: r = {} } = e;
29
+ return /* @__PURE__ */ c(E, { value: r, children: /* @__PURE__ */ c(m, { value: r, children: t }) });
29
30
  }
30
- function j() {
31
- const e = this[g], t = w();
31
+ const C = "Make sure your component is wrapped in StateVocabProvider";
32
+ function w() {
33
+ const e = this[d], t = g();
32
34
  if (!t)
33
- throw new Error("Make sure your component is wrapped in StateVocabProvider");
34
- return m(t, e);
35
+ throw new Error(C);
36
+ return b(t, e);
35
37
  }
36
- function u(e, t) {
37
- return new Proxy(e, {
38
- get(n, r, o) {
39
- return r in t ? Reflect.get(t, r, o) : Reflect.get(n, r, o);
40
- },
41
- has(n, r) {
42
- return r in t || r in n;
43
- }
44
- });
45
- }
46
- function k(e) {
38
+ function R(e) {
47
39
  return typeof e == "object" && e !== null && "serverSlot" in e;
48
40
  }
49
- function S(e, t) {
50
- const n = {};
51
- for (const r in e) {
52
- const o = e[r];
53
- if (k(o))
54
- n[r] = o.serverSlot({
41
+ function l(e, t) {
42
+ const r = {};
43
+ for (const o in e) {
44
+ const n = e[o];
45
+ if (R(n))
46
+ r[o] = n.serverSlot({
55
47
  // Slot definition
56
- getState(...i) {
57
- return j.apply(this, i);
48
+ getState(...a) {
49
+ return w.apply(this, a);
58
50
  }
59
- }), delete n[r].serverSlot, delete n[r].clientSlot;
60
- else if (o !== null && typeof o == "object") {
61
- const i = (s) => t({ [r]: s }), f = S(o, i);
62
- n[r] = u(
63
- (s) => i(s),
64
- f
65
- );
51
+ }), delete r[o].serverSlot, delete r[o].clientSlot;
52
+ else if (n !== null && typeof n == "object") {
53
+ const a = (S) => t({ [o]: S });
54
+ r[o] = l(n, a);
66
55
  } else
67
- n[r] = o;
56
+ r[o] = n;
68
57
  }
69
- return u((r) => t(r), n);
58
+ return r.seed = (o) => t(o), r;
70
59
  }
71
- function W(e) {
72
- return S(e, (t) => t);
60
+ function M(e) {
61
+ return {
62
+ ...l(e, (t) => t),
63
+ StateVocabProvider({ children: t, value: r }) {
64
+ return /* @__PURE__ */ c(x, { value: r, children: t });
65
+ }
66
+ };
73
67
  }
74
68
  export {
75
- H as StateVocabProvider,
76
- W as serverify
69
+ M as serverify
77
70
  };
@@ -1,2 +1 @@
1
1
  export { clientify } from "./setup.client";
2
- export { StateVocabClientProvider as StateVocabProvider } from "./provider.client";
@@ -3,6 +3,6 @@ export declare const StateVocabClientContext: import("react").Context<VocabStore
3
3
  /**
4
4
  * @see method from from https://zustand.docs.pmnd.rs/learn/guides/nextjs
5
5
  */
6
- export declare function useStateVocabClientContext(options?: {
7
- verbose?: boolean;
6
+ export declare function useStateVocabClientContext(options: {
7
+ verbose: boolean;
8
8
  }): VocabStore;
@@ -1,2 +1 @@
1
- export { StateVocabProvider } from "./provider";
2
1
  export { serverify } from "./setup.server";
@@ -0,0 +1,12 @@
1
+ import { type DependencyList } from "react";
2
+ import VocabStore from "./store";
3
+ import type { Deserialize, Serialize } from "./state.types";
4
+ export declare function useDebounce<T extends (...args: never[]) => unknown>(effect: T, wait: number | undefined, deps?: DependencyList): (...args: Parameters<T>) => void;
5
+ export declare const sync: <V>(options: {
6
+ vocabStore: VocabStore;
7
+ statePath: string;
8
+ storage: Storage;
9
+ serialize: Serialize<V>;
10
+ deserialize: Deserialize<V>;
11
+ value: V | undefined;
12
+ }) => void;
@@ -1,3 +1,4 @@
1
+ import type { PropsWithChildren, ReactNode } from "react";
1
2
  import type { Vocab } from "./state.types";
2
3
  type Placeholder<V> = {
3
4
  getState(): V;
@@ -8,10 +9,17 @@ type Slot<V> = {
8
9
  type ServerifiedValue<R> = {
9
10
  [K in keyof R]?: R[K] extends Slot<infer V> ? V : R[K] extends object ? ServerifiedValue<R[K]> : R[K];
10
11
  };
11
- type Serverified<R> = R extends Slot<infer TValue> ? Placeholder<TValue> : R extends object ? ((input: ServerifiedValue<R>) => Vocab) & {
12
+ type Serverified<R> = R extends Slot<infer TValue> ? Placeholder<TValue> : R extends object ? {
13
+ seed(input: ServerifiedValue<R>): Vocab;
14
+ } & {
12
15
  [K in keyof R]: Serverified<R[K]>;
13
16
  } : R;
14
- type ServerifyResult<R extends object> = ((input: ServerifiedValue<R>) => Vocab) & {
17
+ type ServerifyResult<R extends object> = {
18
+ seed(input: ServerifiedValue<R>): Vocab;
19
+ StateVocabProvider(props: PropsWithChildren<{
20
+ value?: ServerifiedValue<R>;
21
+ }>): Promise<ReactNode>;
22
+ } & {
15
23
  [K in keyof R]: Serverified<R[K]>;
16
24
  };
17
25
  export declare function serverify<R extends object>(tree: R): ServerifyResult<R>;
@@ -0,0 +1,3 @@
1
+ "use strict";function f(e,s,n){if(!s)return e;const o=s.split(".");let t=e;for(const c of o)if(t!==null&&typeof t=="object"&&c in t)t=t[c];else return n;return t===void 0?n:t}function y(e,s,n){const o=s.replace(/\[(\d+)\]/g,".$1").split(".");let t=e;for(let c=0;c<o.length-1;c++){const r=o[c],i=o[c+1];(t[r]===void 0||t[r]===null)&&(t[r]=/^\d+$/.test(i)?[]:{}),t=t[r]}return t[o[o.length-1]]=n,e}function d(e,s=0){let n;return function(...o){n!==void 0&&clearTimeout(n),n=setTimeout(()=>{n=void 0,e.apply(this,o)},s)}}function a(e){const s=JSON.stringify(e,null,2).split(`
2
+ `),n=[],o=[];for(const t of s){const c=t.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,r,i,l,u]=c;n.push(`${r}%c"${i}"%c${l}%c${u}`),o.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else n.push(`%c${t}`),o.push("color: #cccccc")}console.log(n.join(`
3
+ `),...o,e)}const p=e=>typeof e=="function",g=e=>typeof e=="function",h=e=>typeof e<"u",$=e=>g(e)?e():e;exports.debounce=d;exports.get=f;exports.isTransformer=p;exports.isValueDefined=h;exports.logStyled=a;exports.set=y;exports.valueOrFactory=$;
@@ -0,0 +1,57 @@
1
+ function a(t, s, n) {
2
+ if (!s)
3
+ return t;
4
+ const o = s.split(".");
5
+ let e = t;
6
+ for (const c of o)
7
+ if (e !== null && typeof e == "object" && c in e)
8
+ e = e[c];
9
+ else
10
+ return n;
11
+ return e === void 0 ? n : e;
12
+ }
13
+ function y(t, s, n) {
14
+ const o = s.replace(/\[(\d+)\]/g, ".$1").split(".");
15
+ let e = t;
16
+ for (let c = 0; c < o.length - 1; c++) {
17
+ const r = o[c], i = o[c + 1];
18
+ (e[r] === void 0 || e[r] === null) && (e[r] = /^\d+$/.test(i) ? [] : {}), e = e[r];
19
+ }
20
+ return e[o[o.length - 1]] = n, t;
21
+ }
22
+ function d(t, s = 0) {
23
+ let n;
24
+ return function(...o) {
25
+ n !== void 0 && clearTimeout(n), n = setTimeout(() => {
26
+ n = void 0, t.apply(this, o);
27
+ }, s);
28
+ };
29
+ }
30
+ function p(t) {
31
+ const s = JSON.stringify(t, null, 2).split(`
32
+ `), n = [], o = [];
33
+ for (const e of s) {
34
+ const c = e.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
35
+ if (c) {
36
+ const [, r, i, l, u] = c;
37
+ n.push(`${r}%c"${i}"%c${l}%c${u}`), o.push(
38
+ "color: #9cdcfe; font-weight: bold",
39
+ "color: #cccccc",
40
+ "color: #ce9178"
41
+ );
42
+ } else
43
+ n.push(`%c${e}`), o.push("color: #cccccc");
44
+ }
45
+ console.log(n.join(`
46
+ `), ...o, t);
47
+ }
48
+ const g = (t) => typeof t == "function", f = (t) => typeof t == "function", h = (t) => typeof t < "u", $ = (t) => f(t) ? t() : t;
49
+ export {
50
+ h as a,
51
+ d,
52
+ a as g,
53
+ g as i,
54
+ p as l,
55
+ y as s,
56
+ $ as v
57
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yakocloud/state-vocab",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.es.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -1 +0,0 @@
1
- "use client";"use strict";const h=require("react/jsx-runtime"),r=require("react"),s=require("./utils-33NqsZoR.js"),c=r.createContext({});function S(o={}){const t=r.useContext(c);return o.verbose&&console.log(`[Store uid]: ${t.uid}`),t}class u{#t;#e;constructor(t){this.uid=Math.random().toString(36).slice(2),this.#t=t??{},this.#e=new Set}subscribe(t){return this.#e.add(t),()=>this.#e.delete(t)}getClientSnapshot(){return this.#t}getServerSnapshot(){return this.#t}get(t){return s.get(this.#t,t)}set(t,e){const n=s.get(this.#t,t),a=s.isTransformer(e)?e(n):e,i={...this.#t};s.set(i,t,a),this.#t=i,this.#e.forEach(l=>l())}}function b(o){const{children:t,value:e}=o,[n]=r.useState(()=>new u(e));return h.jsx(c.Provider,{value:n,children:t})}exports.StateVocabClientProvider=b;exports.VocabStore=u;exports.useStateVocabClientContext=S;
@@ -1,2 +0,0 @@
1
- import { type DependencyList } from "react";
2
- export declare function useDebounce<T extends (...args: never[]) => unknown>(effect: T, wait: number | undefined, deps?: DependencyList): (...args: Parameters<T>) => void;
@@ -1,3 +0,0 @@
1
- "use strict";const T=Symbol("state-def"),f=Symbol("state-path"),S=Symbol("state-verbose"),y=Symbol("state-verbose-path"),a=Symbol("state-ssr");function E(t,s,o){if(!s)return t;const n=s.split(".");let e=t;for(const c of n)if(e!==null&&typeof e=="object"&&c in e)e=e[c];else return o;return e===void 0?o:e}function d(t,s,o){const n=s.replace(/\[(\d+)\]/g,".$1").split(".");let e=t;for(let c=0;c<n.length-1;c++){const r=n[c],l=n[c+1];(e[r]===void 0||e[r]===null)&&(e[r]=/^\d+$/.test(l)?[]:{}),e=e[r]}return e[n[n.length-1]]=o,t}function p(t,s=0){let o;return function(...n){o!==void 0&&clearTimeout(o),o=setTimeout(()=>{o=void 0,t.apply(this,n)},s)}}function A(t){const s=JSON.stringify(t,null,2).split(`
2
- `),o=[],n=[];for(const e of s){const c=e.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,r,l,i,u]=c;o.push(`${r}%c"${l}"%c${i}%c${u}`),n.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else o.push(`%c${e}`),n.push("color: #cccccc")}console.log(o.join(`
3
- `),...n,t)}const m=t=>typeof t=="function",_=t=>typeof t=="function",h=t=>typeof t<"u",g=t=>_(t)?t():t;exports.STATE_DEFINITION=T;exports.STATE_PATH=f;exports.STATE_SSR=a;exports.STATE_VERBOSE=S;exports.STATE_VERBOSE_PATH=y;exports.debounce=p;exports.get=E;exports.isTransformer=m;exports.isValueDefined=h;exports.logStyled=A;exports.set=d;exports.valueOrFactory=g;
@@ -1,63 +0,0 @@
1
- const u = /* @__PURE__ */ Symbol("state-def"), y = /* @__PURE__ */ Symbol("state-path"), S = /* @__PURE__ */ Symbol("state-verbose"), d = /* @__PURE__ */ Symbol("state-verbose-path"), T = /* @__PURE__ */ Symbol("state-ssr");
2
- function p(t, c, s) {
3
- if (!c)
4
- return t;
5
- const o = c.split(".");
6
- let e = t;
7
- for (const n of o)
8
- if (e !== null && typeof e == "object" && n in e)
9
- e = e[n];
10
- else
11
- return s;
12
- return e === void 0 ? s : e;
13
- }
14
- function h(t, c, s) {
15
- const o = c.replace(/\[(\d+)\]/g, ".$1").split(".");
16
- let e = t;
17
- for (let n = 0; n < o.length - 1; n++) {
18
- const r = o[n], l = o[n + 1];
19
- (e[r] === void 0 || e[r] === null) && (e[r] = /^\d+$/.test(l) ? [] : {}), e = e[r];
20
- }
21
- return e[o[o.length - 1]] = s, t;
22
- }
23
- function m(t, c = 0) {
24
- let s;
25
- return function(...o) {
26
- s !== void 0 && clearTimeout(s), s = setTimeout(() => {
27
- s = void 0, t.apply(this, o);
28
- }, c);
29
- };
30
- }
31
- function E(t) {
32
- const c = JSON.stringify(t, null, 2).split(`
33
- `), s = [], o = [];
34
- for (const e of c) {
35
- const n = e.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
36
- if (n) {
37
- const [, r, l, i, a] = n;
38
- s.push(`${r}%c"${l}"%c${i}%c${a}`), o.push(
39
- "color: #9cdcfe; font-weight: bold",
40
- "color: #cccccc",
41
- "color: #ce9178"
42
- );
43
- } else
44
- s.push(`%c${e}`), o.push("color: #cccccc");
45
- }
46
- console.log(s.join(`
47
- `), ...o, t);
48
- }
49
- const g = (t) => typeof t == "function", f = (t) => typeof t == "function", v = (t) => typeof t < "u", b = (t) => f(t) ? t() : t;
50
- export {
51
- y as S,
52
- S as a,
53
- T as b,
54
- d as c,
55
- m as d,
56
- g as e,
57
- u as f,
58
- p as g,
59
- v as i,
60
- E as l,
61
- h as s,
62
- b as v
63
- };