@yakocloud/state-vocab 2.3.6 → 2.5.1

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
@@ -1,37 +1,38 @@
1
1
  # @yakocloud/state-vocab
2
2
 
3
- A lightweight React state management library that synchronizes component state with any `Storage`-compatible (localStorage, sessionStorage, custom).
3
+ A lightweight React state management library that synchronizes component state with any `Storage`-compatible backend (localStorage, sessionStorage, custom).
4
4
 
5
5
  ## Why use state-vocab?
6
-
6
+
7
7
  Most state managers treat persistence as an afterthought — you manage state first, then manually sync it to localStorage. **state-vocab flips this**: storage is defined upfront alongside the state itself, and synchronization is automatic.
8
-
8
+
9
9
  **Storage-first by design.** Every state node declares its backend at definition time — localStorage, sessionStorage, or any custom adapter. No `useEffect(() => localStorage.setItem(...), [value])` scattered across components.
10
-
10
+
11
11
  ```ts
12
- // declare once — works everywhere
13
12
  const storage = setupStorage({
14
13
  theme: defineState({ storage: localStorage, defaultValue: 'Dark' }),
15
14
  session: defineState({ storage: () => sessionStorage }),
16
15
  inMemory: defineState({ defaultValue: 0 }),
17
16
  })
18
17
  ```
19
-
18
+
20
19
  **Bring your own backend.** The `storage` option accepts any object implementing the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage). Point state directly at a server, IndexedDB wrapper, or encrypted store — no extra adapters needed.
21
-
20
+
22
21
  ```ts
23
22
  defineState({
24
23
  storage: {
25
24
  getItem: (key) => api.get(key),
26
25
  setItem: (key, value) => api.set(key, value),
27
26
  removeItem: (key) => api.delete(key),
28
- // ...
27
+ length: 0,
28
+ clear: () => {},
29
+ key: () => null,
29
30
  }
30
31
  })
31
32
  ```
32
-
33
- **No prop drilling.** State lives in a shared `storage` object imported directly into any component. No need to pass values down through layers of props or lift state up to a common ancestor — any component in the tree can read and write the same node independently.
34
-
33
+
34
+ **No prop drilling.** State lives in a shared `storage` object imported directly into any component. No need to pass values down through layers of props or lift state up to a common ancestor.
35
+
35
36
  ```tsx
36
37
  // ❌ without state-vocab — thread props through every layer
37
38
  function Page({ theme, onThemeChange }) {
@@ -43,35 +44,67 @@ function Sidebar({ theme, onThemeChange }) {
43
44
  function ThemeToggle({ theme, onThemeChange }) {
44
45
  return <button onClick={() => onThemeChange('Dark')}>{theme}</button>
45
46
  }
46
-
47
+
47
48
  // ✅ with state-vocab — import storage, use directly
48
49
  function ThemeToggle() {
49
50
  const [theme, setTheme] = storage.preference.theme.useState()
50
51
  return <button onClick={() => setTheme('Dark')}>{theme}</button>
51
52
  }
52
53
  ```
53
-
54
+
55
+ **Initialize once at the root, read anywhere in the tree.** Call `.useState()` with a `defaultValue` at a parent component to seed the state — then call `.useState()` without arguments in any descendant to consume it. No context wiring, no prop passing. Convenient in NextJs
56
+
57
+ ```tsx
58
+ // Root component — initializes the state
59
+ function Page() {
60
+ storage.demo.pageProps.useState({
61
+ defaultValue: {
62
+ a: 1,
63
+ b: 2,
64
+ c: ['one', 'two'],
65
+ },
66
+ })
67
+
68
+ return <DeepChild />
69
+ }
70
+
71
+ // Somewhere deep in the tree — reads the same state
72
+ function DeepChild() {
73
+ const [pageProps] = storage.demo.pageProps.useState()
74
+
75
+ return (
76
+ <div>
77
+ <p>a: {pageProps.a}</p>
78
+ <p>b: {pageProps.b}</p>
79
+ <p>c: {pageProps.c.join(', ')}</p>
80
+ </div>
81
+ )
82
+ }
83
+ ```
84
+
85
+ The `defaultValue` at the root acts as the initializer — subsequent `.useState()` calls in children pick up the shared value automatically without re-specifying defaults.
86
+
54
87
  **Dot-notation access with full TypeScript inference.** The state tree is navigated like a plain object — autocomplete guides you to the right node, and types flow from `defineState<T>` all the way to the hook return value without any manual annotations.
55
-
88
+
56
89
  ```ts
57
90
  const [theme, setTheme] = storage.preference.theme.useState()
58
91
  // ^? 'Dark' | 'White' | 'System'
59
-
92
+
60
93
  const [birthday, setBirthday] = storage.personal.birthday.useState()
61
94
  // ^? Date | null
62
95
  ```
63
-
96
+
64
97
  If you rename or restructure a node in `setupStorage`, TypeScript immediately flags every broken reference across the codebase.
65
-
98
+
66
99
  **Custom serialization per node.** Dates, Maps, class instances — define `serialize`/`deserialize` once and the hook handles the rest transparently.
67
-
100
+
68
101
  ```ts
69
102
  defineState({
70
103
  storage: localStorage,
71
104
  deserialize: (raw) => new Date(JSON.parse(raw)),
72
105
  })
73
106
  ```
74
-
107
+
75
108
  **Minimal API surface.** Three exports: `defineState`, `setupStorage`, `StorageProvider`. No actions, reducers, selectors, or stores to configure.
76
109
 
77
110
  ## Installation
@@ -85,15 +118,17 @@ npm install @yakocloud/state-vocab react react-dom
85
118
  ## Quick Start
86
119
 
87
120
  ```tsx
88
- import { setupStorage, defineState, StorageProvider } from 'state-vocab'
121
+ import { setupStorage, defineState, StorageProvider } from '@yakocloud/state-vocab'
122
+
123
+ type Theme = 'Dark' | 'White' | 'System'
89
124
 
90
125
  const storage = setupStorage({
91
126
  path: {
92
127
  to: {
93
- theme: defineState<'Dark' | 'White' | 'System'>({
128
+ theme: defineState<Theme>({
94
129
  storage: localStorage,
95
130
  defaultValue: 'Dark',
96
- })
131
+ }),
97
132
  },
98
133
  },
99
134
  })
@@ -110,7 +145,7 @@ function Settings() {
110
145
  const [theme, setTheme] = storage.path.to.theme.useState()
111
146
 
112
147
  return (
113
- <select value={theme} onChange={(e) => setTheme(e.target.value)}>
148
+ <select value={theme} onChange={(e) => setTheme(e.target.value as Theme)}>
114
149
  <option value="Dark">Dark</option>
115
150
  <option value="White">White</option>
116
151
  <option value="System">System</option>
@@ -128,7 +163,8 @@ Defines a state node. Options:
128
163
  | Option | Type | Description |
129
164
  |---|---|---|
130
165
  | `storage` | `Storage \| (() => Storage) \| undefined` | Where to persist the value. Omit for in-memory only. |
131
- | `defaultValue` | `T` | Value used when storage has no entry. |
166
+ | `defaultValue` | `T \| (() => T)` | Value used when storage has no entry. Accepts a factory function. |
167
+ | `bidirectional` | `true \| undefined` | Sync state across browser tabs via the `storage` event. |
132
168
  | `serialize` | `(v: T) => string` | Custom serializer. Default: `JSON.stringify`. |
133
169
  | `deserialize` | `(v: string) => T` | Custom deserializer. Default: `JSON.parse`. |
134
170
 
@@ -142,20 +178,26 @@ const theme = defineState<'Dark' | 'White'>({
142
178
  defaultValue: 'Dark',
143
179
  })
144
180
 
145
- // localStorage with custom serialization
181
+ // localStorage with custom deserialization
146
182
  const birthday = defineState({
147
183
  storage: () => localStorage,
148
184
  deserialize: (raw) => new Date(JSON.parse(raw)),
149
185
  })
186
+
187
+ // bidirectional — syncs value when changed in another tab
188
+ const note = defineState({
189
+ storage: localStorage,
190
+ bidirectional: true,
191
+ })
150
192
  ```
151
193
 
152
- ### `setupStorage(tree, options)`
194
+ ### `setupStorage(tree, options?)`
153
195
 
154
196
  Wraps a nested object of `defineState()` nodes and injects dot-separated paths into each leaf. The returned object mirrors your tree structure.
155
197
 
156
- | Parameter | Type | Description | Default
157
- |---|---|---|
158
- | `ssr` | `boolean \| undefined` | SSR support | false
198
+ | Option | Type | Description | Default |
199
+ |---|---|---|---|
200
+ | `ssr` | `boolean \| undefined` | Defer storage reads until after mount (SSR support) | `false` |
159
201
 
160
202
  ```ts
161
203
  const storage = setupStorage({
@@ -165,14 +207,13 @@ const storage = setupStorage({
165
207
  },
166
208
  })
167
209
 
168
- // Access paths:
169
210
  storage.user.name // → path: "user.name"
170
211
  storage.user.age // → path: "user.age"
171
212
  ```
172
213
 
173
214
  ### `StorageProvider`
174
215
 
175
- A React context provider that must wrap all components using `useState()` from any state node. Place it once near the top of your tree.
216
+ A React context provider that must wrap all components using `.useState()` from any state node. Place it once near the top of your tree.
176
217
 
177
218
  ```tsx
178
219
  createRoot(document.getElementById('root')!).render(
@@ -182,44 +223,55 @@ createRoot(document.getElementById('root')!).render(
182
223
  )
183
224
  ```
184
225
 
226
+ Accepts an optional `verbose` prop that logs the current state vocab to the browser console on every change — useful during development.
227
+
228
+ ```tsx
229
+ <StorageProvider verbose>
230
+ <App />
231
+ </StorageProvider>
232
+ ```
233
+
185
234
  ## `useState` Hook
186
235
 
187
236
  Each state node exposes a `.useState()` method that works like React's built-in `useState` but adds persistence and callbacks.
188
237
 
189
238
  ```ts
190
- const [value, setValue, resetValue] = storage.path.to.node.useState(
191
- defaultValue?,
192
- options?
193
- )
239
+ const [value, setValue, resetValue] = storage.path.to.node.useState(options?)
194
240
  ```
195
241
 
196
- ### Arguments
242
+ ### Options
197
243
 
198
- **`defaultValue`** — overrides the `defineState`-level default for this usage. Accepts a value or initializer function:
244
+ **`defaultValue`** — overrides the `defineState`-level default for this usage. Accepts a value or factory function:
199
245
 
200
246
  ```ts
201
- const [alarm] = storage.alarm.useState(() => new Date())
247
+ const [alarm] = storage.alarm.useState({ defaultValue: () => new Date() })
202
248
  ```
203
249
 
204
- **`options.delayedSet`** — debounce the `onSet` callback by N milliseconds:
250
+ **`delayedSet`** — debounces the `onSet` callback by N milliseconds:
205
251
 
206
252
  ```ts
207
- const [note, setNote] = storage.note.useState('', {
253
+ const [note, setNote] = storage.note.useState({
208
254
  delayedSet: 1000,
209
255
  onSet: (value) => saveToServer(value),
210
256
  })
211
257
  ```
212
258
 
213
- **`options.onSet`** — called after every state change with `(nextValue, prevValue)`:
259
+ **`onSet`** — called after every state change with `(nextValue, prevValue)`:
214
260
 
215
261
  ```ts
216
- const [counter, setCounter] = storage.counter.useState(0, {
262
+ const [counter, setCounter] = storage.counter.useState({
217
263
  onSet(next, prev) {
218
264
  console.log(`Changed from ${prev} to ${next}`)
219
265
  },
220
266
  })
221
267
  ```
222
268
 
269
+ **`bidirectional`** — enables cross-tab sync via the `storage` event. Can be set here or in `defineState`:
270
+
271
+ ```ts
272
+ const [note, setNote] = storage.note.useState({ bidirectional: true })
273
+ ```
274
+
223
275
  ### Return value
224
276
 
225
277
  ```ts
@@ -228,44 +280,49 @@ const [value, setValue, resetValue] = storage.node.useState()
228
280
 
229
281
  - **`value`** — current state
230
282
  - **`setValue(nextValue | updater)`** — set state; accepts a value or `(prev) => next` function
231
- - **`resetValue()`** — restores the default value
283
+ - **`resetValue()`** — restores the default value (removes the storage entry if no default is defined)
232
284
 
233
285
  ## Custom Storage
234
286
 
235
- Any object implementing the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage) works as a backend:
287
+ Any object implementing the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage) works as a backend. This makes it easy to add debouncing, encryption, or remote persistence:
236
288
 
237
289
  ```ts
290
+ const db: Record<string, string> = {}
291
+
238
292
  const storage = setupStorage({
239
- server: defineState({
240
- storage: {
241
- length: 0,
242
- getItem: (key) => cache[key] ?? null,
243
- setItem: (key, value) => api.save(key, value),
244
- removeItem: (key) => { delete cache[key] },
245
- clear: () => {},
246
- key: () => null,
247
- },
248
- }),
293
+ server: {
294
+ data: defineState({
295
+ defaultValue: '',
296
+ storage: {
297
+ length: 0,
298
+ getItem: (key) => db[key] ?? null,
299
+ setItem: (key, value) => debouncedSave(key, value),
300
+ removeItem: (key) => { delete db[key] },
301
+ clear: () => {},
302
+ key: () => null,
303
+ },
304
+ }),
305
+ },
249
306
  })
250
307
  ```
251
308
 
252
309
  ## Full Example
253
310
 
254
311
  ```tsx
255
- import { setupStorage, defineState, StorageProvider } from 'state-vocab'
312
+ import { setupStorage, defineState, StorageProvider } from '@yakocloud/state-vocab'
256
313
 
257
314
  type Theme = 'Dark' | 'White' | 'System'
258
315
 
259
316
  const storage = setupStorage({
260
317
  preference: {
261
318
  theme: defineState<Theme>({ storage: localStorage, defaultValue: 'Dark' }),
262
- nightMode: defineState({ storage: sessionStorage }),
319
+ nightMode: defineState({ storage: sessionStorage, defaultValue: false }),
263
320
  },
264
321
  stats: {
265
- counter: defineState({ defaultValue: 0 }),
322
+ counter: defineState({ defaultValue: 0, storage: sessionStorage }),
266
323
  },
267
324
  personal: {
268
- note: defineState({ storage: localStorage }),
325
+ note: defineState({ storage: localStorage, defaultValue: '' }),
269
326
  birthday: defineState({
270
327
  storage: localStorage,
271
328
  deserialize: (raw) => {
@@ -273,20 +330,41 @@ const storage = setupStorage({
273
330
  },
274
331
  }),
275
332
  },
333
+ demo: {
334
+ pageProps: defineState<{ title: string; count: number }>({
335
+ storage: localStorage,
336
+ }),
337
+ },
276
338
  })
277
339
 
340
+ // Root — initializes shared state for the whole subtree
341
+ function Page() {
342
+ storage.demo.pageProps.useState({
343
+ defaultValue: { title: 'Hello', count: 42 },
344
+ })
345
+
346
+ return <Dashboard />
347
+ }
348
+
349
+ // Deep child — reads without re-specifying defaults
350
+ function PageHeader() {
351
+ const [pageProps] = storage.demo.pageProps.useState()
352
+ return <h1>{pageProps.title} ({pageProps.count})</h1>
353
+ }
354
+
278
355
  function Dashboard() {
279
356
  const [theme, setTheme] = storage.preference.theme.useState()
280
- const [nightMode, setNightMode] = storage.preference.nightMode.useState(false)
281
- const [counter, setCounter, resetCounter] = storage.stats.counter.useState(0)
282
- const [note, setNote] = storage.personal.note.useState('', {
357
+ const [nightMode, setNightMode] = storage.preference.nightMode.useState()
358
+ const [counter, setCounter, resetCounter] = storage.stats.counter.useState()
359
+ const [note, setNote] = storage.personal.note.useState({
283
360
  delayedSet: 500,
284
- bidirectional: true,
285
361
  onSet: (v) => console.log('Saving note:', v),
286
362
  })
287
363
 
288
364
  return (
289
365
  <div>
366
+ <PageHeader />
367
+
290
368
  <select value={theme ?? ''} onChange={(e) => setTheme(e.target.value as Theme)}>
291
369
  <option value="Dark">Dark</option>
292
370
  <option value="White">White</option>
@@ -317,7 +395,7 @@ function Dashboard() {
317
395
 
318
396
  createRoot(document.getElementById('root')!).render(
319
397
  <StorageProvider>
320
- <Dashboard />
398
+ <Page />
321
399
  </StorageProvider>
322
400
  )
323
401
  ```
@@ -329,12 +407,16 @@ createRoot(document.getElementById('root')!).render(
329
407
  | Option | Type | Default |
330
408
  |---|---|---|
331
409
  | `storage` | `Storage \| (() => Storage) \| undefined` | `undefined` (in-memory) |
332
- | `defaultValue` | `T \| undefined` | `undefined` |
410
+ | `defaultValue` | `T \| (() => T) \| undefined` | `undefined` |
333
411
  | `bidirectional` | `true \| undefined` | `undefined` |
334
412
  | `serialize` | `(v: T) => string` | `JSON.stringify` |
335
413
  | `deserialize` | `(v: string) => T` | `JSON.parse` |
336
414
 
337
- ### `setupStorage<T>(tree: T): T`
415
+ ### `setupStorage<T>(tree: T, options?): T`
416
+
417
+ | Option | Type | Default |
418
+ |---|---|---|
419
+ | `ssr` | `boolean \| undefined` | `false` |
338
420
 
339
421
  Returns a proxied copy of `tree` with paths injected into all leaf nodes.
340
422
 
@@ -342,13 +424,17 @@ Returns a proxied copy of `tree` with paths injected into all leaf nodes.
342
424
 
343
425
  React context provider. Must be an ancestor of any component using `.useState()`.
344
426
 
345
- ### `node.useState<D>(defaultValue?, options?)`
427
+ | Prop | Type | Description |
428
+ |---|---|---|
429
+ | `verbose` | `boolean \| undefined` | Log state vocab to console on every change |
430
+
431
+ ### `node.useState(options?)`
346
432
 
347
- | Parameter | Type | Description |
433
+ | Option | Type | Description |
348
434
  |---|---|---|
349
- | `defaultValue` | `D \| (() => D) \| undefined` | Local default, overrides `defineState` default |
350
- | `options.delayedSet` | `number \| undefined` | Debounce delay for `onSet` in ms |
351
- | `options.onSet` | `(next: D, prev: D) => void \| undefined` | Callback after state change |
352
- | `options.bidirectional` | `true \| undefined` | bidirectional state update to sync tabs |
435
+ | `defaultValue` | `T \| (() => T) \| undefined` | Local default, overrides `defineState` default |
436
+ | `delayedSet` | `number \| undefined` | Debounce delay for `onSet` in ms |
437
+ | `onSet` | `(next: T, prev: T) => void \| undefined` | Callback after state change |
438
+ | `bidirectional` | `true \| undefined` | Sync state across browser tabs |
353
439
 
354
440
  Returns `[value, setValue, resetValue]`.
@@ -1,8 +1,8 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("react"),te=Symbol("state-def"),C=Symbol("state-path"),L=Symbol("state-ssr");function fe(t,a,r){if(!a)return t;const s=a.split(".");let n=t;for(const c of s)if(n!==null&&typeof n=="object"&&c in n)n=n[c];else return r;return n===void 0?r:n}function de(t,a,r){const s=a.replace(/\[(\d+)\]/g,".$1").split(".");let n=t;for(let c=0;c<s.length-1;c++){const d=s[c],b=s[c+1];(n[d]===void 0||n[d]===null)&&(n[d]=/^\d+$/.test(b)?[]:{}),n=n[d]}return n[s[s.length-1]]=r,t}function me(t,a=0){let r;return function(...s){r!==void 0&&clearTimeout(r),r=setTimeout(()=>{r=void 0,t.apply(this,s)},a)}}function be(t,a,r=[]){return _.useMemo(()=>me(t,a),r)}function ve(t){const a=JSON.stringify(t,null,2).split(`
2
- `),r=[],s=[];for(const n of a){const c=n.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,d,b,v,u]=c;r.push(`${d}%c"${b}"%c${v}%c${u}`),s.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else r.push(`%c${n}`),s.push("color: #cccccc")}console.log(r.join(`
3
- `),...s,t)}var j={exports:{}},x={};var B;function Ee(){if(B)return x;B=1;var t=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function r(s,n,c){var d=null;if(c!==void 0&&(d=""+c),n.key!==void 0&&(d=""+n.key),"key"in n){c={};for(var b in n)b!=="key"&&(c[b]=n[b])}else c=n;return n=c.ref,{$$typeof:t,type:s,key:d,ref:n!==void 0?n:null,props:c}}return x.Fragment=a,x.jsx=r,x.jsxs=r,x}var O={};var H;function Se(){return H||(H=1,process.env.NODE_ENV!=="production"&&(function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===ue?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case h:return"Fragment";case m:return"Profiler";case k:return"StrictMode";case oe:return"Suspense";case ae:return"SuspenseList";case ce:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case p:return"Portal";case $:return e.displayName||"Context";case g:return(e._context.displayName||"Context")+".Consumer";case w:var o=e.render;return e=e.displayName,e||(e=o.displayName||o.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case se:return o=e.displayName||null,o!==null?o:t(e.type)||"Memo";case I:o=e._payload,e=e._init;try{return t(e(o))}catch{}}return null}function a(e){return""+e}function r(e){try{a(e);var o=!1}catch{o=!0}if(o){o=console;var l=o.error,i=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return l.call(o,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",i),a(e)}}function s(e){if(e===h)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===I)return"<...>";try{var o=t(e);return o?"<"+o+">":"<...>"}catch{return"<...>"}}function n(){var e=M.A;return e===null?null:e.getOwner()}function c(){return Error("react-stack-top-frame")}function d(e){if(W.call(e,"key")){var o=Object.getOwnPropertyDescriptor(e,"key").get;if(o&&o.isReactWarning)return!1}return e.key!==void 0}function b(e,o){function l(){J||(J=!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)",o))}l.isReactWarning=!0,Object.defineProperty(e,"key",{get:l,configurable:!0})}function v(){var e=t(this.type);return U[e]||(U[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function u(e,o,l,i,A,D){var f=l.ref;return e={$$typeof:T,type:e,key:o,props:l,_owner:i},(f!==void 0?f:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:v}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:A}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:D}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function y(e,o,l,i,A,D){var f=o.children;if(f!==void 0)if(i)if(le(f)){for(i=0;i<f.length;i++)E(f[i]);Object.freeze&&Object.freeze(f)}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 E(f);if(W.call(o,"key")){f=t(e);var P=Object.keys(o).filter(function(ie){return ie!=="key"});i=0<P.length?"{key: someKey, "+P.join(": ..., ")+": ...}":"{key: someKey}",X[f+i]||(P=0<P.length?"{"+P.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("react"),re=Symbol("state-def"),$=Symbol("state-path"),W=Symbol("state-ssr");function ie(t,s,r){if(!s)return t;const a=s.split(".");let n=t;for(const c of a)if(n!==null&&typeof n=="object"&&c in n)n=n[c];else return r;return n===void 0?r:n}function fe(t,s,r){const a=s.replace(/\[(\d+)\]/g,".$1").split(".");let n=t;for(let c=0;c<a.length-1;c++){const m=a[c],v=a[c+1];(n[m]===void 0||n[m]===null)&&(n[m]=/^\d+$/.test(v)?[]:{}),n=n[m]}return n[a[a.length-1]]=r,t}function de(t,s=0){let r;return function(...a){r!==void 0&&clearTimeout(r),r=setTimeout(()=>{r=void 0,t.apply(this,a)},s)}}function me(t,s,r=[]){return p.useMemo(()=>de(t,s),r)}function be(t){const s=JSON.stringify(t,null,2).split(`
2
+ `),r=[],a=[];for(const n of s){const c=n.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);if(c){const[,m,v,S,l]=c;r.push(`${m}%c"${v}"%c${S}%c${l}`),a.push("color: #9cdcfe; font-weight: bold","color: #cccccc","color: #ce9178")}else r.push(`%c${n}`),a.push("color: #cccccc")}console.log(r.join(`
3
+ `),...a,t)}var V={exports:{}},x={};var Z;function ve(){if(Z)return x;Z=1;var t=Symbol.for("react.transitional.element"),s=Symbol.for("react.fragment");function r(a,n,c){var m=null;if(c!==void 0&&(m=""+c),n.key!==void 0&&(m=""+n.key),"key"in n){c={};for(var v in n)v!=="key"&&(c[v]=n[v])}else c=n;return n=c.ref,{$$typeof:t,type:a,key:m,ref:n!==void 0?n:null,props:c}}return x.Fragment=s,x.jsx=r,x.jsxs=r,x}var O={};var Q;function Ee(){return Q||(Q=1,process.env.NODE_ENV!=="production"&&(function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===ce?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case E:return"Fragment";case A:return"Profiler";case k:return"StrictMode";case J:return"Suspense";case w:return"SuspenseList";case se:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case T:return"Portal";case h:return e.displayName||"Context";case b:return(e._context.displayName||"Context")+".Consumer";case j:var o=e.render;return e=e.displayName,e||(e=o.displayName||o.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ae:return o=e.displayName||null,o!==null?o:t(e.type)||"Memo";case I:o=e._payload,e=e._init;try{return t(e(o))}catch{}}return null}function s(e){return""+e}function r(e){try{s(e);var o=!1}catch{o=!0}if(o){o=console;var u=o.error,f=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return u.call(o,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",f),s(e)}}function a(e){if(e===E)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===I)return"<...>";try{var o=t(e);return o?"<"+o+">":"<...>"}catch{return"<...>"}}function n(){var e=M.A;return e===null?null:e.getOwner()}function c(){return Error("react-stack-top-frame")}function m(e){if(U.call(e,"key")){var o=Object.getOwnPropertyDescriptor(e,"key").get;if(o&&o.isReactWarning)return!1}return e.key!==void 0}function v(e,o){function u(){q||(q=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",o))}u.isReactWarning=!0,Object.defineProperty(e,"key",{get:u,configurable:!0})}function S(){var e=t(this.type);return G[e]||(G[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function l(e,o,u,f,N,D){var d=u.ref;return e={$$typeof:g,type:e,key:o,props:u,_owner:f},(d!==void 0?d:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:S}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:N}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:D}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function i(e,o,u,f,N,D){var d=o.children;if(d!==void 0)if(f)if(ue(d)){for(f=0;f<d.length;f++)_(d[f]);Object.freeze&&Object.freeze(d)}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);if(U.call(o,"key")){d=t(e);var P=Object.keys(o).filter(function(le){return le!=="key"});f=0<P.length?"{key: someKey, "+P.join(": ..., ")+": ...}":"{key: someKey}",H[d+f]||(P=0<P.length?"{"+P.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
4
4
  let props = %s;
5
5
  <%s {...props} />
6
6
  React keys must be passed directly to JSX without using spread:
7
7
  let props = %s;
8
- <%s key={someKey} {...props} />`,i,f,P,f),X[f+i]=!0)}if(f=null,l!==void 0&&(r(l),f=""+l),d(o)&&(r(o.key),f=""+o.key),"key"in o){l={};for(var F in o)F!=="key"&&(l[F]=o[F])}else l=o;return f&&b(l,typeof e=="function"?e.displayName||e.name||"Unknown":e),u(e,f,l,n(),A,D)}function E(e){R(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===I&&(e._payload.status==="fulfilled"?R(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function R(e){return typeof e=="object"&&e!==null&&e.$$typeof===T}var S=_,T=Symbol.for("react.transitional.element"),p=Symbol.for("react.portal"),h=Symbol.for("react.fragment"),k=Symbol.for("react.strict_mode"),m=Symbol.for("react.profiler"),g=Symbol.for("react.consumer"),$=Symbol.for("react.context"),w=Symbol.for("react.forward_ref"),oe=Symbol.for("react.suspense"),ae=Symbol.for("react.suspense_list"),se=Symbol.for("react.memo"),I=Symbol.for("react.lazy"),ce=Symbol.for("react.activity"),ue=Symbol.for("react.client.reference"),M=S.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,W=Object.prototype.hasOwnProperty,le=Array.isArray,Y=console.createTask?console.createTask:function(){return null};S={react_stack_bottom_frame:function(e){return e()}};var J,U={},q=S.react_stack_bottom_frame.bind(S,c)(),G=Y(s(c)),X={};O.Fragment=h,O.jsx=function(e,o,l){var i=1e4>M.recentlyCreatedOwnerStacks++;return y(e,o,l,!1,i?Error("react-stack-top-frame"):q,i?Y(s(e)):G)},O.jsxs=function(e,o,l){var i=1e4>M.recentlyCreatedOwnerStacks++;return y(e,o,l,!0,i?Error("react-stack-top-frame"):q,i?Y(s(e)):G)}})()),O}var Z;function _e(){return Z||(Z=1,process.env.NODE_ENV==="production"?j.exports=Ee():j.exports=Se()),j.exports}var pe=_e();const re=_.createContext({stateVocab:{},setStateVocab:()=>{}});function Re(){return _.useContext(re)}const Te=t=>{const{children:a,verbose:r}=t,[s,n]=_.useState({});return r&&ve(s),pe.jsx(re.Provider,{value:{stateVocab:s,setStateVocab:n},children:a})},V=(t,a)=>r=>{const s={...r};return de(s,t,a),s},Q=t=>{const{serialized:a,deserialize:r}=t;return a===null?null:r(a)},ye=t=>typeof t=="function",ge=t=>typeof t=="function",z=t=>typeof t<"u",N=t=>ge(t)?t():t,he=typeof window>"u";function ke(t={}){return{[te]:!0,[L]:!1,[C]:"",useState(a){const r=he?void 0:N(t.storage),s=t.serialize??JSON.stringify,n=t.deserialize??JSON.parse,c=t.defaultValue,d=t.bidirectional;a??={};const b=be(a.onSet??(()=>{}),a.delayedSet,[]),v=Re(),u=this[C],y=this[L],[E,R]=_.useState(!y);_.useEffect(()=>R(!0),[]);const S=_.useMemo(()=>{if(!E||!r)return;const m=r.getItem(u);return Q({deserialize:n,serialized:m})},[E]),T=_.useMemo(()=>fe(v.stateVocab,u,S??N(a.defaultValue)??c),[v.stateVocab,S]);_.useEffect(()=>{z(T)&&(v.setStateVocab(V(u,T)),r&&S===null&&r.setItem(u,s(T)))},[S]),_.useEffect(()=>{if(!a.bidirectional&&!d)return;const m=g=>{if(g.key!==u)return;const $=g.newValue,w=Q({serialized:$,deserialize:n})??N(a.defaultValue)??c;z(w)&&(v.setStateVocab(V(u,w)),b(w,p.current),p.current=w)};return window.addEventListener("storage",m),()=>window.removeEventListener("storage",m)},[a.bidirectional,d]);const p=_.useRef(T);return[T,m=>{const g=ye(m)?m(p.current):m;v.setStateVocab(V(u,g)),b(g,p.current),r&&r.setItem(u,s(g)),p.current=g},()=>{const m=N(a.defaultValue)??c;if(!z(m)){r?.removeItem(u);return}v.setStateVocab(V(u,m)),b(m,p.current),p.current=m,r&&r.setItem(u,s(m))}]},toString(){return this[C]}}}const K=new WeakMap,ee=new WeakMap;function ne(t,a){a??={};const{path:r="",ssr:s}=a;let n=K.get(t);n||(n=new Map,K.set(t,n));const c=n.get(r);if(c)return c;const d=new Proxy(t,{get(b,v){const u=b[v],y=r?`${r}.${String(v)}`:String(v);if(u&&typeof u=="object"&&te in u){const E=u;let R=ee.get(E);R||(R=new Map,ee.set(E,R));const S=R.get(y);if(S)return S;const T=Reflect.ownKeys(E).filter(k=>typeof E[k]=="function"),p=Object.fromEntries(T.map(k=>[k,(...m)=>E[k].call({...E,[C]:y,[L]:s},...m)])),h={...E,...p};return R.set(y,h),h}return u&&typeof u=="object"?ne(u,{path:y,ssr:s}):u}});return n.set(r,d),d}function we(t,a){return ne(t,a)}exports.StorageProvider=Te;exports.defineState=ke;exports.setupStorage=we;
8
+ <%s key={someKey} {...props} />`,f,d,P,d),H[d+f]=!0)}if(d=null,u!==void 0&&(r(u),d=""+u),m(o)&&(r(o.key),d=""+o.key),"key"in o){u={};for(var F in o)F!=="key"&&(u[F]=o[F])}else u=o;return d&&v(u,typeof e=="function"?e.displayName||e.name||"Unknown":e),l(e,d,u,n(),N,D)}function _(e){R(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===I&&(e._payload.status==="fulfilled"?R(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function R(e){return typeof e=="object"&&e!==null&&e.$$typeof===g}var y=p,g=Symbol.for("react.transitional.element"),T=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),k=Symbol.for("react.strict_mode"),A=Symbol.for("react.profiler"),b=Symbol.for("react.consumer"),h=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),J=Symbol.for("react.suspense"),w=Symbol.for("react.suspense_list"),ae=Symbol.for("react.memo"),I=Symbol.for("react.lazy"),se=Symbol.for("react.activity"),ce=Symbol.for("react.client.reference"),M=y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,U=Object.prototype.hasOwnProperty,ue=Array.isArray,Y=console.createTask?console.createTask:function(){return null};y={react_stack_bottom_frame:function(e){return e()}};var q,G={},X=y.react_stack_bottom_frame.bind(y,c)(),B=Y(a(c)),H={};O.Fragment=E,O.jsx=function(e,o,u){var f=1e4>M.recentlyCreatedOwnerStacks++;return i(e,o,u,!1,f?Error("react-stack-top-frame"):X,f?Y(a(e)):B)},O.jsxs=function(e,o,u){var f=1e4>M.recentlyCreatedOwnerStacks++;return i(e,o,u,!0,f?Error("react-stack-top-frame"):X,f?Y(a(e)):B)}})()),O}var K;function _e(){return K||(K=1,process.env.NODE_ENV==="production"?V.exports=ve():V.exports=Ee()),V.exports}var pe=_e();const ne=p.createContext({stateVocab:{},setStateVocab:()=>{}});function Se(){return p.useContext(ne)}const Re=t=>{const{children:s,verbose:r}=t,[a,n]=p.useState({});return r&&be(a),pe.jsx(ne.Provider,{value:{stateVocab:a,setStateVocab:n},children:s})},C=(t,s)=>r=>{const a={...r};return fe(a,t,s),a},Te=t=>typeof t=="function",ye=t=>typeof t=="function",z=t=>typeof t<"u",L=t=>ye(t)?t():t,ge=typeof window>"u";function he(t={}){return{[re]:!0,[W]:!1,[$]:"",useState(s){const r=ge?void 0:L(t.storage),a=t.serialize??JSON.stringify,n=t.deserialize??JSON.parse,c=L(t.defaultValue),m=t.bidirectional;s??={};const v=L(s.defaultValue),S=me(s.onSet??(()=>{}),s.delayedSet,[]),l=Se(),i=this[$],_=this[W],[R,y]=p.useState(!_);p.useEffect(()=>y(!0),[]);const g=p.useMemo(()=>{if(!R||!r)return;const b=r.getItem(i);return b===null?null:n(b)},[R]),T=p.useMemo(()=>ie(l.stateVocab,i,g??v??c),[l.stateVocab,g]),E=p.useRef(T);return p.useEffect(()=>{z(T)&&(l.setStateVocab(C(i,T)),r&&g===null&&r.setItem(i,a(T)),E.current=T)},[g]),p.useEffect(()=>{if(!s.bidirectional&&!m)return;const b=h=>{if(h.key!==i)return;const j=h.newValue,w=(j===null?null:n(j))??v??c;z(w)&&(l.setStateVocab(C(i,w)),S(w,E.current),E.current=w)};return window.addEventListener("storage",b),()=>window.removeEventListener("storage",b)},[s.bidirectional,m]),[T,b=>{const h=Te(b)?b(E.current):b;l.setStateVocab(C(i,h)),S(h,E.current),r&&r.setItem(i,a(h)),E.current=h},()=>{const b=v??c;if(!z(b)){r?.removeItem(i);return}l.setStateVocab(C(i,b)),S(b,E.current),E.current=b,r&&r.setItem(i,a(b))}]},toString(){return this[$]}}}const ee=new WeakMap,te=new WeakMap;function oe(t,s){s??={};const{path:r="",ssr:a}=s;let n=ee.get(t);n||(n=new Map,ee.set(t,n));const c=n.get(r);if(c)return c;const m=new Proxy(t,{get(v,S){const l=v[S],i=r?`${r}.${String(S)}`:String(S);if(l&&typeof l=="object"&&re in l){const _=l;let R=te.get(_);R||(R=new Map,te.set(_,R));const y=R.get(i);if(y)return y;const g=Reflect.ownKeys(_).filter(k=>typeof _[k]=="function"),T=Object.fromEntries(g.map(k=>[k,(...A)=>_[k].call({..._,[$]:i,[W]:a},...A)])),E={..._,...T};return R.set(i,E),E}return l&&typeof l=="object"?oe(l,{path:i,ssr:a}):l}});return n.set(r,m),m}function ke(t,s){return oe(t,s)}exports.StorageProvider=Re;exports.defineState=he;exports.setupStorage=ke;
@@ -1,119 +1,119 @@
1
- import me, { useMemo as L, createContext as be, useState as re, useContext as ve, useEffect as M, useRef as Ee } from "react";
2
- const ne = Symbol("state-def"), N = Symbol("state-path"), W = Symbol("state-ssr");
3
- function _e(t, a, r) {
4
- if (!a)
1
+ import de, { useMemo as W, createContext as me, useState as ne, useContext as be, useEffect as M, useRef as ve } from "react";
2
+ const oe = Symbol("state-def"), C = Symbol("state-path"), J = Symbol("state-ssr");
3
+ function Ee(t, s, r) {
4
+ if (!s)
5
5
  return t;
6
- const s = a.split(".");
6
+ const a = s.split(".");
7
7
  let n = t;
8
- for (const c of s)
8
+ for (const c of a)
9
9
  if (n !== null && typeof n == "object" && c in n)
10
10
  n = n[c];
11
11
  else
12
12
  return r;
13
13
  return n === void 0 ? r : n;
14
14
  }
15
- function pe(t, a, r) {
16
- const s = a.replace(/\[(\d+)\]/g, ".$1").split(".");
15
+ function _e(t, s, r) {
16
+ const a = s.replace(/\[(\d+)\]/g, ".$1").split(".");
17
17
  let n = t;
18
- for (let c = 0; c < s.length - 1; c++) {
19
- const d = s[c], b = s[c + 1];
20
- (n[d] === void 0 || n[d] === null) && (n[d] = /^\d+$/.test(b) ? [] : {}), n = n[d];
18
+ for (let c = 0; c < a.length - 1; c++) {
19
+ const m = a[c], v = a[c + 1];
20
+ (n[m] === void 0 || n[m] === null) && (n[m] = /^\d+$/.test(v) ? [] : {}), n = n[m];
21
21
  }
22
- return n[s[s.length - 1]] = r, t;
22
+ return n[a[a.length - 1]] = r, t;
23
23
  }
24
- function Se(t, a = 0) {
24
+ function pe(t, s = 0) {
25
25
  let r;
26
- return function(...s) {
26
+ return function(...a) {
27
27
  r !== void 0 && clearTimeout(r), r = setTimeout(() => {
28
- r = void 0, t.apply(this, s);
29
- }, a);
28
+ r = void 0, t.apply(this, a);
29
+ }, s);
30
30
  };
31
31
  }
32
- function Re(t, a, r = []) {
33
- return L(
34
- () => Se(t, a),
32
+ function Se(t, s, r = []) {
33
+ return W(
34
+ () => pe(t, s),
35
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
36
  r
37
37
  );
38
38
  }
39
- function Te(t) {
40
- const a = JSON.stringify(t, null, 2).split(`
41
- `), r = [], s = [];
42
- for (const n of a) {
39
+ function Re(t) {
40
+ const s = JSON.stringify(t, null, 2).split(`
41
+ `), r = [], a = [];
42
+ for (const n of s) {
43
43
  const c = n.match(/^(\s*)"([^"]+)"(\s*:\s*)(.+)$/);
44
44
  if (c) {
45
- const [, d, b, v, u] = c;
46
- r.push(`${d}%c"${b}"%c${v}%c${u}`), s.push(
45
+ const [, m, v, p, l] = c;
46
+ r.push(`${m}%c"${v}"%c${p}%c${l}`), a.push(
47
47
  "color: #9cdcfe; font-weight: bold",
48
48
  "color: #cccccc",
49
49
  "color: #ce9178"
50
50
  );
51
51
  } else
52
- r.push(`%c${n}`), s.push("color: #cccccc");
52
+ r.push(`%c${n}`), a.push("color: #cccccc");
53
53
  }
54
54
  console.log(r.join(`
55
- `), ...s, t);
55
+ `), ...a, t);
56
56
  }
57
- var O = { exports: {} }, P = {};
58
- var H;
59
- function ye() {
60
- if (H) return P;
61
- H = 1;
62
- var t = Symbol.for("react.transitional.element"), a = Symbol.for("react.fragment");
63
- function r(s, n, c) {
64
- var d = null;
65
- if (c !== void 0 && (d = "" + c), n.key !== void 0 && (d = "" + n.key), "key" in n) {
57
+ var N = { exports: {} }, P = {};
58
+ var Q;
59
+ function Te() {
60
+ if (Q) return P;
61
+ Q = 1;
62
+ var t = Symbol.for("react.transitional.element"), s = Symbol.for("react.fragment");
63
+ function r(a, n, c) {
64
+ var m = null;
65
+ if (c !== void 0 && (m = "" + c), n.key !== void 0 && (m = "" + n.key), "key" in n) {
66
66
  c = {};
67
- for (var b in n)
68
- b !== "key" && (c[b] = n[b]);
67
+ for (var v in n)
68
+ v !== "key" && (c[v] = n[v]);
69
69
  } else c = n;
70
70
  return n = c.ref, {
71
71
  $$typeof: t,
72
- type: s,
73
- key: d,
72
+ type: a,
73
+ key: m,
74
74
  ref: n !== void 0 ? n : null,
75
75
  props: c
76
76
  };
77
77
  }
78
- return P.Fragment = a, P.jsx = r, P.jsxs = r, P;
78
+ return P.Fragment = s, P.jsx = r, P.jsxs = r, P;
79
79
  }
80
80
  var x = {};
81
- var Z;
82
- function he() {
83
- return Z || (Z = 1, process.env.NODE_ENV !== "production" && (function() {
81
+ var K;
82
+ function ye() {
83
+ return K || (K = 1, process.env.NODE_ENV !== "production" && (function() {
84
84
  function t(e) {
85
85
  if (e == null) return null;
86
86
  if (typeof e == "function")
87
- return e.$$typeof === ie ? null : e.displayName || e.name || null;
87
+ return e.$$typeof === le ? null : e.displayName || e.name || null;
88
88
  if (typeof e == "string") return e;
89
89
  switch (e) {
90
- case h:
90
+ case E:
91
91
  return "Fragment";
92
- case m:
92
+ case A:
93
93
  return "Profiler";
94
94
  case g:
95
95
  return "StrictMode";
96
- case se:
96
+ case U:
97
97
  return "Suspense";
98
- case ce:
98
+ case k:
99
99
  return "SuspenseList";
100
- case le:
100
+ case ue:
101
101
  return "Activity";
102
102
  }
103
103
  if (typeof e == "object")
104
104
  switch (typeof e.tag == "number" && console.error(
105
105
  "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
106
106
  ), e.$$typeof) {
107
- case p:
107
+ case R:
108
108
  return "Portal";
109
- case C:
109
+ case h:
110
110
  return e.displayName || "Context";
111
- case y:
111
+ case b:
112
112
  return (e._context.displayName || "Context") + ".Consumer";
113
- case k:
113
+ case O:
114
114
  var o = e.render;
115
115
  return e = e.displayName, e || (e = o.displayName || o.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
116
- case ue:
116
+ case ce:
117
117
  return o = e.displayName || null, o !== null ? o : t(e.type) || "Memo";
118
118
  case $:
119
119
  o = e._payload, e = e._init;
@@ -124,28 +124,28 @@ function he() {
124
124
  }
125
125
  return null;
126
126
  }
127
- function a(e) {
127
+ function s(e) {
128
128
  return "" + e;
129
129
  }
130
130
  function r(e) {
131
131
  try {
132
- a(e);
132
+ s(e);
133
133
  var o = !1;
134
134
  } catch {
135
135
  o = !0;
136
136
  }
137
137
  if (o) {
138
138
  o = console;
139
- var l = o.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
140
- return l.call(
139
+ var u = o.error, f = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
140
+ return u.call(
141
141
  o,
142
142
  "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
143
- i
144
- ), a(e);
143
+ f
144
+ ), s(e);
145
145
  }
146
146
  }
147
- function s(e) {
148
- if (e === h) return "<>";
147
+ function a(e) {
148
+ if (e === E) return "<>";
149
149
  if (typeof e == "object" && e !== null && e.$$typeof === $)
150
150
  return "<...>";
151
151
  try {
@@ -162,42 +162,42 @@ function he() {
162
162
  function c() {
163
163
  return Error("react-stack-top-frame");
164
164
  }
165
- function d(e) {
166
- if (J.call(e, "key")) {
165
+ function m(e) {
166
+ if (q.call(e, "key")) {
167
167
  var o = Object.getOwnPropertyDescriptor(e, "key").get;
168
168
  if (o && o.isReactWarning) return !1;
169
169
  }
170
170
  return e.key !== void 0;
171
171
  }
172
- function b(e, o) {
173
- function l() {
174
- U || (U = !0, console.error(
172
+ function v(e, o) {
173
+ function u() {
174
+ G || (G = !0, console.error(
175
175
  "%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)",
176
176
  o
177
177
  ));
178
178
  }
179
- l.isReactWarning = !0, Object.defineProperty(e, "key", {
180
- get: l,
179
+ u.isReactWarning = !0, Object.defineProperty(e, "key", {
180
+ get: u,
181
181
  configurable: !0
182
182
  });
183
183
  }
184
- function v() {
184
+ function p() {
185
185
  var e = t(this.type);
186
- return q[e] || (q[e] = !0, console.error(
186
+ return X[e] || (X[e] = !0, console.error(
187
187
  "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."
188
188
  )), e = this.props.ref, e !== void 0 ? e : null;
189
189
  }
190
- function u(e, o, l, i, A, D) {
191
- var f = l.ref;
190
+ function l(e, o, u, f, j, D) {
191
+ var d = u.ref;
192
192
  return e = {
193
- $$typeof: R,
193
+ $$typeof: y,
194
194
  type: e,
195
195
  key: o,
196
- props: l,
197
- _owner: i
198
- }, (f !== void 0 ? f : null) !== null ? Object.defineProperty(e, "ref", {
196
+ props: u,
197
+ _owner: f
198
+ }, (d !== void 0 ? d : null) !== null ? Object.defineProperty(e, "ref", {
199
199
  enumerable: !1,
200
- get: v
200
+ get: p
201
201
  }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
202
202
  configurable: !1,
203
203
  enumerable: !1,
@@ -212,7 +212,7 @@ function he() {
212
212
  configurable: !1,
213
213
  enumerable: !1,
214
214
  writable: !0,
215
- value: A
215
+ value: j
216
216
  }), Object.defineProperty(e, "_debugTask", {
217
217
  configurable: !1,
218
218
  enumerable: !1,
@@ -220,253 +220,248 @@ function he() {
220
220
  value: D
221
221
  }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
222
222
  }
223
- function T(e, o, l, i, A, D) {
224
- var f = o.children;
225
- if (f !== void 0)
226
- if (i)
227
- if (fe(f)) {
228
- for (i = 0; i < f.length; i++)
229
- E(f[i]);
230
- Object.freeze && Object.freeze(f);
223
+ function i(e, o, u, f, j, D) {
224
+ var d = o.children;
225
+ if (d !== void 0)
226
+ if (f)
227
+ if (ie(d)) {
228
+ for (f = 0; f < d.length; f++)
229
+ _(d[f]);
230
+ Object.freeze && Object.freeze(d);
231
231
  } else
232
232
  console.error(
233
233
  "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
234
234
  );
235
- else E(f);
236
- if (J.call(o, "key")) {
237
- f = t(e);
238
- var w = Object.keys(o).filter(function(de) {
239
- return de !== "key";
235
+ else _(d);
236
+ if (q.call(o, "key")) {
237
+ d = t(e);
238
+ var w = Object.keys(o).filter(function(fe) {
239
+ return fe !== "key";
240
240
  });
241
- i = 0 < w.length ? "{key: someKey, " + w.join(": ..., ") + ": ...}" : "{key: someKey}", B[f + i] || (w = 0 < w.length ? "{" + w.join(": ..., ") + ": ...}" : "{}", console.error(
241
+ f = 0 < w.length ? "{key: someKey, " + w.join(": ..., ") + ": ...}" : "{key: someKey}", Z[d + f] || (w = 0 < w.length ? "{" + w.join(": ..., ") + ": ...}" : "{}", console.error(
242
242
  `A props object containing a "key" prop is being spread into JSX:
243
243
  let props = %s;
244
244
  <%s {...props} />
245
245
  React keys must be passed directly to JSX without using spread:
246
246
  let props = %s;
247
247
  <%s key={someKey} {...props} />`,
248
- i,
249
248
  f,
249
+ d,
250
250
  w,
251
- f
252
- ), B[f + i] = !0);
251
+ d
252
+ ), Z[d + f] = !0);
253
253
  }
254
- if (f = null, l !== void 0 && (r(l), f = "" + l), d(o) && (r(o.key), f = "" + o.key), "key" in o) {
255
- l = {};
254
+ if (d = null, u !== void 0 && (r(u), d = "" + u), m(o) && (r(o.key), d = "" + o.key), "key" in o) {
255
+ u = {};
256
256
  for (var F in o)
257
- F !== "key" && (l[F] = o[F]);
258
- } else l = o;
259
- return f && b(
260
- l,
257
+ F !== "key" && (u[F] = o[F]);
258
+ } else u = o;
259
+ return d && v(
260
+ u,
261
261
  typeof e == "function" ? e.displayName || e.name || "Unknown" : e
262
- ), u(
262
+ ), l(
263
263
  e,
264
- f,
265
- l,
264
+ d,
265
+ u,
266
266
  n(),
267
- A,
267
+ j,
268
268
  D
269
269
  );
270
270
  }
271
- function E(e) {
271
+ function _(e) {
272
272
  S(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === $ && (e._payload.status === "fulfilled" ? S(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
273
273
  }
274
274
  function S(e) {
275
- return typeof e == "object" && e !== null && e.$$typeof === R;
275
+ return typeof e == "object" && e !== null && e.$$typeof === y;
276
276
  }
277
- var _ = me, R = Symbol.for("react.transitional.element"), p = Symbol.for("react.portal"), h = Symbol.for("react.fragment"), g = Symbol.for("react.strict_mode"), m = Symbol.for("react.profiler"), y = Symbol.for("react.consumer"), C = Symbol.for("react.context"), k = Symbol.for("react.forward_ref"), se = Symbol.for("react.suspense"), ce = Symbol.for("react.suspense_list"), ue = Symbol.for("react.memo"), $ = Symbol.for("react.lazy"), le = Symbol.for("react.activity"), ie = Symbol.for("react.client.reference"), I = _.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, J = Object.prototype.hasOwnProperty, fe = Array.isArray, Y = console.createTask ? console.createTask : function() {
277
+ var T = de, y = Symbol.for("react.transitional.element"), R = Symbol.for("react.portal"), E = Symbol.for("react.fragment"), g = Symbol.for("react.strict_mode"), A = Symbol.for("react.profiler"), b = Symbol.for("react.consumer"), h = Symbol.for("react.context"), O = Symbol.for("react.forward_ref"), U = Symbol.for("react.suspense"), k = Symbol.for("react.suspense_list"), ce = Symbol.for("react.memo"), $ = Symbol.for("react.lazy"), ue = Symbol.for("react.activity"), le = Symbol.for("react.client.reference"), I = T.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, q = Object.prototype.hasOwnProperty, ie = Array.isArray, Y = console.createTask ? console.createTask : function() {
278
278
  return null;
279
279
  };
280
- _ = {
280
+ T = {
281
281
  react_stack_bottom_frame: function(e) {
282
282
  return e();
283
283
  }
284
284
  };
285
- var U, q = {}, G = _.react_stack_bottom_frame.bind(
286
- _,
285
+ var G, X = {}, B = T.react_stack_bottom_frame.bind(
286
+ T,
287
287
  c
288
- )(), X = Y(s(c)), B = {};
289
- x.Fragment = h, x.jsx = function(e, o, l) {
290
- var i = 1e4 > I.recentlyCreatedOwnerStacks++;
291
- return T(
288
+ )(), H = Y(a(c)), Z = {};
289
+ x.Fragment = E, x.jsx = function(e, o, u) {
290
+ var f = 1e4 > I.recentlyCreatedOwnerStacks++;
291
+ return i(
292
292
  e,
293
293
  o,
294
- l,
294
+ u,
295
295
  !1,
296
- i ? Error("react-stack-top-frame") : G,
297
- i ? Y(s(e)) : X
296
+ f ? Error("react-stack-top-frame") : B,
297
+ f ? Y(a(e)) : H
298
298
  );
299
- }, x.jsxs = function(e, o, l) {
300
- var i = 1e4 > I.recentlyCreatedOwnerStacks++;
301
- return T(
299
+ }, x.jsxs = function(e, o, u) {
300
+ var f = 1e4 > I.recentlyCreatedOwnerStacks++;
301
+ return i(
302
302
  e,
303
303
  o,
304
- l,
304
+ u,
305
305
  !0,
306
- i ? Error("react-stack-top-frame") : G,
307
- i ? Y(s(e)) : X
306
+ f ? Error("react-stack-top-frame") : B,
307
+ f ? Y(a(e)) : H
308
308
  );
309
309
  };
310
310
  })()), x;
311
311
  }
312
- var Q;
313
- function ge() {
314
- return Q || (Q = 1, process.env.NODE_ENV === "production" ? O.exports = ye() : O.exports = he()), O.exports;
312
+ var ee;
313
+ function he() {
314
+ return ee || (ee = 1, process.env.NODE_ENV === "production" ? N.exports = Te() : N.exports = ye()), N.exports;
315
315
  }
316
- var ke = ge();
317
- const oe = be({
316
+ var ge = he();
317
+ const ae = me({
318
318
  stateVocab: {},
319
319
  setStateVocab: () => {
320
320
  }
321
321
  });
322
- function we() {
323
- return ve(oe);
322
+ function ke() {
323
+ return be(ae);
324
324
  }
325
- const je = (t) => {
326
- const { children: a, verbose: r } = t, [s, n] = re({});
327
- return r && Te(s), /* @__PURE__ */ ke.jsx(oe.Provider, { value: { stateVocab: s, setStateVocab: n }, children: a });
328
- }, j = (t, a) => (r) => {
329
- const s = { ...r };
330
- return pe(s, t, a), s;
331
- }, K = (t) => {
332
- const { serialized: a, deserialize: r } = t;
333
- return a === null ? null : r(a);
334
- }, Pe = (t) => typeof t == "function", xe = (t) => typeof t == "function", z = (t) => typeof t < "u", V = (t) => xe(t) ? t() : t, Ae = typeof window > "u";
335
- function Ve(t = {}) {
325
+ const Oe = (t) => {
326
+ const { children: s, verbose: r } = t, [a, n] = ne({});
327
+ return r && Re(a), /* @__PURE__ */ ge.jsx(ae.Provider, { value: { stateVocab: a, setStateVocab: n }, children: s });
328
+ }, V = (t, s) => (r) => {
329
+ const a = { ...r };
330
+ return _e(a, t, s), a;
331
+ }, we = (t) => typeof t == "function", Pe = (t) => typeof t == "function", z = (t) => typeof t < "u", L = (t) => Pe(t) ? t() : t, xe = typeof window > "u";
332
+ function je(t = {}) {
336
333
  return {
337
- [ne]: !0,
334
+ [oe]: !0,
338
335
  // marks this object as a leaf in the router tree
339
- [W]: !1,
336
+ [J]: !1,
340
337
  // placeholder; injected at runtime by injectPaths()
341
- [N]: "",
338
+ [C]: "",
342
339
  // placeholder; injected at runtime by injectPaths()
343
- useState(a) {
344
- const r = Ae ? void 0 : V(t.storage), s = t.serialize ?? JSON.stringify, n = t.deserialize ?? JSON.parse, c = t.defaultValue, d = t.bidirectional;
345
- a ??= {};
346
- const b = Re(
347
- a.onSet ?? (() => {
340
+ useState(s) {
341
+ const r = xe ? void 0 : L(t.storage), a = t.serialize ?? JSON.stringify, n = t.deserialize ?? JSON.parse, c = L(t.defaultValue), m = t.bidirectional;
342
+ s ??= {};
343
+ const v = L(s.defaultValue), p = Se(
344
+ s.onSet ?? (() => {
348
345
  }),
349
- a.delayedSet,
346
+ s.delayedSet,
350
347
  []
351
- ), v = we(), u = this[N], T = this[W], [E, S] = re(!T);
352
- M(() => S(!0), []);
353
- const _ = L(
348
+ ), l = ke(), i = this[C], _ = this[J], [S, T] = ne(!_);
349
+ M(() => T(!0), []);
350
+ const y = W(
354
351
  () => {
355
- if (!E || !r)
352
+ if (!S || !r)
356
353
  return;
357
- const m = r.getItem(u);
358
- return K({ deserialize: n, serialized: m });
354
+ const b = r.getItem(i);
355
+ return b === null ? null : n(b);
359
356
  },
360
357
  // eslint-disable-next-line react-hooks/exhaustive-deps
361
- [E]
362
- ), R = L(
363
- () => _e(
364
- v.stateVocab,
365
- u,
358
+ [S]
359
+ ), R = W(
360
+ () => Ee(
361
+ l.stateVocab,
362
+ i,
366
363
  // 3rd argument in order to avoid waiting for useEffect execution
367
- _ ?? V(a.defaultValue) ?? c
364
+ y ?? v ?? c
368
365
  ),
369
366
  // eslint-disable-next-line react-hooks/exhaustive-deps
370
367
  [
371
- v.stateVocab,
372
- _
368
+ l.stateVocab,
369
+ y
373
370
  ]
374
- );
375
- M(
371
+ ), E = ve(R);
372
+ return M(
376
373
  () => {
377
- z(R) && (v.setStateVocab(j(u, R)), r && _ === null && r.setItem(u, s(R)));
374
+ z(R) && (l.setStateVocab(V(i, R)), r && y === null && r.setItem(i, a(R)), E.current = R);
378
375
  },
379
376
  // eslint-disable-next-line react-hooks/exhaustive-deps
380
- [_]
377
+ [y]
381
378
  ), M(() => {
382
- if (!a.bidirectional && !d)
379
+ if (!s.bidirectional && !m)
383
380
  return;
384
- const m = (y) => {
385
- if (y.key !== u)
381
+ const b = (h) => {
382
+ if (h.key !== i)
386
383
  return;
387
- const C = y.newValue, k = K({ serialized: C, deserialize: n }) ?? V(a.defaultValue) ?? c;
388
- z(k) && (v.setStateVocab(j(u, k)), b(k, p.current), p.current = k);
384
+ const O = h.newValue, k = (O === null ? null : n(O)) ?? v ?? c;
385
+ z(k) && (l.setStateVocab(V(i, k)), p(k, E.current), E.current = k);
389
386
  };
390
- return window.addEventListener("storage", m), () => window.removeEventListener("storage", m);
387
+ return window.addEventListener("storage", b), () => window.removeEventListener("storage", b);
391
388
  }, [
392
- a.bidirectional,
393
- d
394
- ]);
395
- const p = Ee(R);
396
- return [
389
+ s.bidirectional,
390
+ m
391
+ ]), [
397
392
  R,
398
- (m) => {
399
- const y = Pe(m) ? m(p.current) : m;
400
- v.setStateVocab(j(u, y)), b(y, p.current), r && r.setItem(u, s(y)), p.current = y;
393
+ (b) => {
394
+ const h = we(b) ? b(E.current) : b;
395
+ l.setStateVocab(V(i, h)), p(h, E.current), r && r.setItem(i, a(h)), E.current = h;
401
396
  },
402
397
  () => {
403
- const m = V(a.defaultValue) ?? c;
404
- if (!z(m)) {
405
- r?.removeItem(u);
398
+ const b = v ?? c;
399
+ if (!z(b)) {
400
+ r?.removeItem(i);
406
401
  return;
407
402
  }
408
- v.setStateVocab(j(u, m)), b(m, p.current), p.current = m, r && r.setItem(u, s(m));
403
+ l.setStateVocab(V(i, b)), p(b, E.current), E.current = b, r && r.setItem(i, a(b));
409
404
  }
410
405
  ];
411
406
  },
412
407
  /** Returns the fully qualified job name (dot-separated path). */
413
408
  toString() {
414
- return this[N];
409
+ return this[C];
415
410
  }
416
411
  };
417
412
  }
418
- const ee = /* @__PURE__ */ new WeakMap(), te = /* @__PURE__ */ new WeakMap();
419
- function ae(t, a) {
420
- a ??= {};
413
+ const te = /* @__PURE__ */ new WeakMap(), re = /* @__PURE__ */ new WeakMap();
414
+ function se(t, s) {
415
+ s ??= {};
421
416
  const {
422
417
  path: r = "",
423
- ssr: s
424
- } = a;
425
- let n = ee.get(t);
426
- n || (n = /* @__PURE__ */ new Map(), ee.set(t, n));
418
+ ssr: a
419
+ } = s;
420
+ let n = te.get(t);
421
+ n || (n = /* @__PURE__ */ new Map(), te.set(t, n));
427
422
  const c = n.get(r);
428
423
  if (c)
429
424
  return c;
430
- const d = new Proxy(t, {
431
- get(b, v) {
432
- const u = b[v], T = r ? `${r}.${String(v)}` : String(v);
433
- if (u && typeof u == "object" && ne in u) {
434
- const E = u;
435
- let S = te.get(E);
436
- S || (S = /* @__PURE__ */ new Map(), te.set(E, S));
437
- const _ = S.get(T);
438
- if (_)
439
- return _;
440
- const R = Reflect.ownKeys(E).filter(
441
- (g) => typeof E[g] == "function"
442
- ), p = Object.fromEntries(
443
- R.map((g) => [
425
+ const m = new Proxy(t, {
426
+ get(v, p) {
427
+ const l = v[p], i = r ? `${r}.${String(p)}` : String(p);
428
+ if (l && typeof l == "object" && oe in l) {
429
+ const _ = l;
430
+ let S = re.get(_);
431
+ S || (S = /* @__PURE__ */ new Map(), re.set(_, S));
432
+ const T = S.get(i);
433
+ if (T)
434
+ return T;
435
+ const y = Reflect.ownKeys(_).filter(
436
+ (g) => typeof _[g] == "function"
437
+ ), R = Object.fromEntries(
438
+ y.map((g) => [
444
439
  g,
445
- (...m) => E[g].call(
440
+ (...A) => _[g].call(
446
441
  {
447
- ...E,
448
- [N]: T,
449
- [W]: s
442
+ ..._,
443
+ [C]: i,
444
+ [J]: a
450
445
  },
451
- ...m
446
+ ...A
452
447
  )
453
448
  ])
454
- ), h = { ...E, ...p };
455
- return S.set(T, h), h;
449
+ ), E = { ..._, ...R };
450
+ return S.set(i, E), E;
456
451
  }
457
- return u && typeof u == "object" ? ae(u, {
458
- path: T,
459
- ssr: s
460
- }) : u;
452
+ return l && typeof l == "object" ? se(l, {
453
+ path: i,
454
+ ssr: a
455
+ }) : l;
461
456
  }
462
457
  });
463
- return n.set(r, d), d;
458
+ return n.set(r, m), m;
464
459
  }
465
- function Ne(t, a) {
466
- return ae(t, a);
460
+ function Ne(t, s) {
461
+ return se(t, s);
467
462
  }
468
463
  export {
469
- je as StorageProvider,
470
- Ve as defineState,
464
+ Oe as StorageProvider,
465
+ je as defineState,
471
466
  Ne as setupStorage
472
467
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const toLocalDatetimeString: (date: Date | null) => string;
2
+ export declare const toDateString: (date: Date | null) => string | undefined;
@@ -1,16 +1,16 @@
1
1
  import { STATE_DEFINITION, STATE_PATH, STATE_SSR } from "./constants";
2
2
  import type { Deserialize, Serialize, ValueOrFactory, ValueOrTransformer } from "./state.types";
3
- export declare function defineState<T>(definitionOptions?: {
3
+ export declare function defineState<D>(definitionOptions?: {
4
4
  storage?: ValueOrFactory<Storage>;
5
- defaultValue?: T;
5
+ defaultValue?: ValueOrFactory<D>;
6
6
  bidirectional?: true;
7
- serialize?: Serialize<T>;
8
- deserialize?: Deserialize<T>;
7
+ serialize?: Serialize<D>;
8
+ deserialize?: Deserialize<D>;
9
9
  }): {
10
10
  [STATE_DEFINITION]: boolean;
11
11
  [STATE_SSR]: boolean;
12
12
  [STATE_PATH]: string;
13
- useState<D = T>(this: {
13
+ useState(this: {
14
14
  [STATE_PATH]: string;
15
15
  [STATE_SSR]: boolean;
16
16
  }, options?: {
@@ -3,10 +3,6 @@ import type { ValueOrTransformer, Transformer, ValueOrFactory } from "./state.ty
3
3
  export declare const embed: <D>(statePath: string, value: D) => (vocab: Vocab<D>) => {
4
4
  [x: string]: D | null;
5
5
  };
6
- export declare const genStoredValue: <V>(options: {
7
- serialized: string | null;
8
- deserialize: (v: string) => V;
9
- }) => V | null;
10
6
  export declare const isTransformer: <V>(v: ValueOrTransformer<V>) => v is Transformer<V>;
11
7
  export declare const isValueDefined: <V>(v: V | undefined) => v is V;
12
8
  export declare const valueOrFactory: <V>(input: ValueOrFactory<V>) => V;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yakocloud/state-vocab",
3
- "version": "2.3.6",
3
+ "version": "2.5.1",
4
4
  "main": "dist/state-vocab.cjs.js",
5
5
  "module": "dist/state-vocab.es.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -8,6 +8,22 @@
8
8
  "files": [
9
9
  "dist"
10
10
  ],
11
+ "keywords": [
12
+ "react",
13
+ "state",
14
+ "state-management",
15
+ "storage",
16
+ "localStorage",
17
+ "sessionStorage",
18
+ "persist",
19
+ "persistent-state",
20
+ "hooks",
21
+ "useState",
22
+ "typescript",
23
+ "no-boilerplate",
24
+ "sync",
25
+ "cross-tab"
26
+ ],
11
27
  "repository": {
12
28
  "type": "git",
13
29
  "url": "https://github.com/yakovenkoroman1993/state-vocab"