@plasius/react-state 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.cjs +85 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -62
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
`@plasius/react-state` provides a scoped state management solution for React applications. It allows developers to create isolated, testable, and composable stores without introducing heavy dependencies.
|
|
16
16
|
|
|
17
|
+
**Key traits**
|
|
18
|
+
- React 18/19 compatible; uses `useSyncExternalStore` for tearing-safe snapshots.
|
|
19
|
+
- Distinct-until-changed dispatch flow to avoid needless notifications and re-renders.
|
|
20
|
+
- Selector subscriptions accept custom equality to prevent redundant renders when slices are unchanged.
|
|
21
|
+
- Scoped Provider recreates its store when `initialState` changes so fresh trees start from fresh state.
|
|
22
|
+
|
|
17
23
|
---
|
|
18
24
|
|
|
19
25
|
## Installation
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -98,23 +88,49 @@ function createStore(reducer, initialState) {
|
|
|
98
88
|
}
|
|
99
89
|
const globalSnapshot = [...listeners];
|
|
100
90
|
devTrack("store:notify:all", { listeners: globalSnapshot.length });
|
|
101
|
-
|
|
91
|
+
let firstError;
|
|
92
|
+
for (const listener of globalSnapshot) {
|
|
93
|
+
try {
|
|
94
|
+
listener();
|
|
95
|
+
} catch (err) {
|
|
96
|
+
if (!firstError) firstError = err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
102
99
|
for (const [key, set] of keyListeners.entries()) {
|
|
103
100
|
if (!Object.is(prevState[key], state[key])) {
|
|
104
101
|
devTrack("store:notify:key", { key: String(key), listeners: set.size });
|
|
105
|
-
for (const listener of [...set])
|
|
102
|
+
for (const listener of [...set]) {
|
|
103
|
+
try {
|
|
104
|
+
listener(state[key]);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (!firstError) firstError = err;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
let selNotifies = 0;
|
|
109
|
-
|
|
112
|
+
for (const entry of [...selectorListeners]) {
|
|
110
113
|
const nextValue = entry.selector(state);
|
|
111
|
-
|
|
114
|
+
const equal = entry.isEqual ?? Object.is;
|
|
115
|
+
let isSame = false;
|
|
116
|
+
try {
|
|
117
|
+
isSame = equal(entry.lastValue, nextValue);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (!firstError) firstError = err;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (!isSame) {
|
|
112
123
|
entry.lastValue = nextValue;
|
|
113
|
-
|
|
124
|
+
try {
|
|
125
|
+
entry.listener(nextValue);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (!firstError) firstError = err;
|
|
128
|
+
}
|
|
114
129
|
selNotifies++;
|
|
115
130
|
}
|
|
116
|
-
}
|
|
131
|
+
}
|
|
117
132
|
devTrack("store:notify:selector", { listeners: selNotifies });
|
|
133
|
+
if (firstError) throw firstError;
|
|
118
134
|
};
|
|
119
135
|
const subscribe = (listener) => {
|
|
120
136
|
listeners.add(listener);
|
|
@@ -135,11 +151,12 @@ function createStore(reducer, initialState) {
|
|
|
135
151
|
devTrack("store:sub:key:remove", { key: String(key), size: set.size });
|
|
136
152
|
};
|
|
137
153
|
};
|
|
138
|
-
const subscribeWithSelector = (selector, listener) => {
|
|
154
|
+
const subscribeWithSelector = (selector, listener, isEqual) => {
|
|
139
155
|
const entry = {
|
|
140
156
|
selector,
|
|
141
157
|
listener,
|
|
142
|
-
lastValue: selector(state)
|
|
158
|
+
lastValue: selector(state),
|
|
159
|
+
isEqual
|
|
143
160
|
};
|
|
144
161
|
selectorListeners.add(entry);
|
|
145
162
|
devTrack("store:sub:selector:add", { size: selectorListeners.size });
|
|
@@ -216,16 +233,16 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
216
233
|
children,
|
|
217
234
|
initialState: override
|
|
218
235
|
}) => {
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
storeRef.current = createStore(reducer, override ?? initialState);
|
|
236
|
+
const store = (0, import_react.useMemo)(() => {
|
|
237
|
+
const next = createStore(reducer, override ?? initialState);
|
|
222
238
|
devTrack2("scoped:store:create");
|
|
223
|
-
|
|
239
|
+
return next;
|
|
240
|
+
}, [reducer, override, initialState]);
|
|
224
241
|
(0, import_react.useEffect)(() => {
|
|
225
242
|
devTrack2("scoped:provider:mount");
|
|
226
243
|
return () => devTrack2("scoped:provider:unmount");
|
|
227
244
|
}, []);
|
|
228
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Context.Provider, { value:
|
|
245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Context.Provider, { value: store, children });
|
|
229
246
|
};
|
|
230
247
|
const useStore2 = () => {
|
|
231
248
|
const ctx = (0, import_react.useContext)(Context);
|
|
@@ -245,21 +262,36 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
245
262
|
function useSelector(selector, isEqual = shallowEqual) {
|
|
246
263
|
const ctx = (0, import_react.useContext)(Context);
|
|
247
264
|
if (!ctx) throw new Error("Store not found in context");
|
|
248
|
-
const state = (0, import_react.useSyncExternalStore)(
|
|
249
|
-
makeBatchedSubscribe(ctx.subscribe),
|
|
250
|
-
ctx.getState,
|
|
251
|
-
ctx.getState
|
|
252
|
-
);
|
|
253
265
|
const lastRef = (0, import_react.useRef)(null);
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
266
|
+
const getSnapshot = () => {
|
|
267
|
+
const nextSelected = selector(ctx.getState());
|
|
268
|
+
const last = lastRef.current;
|
|
269
|
+
if (last && isEqual(last.selected, nextSelected)) {
|
|
270
|
+
devTrack2("scoped:selector:cache-hit");
|
|
271
|
+
return last.selected;
|
|
272
|
+
}
|
|
273
|
+
devTrack2("scoped:selector:cache-miss");
|
|
274
|
+
lastRef.current = { selected: nextSelected };
|
|
275
|
+
return nextSelected;
|
|
276
|
+
};
|
|
277
|
+
const subscribe = (onChange) => {
|
|
278
|
+
devTrack2("scoped:selector:sub:add");
|
|
279
|
+
const unsubscribe = ctx.subscribeWithSelector(selector, (nextSelected) => {
|
|
280
|
+
const last = lastRef.current;
|
|
281
|
+
if (last && isEqual(last.selected, nextSelected)) {
|
|
282
|
+
devTrack2("scoped:selector:skip");
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
lastRef.current = { selected: nextSelected };
|
|
286
|
+
devTrack2("scoped:selector:notify");
|
|
287
|
+
enqueue(onChange);
|
|
288
|
+
}, isEqual);
|
|
289
|
+
return () => {
|
|
290
|
+
devTrack2("scoped:selector:sub:remove");
|
|
291
|
+
unsubscribe();
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
return (0, import_react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
263
295
|
}
|
|
264
296
|
return {
|
|
265
297
|
Context,
|
|
@@ -271,7 +303,7 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
271
303
|
}
|
|
272
304
|
|
|
273
305
|
// src/provider.tsx
|
|
274
|
-
var import_react2 =
|
|
306
|
+
var import_react2 = require("react");
|
|
275
307
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
276
308
|
var __DEV__2 = typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true;
|
|
277
309
|
function devTrack3(name, props) {
|
|
@@ -305,39 +337,21 @@ function StoreProvider({
|
|
|
305
337
|
}
|
|
306
338
|
function useStore() {
|
|
307
339
|
const store = useStoreInstance();
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
changed: changedKeys,
|
|
324
|
-
count: changedKeys.length
|
|
325
|
-
});
|
|
326
|
-
} catch {
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
prevRef.current = next;
|
|
330
|
-
setState(next);
|
|
331
|
-
} else {
|
|
332
|
-
devTrack3("store:react:no-op");
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
return () => {
|
|
336
|
-
devTrack3("store:react:unsubscribe");
|
|
337
|
-
unsubscribe();
|
|
338
|
-
};
|
|
339
|
-
}, [store]);
|
|
340
|
-
return state;
|
|
340
|
+
return (0, import_react2.useSyncExternalStore)(
|
|
341
|
+
(onStoreChange) => {
|
|
342
|
+
devTrack3("store:react:subscribe");
|
|
343
|
+
const unsubscribe = store.subscribe(() => {
|
|
344
|
+
devTrack3("store:react:notify");
|
|
345
|
+
onStoreChange();
|
|
346
|
+
});
|
|
347
|
+
return () => {
|
|
348
|
+
devTrack3("store:react:unsubscribe");
|
|
349
|
+
unsubscribe();
|
|
350
|
+
};
|
|
351
|
+
},
|
|
352
|
+
store.getState,
|
|
353
|
+
store.getState
|
|
354
|
+
);
|
|
341
355
|
}
|
|
342
356
|
function useDispatch() {
|
|
343
357
|
const store = useStoreInstance();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/create-scoped-store.tsx","../src/freeze.ts","../src/store.ts","../src/provider.tsx","../src/metadata-store.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./create-scoped-store.js\";\nexport * from \"./store.js\";\nexport * from \"./provider.js\";\nexport * from \"./metadata-store.js\";\n","export type Reducer<S, A> = (state: S, action: A) => S;\nexport type Listener = () => void;\nexport type Unsubscribe = () => void;\nexport const __noop = null;","import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect } from \"react\";\nimport type { IState, IAction, Store } from \"./store.js\";\nimport { createStore } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Local microtask-based batching (no react-dom dependency)\nconst _queue = new Set<() => void>();\nlet _queued = false;\nconst _schedule = typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn: () => void) => Promise.resolve().then(fn);\n\nfunction enqueue(fn: () => void) {\n _queue.add(fn);\n if (_queued) return;\n _queued = true;\n _schedule(() => {\n _queued = false;\n const fns = Array.from(_queue);\n _queue.clear();\n for (const f of fns) f();\n devTrack(\"scoped:batch:flush\", { size: fns.length });\n });\n}\n\nfunction makeBatchedSubscribe(subscribe: (l: () => void) => () => void) {\n return (onChange: () => void) => {\n devTrack(\"scoped:sub:add\");\n const wrapped = () => {\n devTrack(\"scoped:notify:enqueue\");\n enqueue(onChange);\n };\n const unsubscribe = subscribe(wrapped);\n return () => {\n devTrack(\"scoped:sub:remove\");\n unsubscribe();\n };\n };\n}\n\nfunction shallowEqual(a: any, b: any) {\n if (Object.is(a, b)) return true;\n if (\n typeof a !== \"object\" ||\n a === null ||\n typeof b !== \"object\" ||\n b === null\n )\n return false;\n const ak = Object.keys(a),\n bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (let i = 0; i < ak.length; i++) {\n const k = ak[i] as string;\n if (\n !Object.prototype.hasOwnProperty.call(b, k) ||\n !Object.is((a as any)[k], (b as any)[k])\n )\n return false;\n }\n return true;\n}\n\nexport function createScopedStoreContext<S extends IState, A extends IAction>(\n reducer: (state: S, action: A) => S,\n initialState: S\n) {\n const Context = createContext<Store<S, A> | null>(null);\n\n // Each Provider instance gets its own store.\n const Provider = ({\n children,\n initialState: override,\n }: {\n children: React.ReactNode;\n initialState?: S;\n }) => {\n const storeRef = useRef<Store<S, A> | null>(null);\n if (!storeRef.current) {\n storeRef.current = createStore(reducer, override ?? initialState);\n devTrack(\"scoped:store:create\");\n }\n\n useEffect(() => {\n devTrack(\"scoped:provider:mount\");\n return () => devTrack(\"scoped:provider:unmount\");\n }, []);\n\n return <Context.Provider value={storeRef.current}>{children}</Context.Provider>;\n };\n\n const useStore = (): S => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n devTrack(\"scoped:useStore\");\n return useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n };\n\n const useDispatch = (): ((action: A) => void) => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Dispatch not found in context\");\n return useCallback((action: A) => ctx.dispatch(action), [ctx]);\n };\n\n function useSelector<T>(\n selector: (state: S) => T,\n isEqual: (a: T, b: T) => boolean = shallowEqual\n ): T {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n\n // Subscribe to the raw state snapshot (stable reference until a dispatch)\n const state = useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n\n // Cache the selected slice per state snapshot to avoid returning fresh objects during render\n const lastRef = useRef<{ state: S; selected: T } | null>(null);\n const last = lastRef.current;\n const nextSelected = selector(state);\n\n if (last && last.state === state && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:cache-hit\");\n return last.selected; // return cached reference to satisfy getSnapshot caching\n }\n\n devTrack(\"scoped:selector:cache-miss\");\n lastRef.current = { state, selected: nextSelected };\n return nextSelected;\n }\n\n return {\n Context,\n Provider,\n useStore,\n useDispatch,\n useSelector,\n };\n}\n","// freeze.ts\nexport function deepFreeze<T>(obj: T, seen = new WeakSet<object>()): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const o = obj as unknown as object;\n if (seen.has(o)) return obj;\n seen.add(o);\n\n // Freeze children first\n for (const key of Object.getOwnPropertyNames(o)) {\n // @ts-expect-error index access\n const val = (o as any)[key];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n // Also handle symbols (rare but safe)\n for (const sym of Object.getOwnPropertySymbols(o)) {\n // @ts-expect-error index access\n const val = (o as any)[sym];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n\n return Object.freeze(obj);\n}\n","import type { Reducer, Listener } from \"./types.js\";\nimport { deepFreeze } from \"./freeze.js\";\n\nconst DEV =\n typeof import.meta !== \"undefined\"\n ? (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV\n : process.env.NODE_ENV !== \"production\";\n\n// Lightweight DEV-only tracker\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!DEV) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Allow narrower parameter types for callbacks without fighting variance\ntype BivariantListener<T> = {\n bivarianceHack(value: T): void;\n}[\"bivarianceHack\"];\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface IState {}\nexport interface IAction {\n type: string;\n}\n\nexport interface Store<S extends IState, A extends IAction> {\n getState(): S;\n dispatch(action: A): void;\n /**\n * Subscribe to all state changes.\n */\n subscribe(listener: Listener): () => void;\n /**\n * Subscribe to changes of a specific key in the state.\n */\n subscribeToKey<K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ): () => void;\n /**\n * Subscribe to changes in a selected value from the state.\n */\n subscribeWithSelector<T>(\n selector: (state: S) => T,\n listener: (selected: T) => void\n ): () => void;\n}\n\nexport function createStore<S extends IState, A extends IAction>(\n reducer: Reducer<S, A>,\n initialState: S\n): Store<S, A> {\n let state: S = DEV ? deepFreeze(initialState) : initialState;\n const listeners = new Set<Listener>();\n const keyListeners = new Map<keyof S, Set<BivariantListener<S[keyof S]>>>();\n\n interface SelectorEntry<T> {\n selector: (state: S) => T;\n listener: BivariantListener<T>;\n lastValue: T;\n }\n const selectorListeners = new Set<SelectorEntry<unknown>>();\n\n const getState = () => state;\n\n const dispatch = (action: A) => {\n const prevState = state;\n const nextState = reducer(state, action);\n\n if (DEV) deepFreeze(nextState);\n\n // Track the inbound action\n devTrack(\"store:dispatch\", { type: action?.type });\n\n // Distinct-until-changed: if the reducer returns the same reference,\n // skip all notifications (prevents unnecessary re-renders).\n if (Object.is(prevState, nextState)) {\n state = nextState; // keep any identity guarantees from reducer\n devTrack(\"store:no-op\", { type: action?.type });\n return;\n }\n\n state = nextState;\n\n // Compute changed keys (shallow) for diagnostics\n let changedKeys: (keyof S)[] | undefined;\n if (DEV) {\n changedKeys = Object.keys(nextState as Record<string, unknown>)\n .filter((k) => !Object.is((prevState as any)[k], (nextState as any)[k])) as (keyof S)[];\n devTrack(\"store:state-changed\", { type: action?.type, changedKeys });\n }\n\n // Notify global listeners (iterate over a snapshot so unsubscribe during\n // notify does not skip the next listener)\n const globalSnapshot = [...listeners];\n devTrack(\"store:notify:all\", { listeners: globalSnapshot.length });\n for (const listener of globalSnapshot) listener();\n\n // Notify key listeners only when that key actually changed (Object.is)\n for (const [key, set] of keyListeners.entries()) {\n if (!Object.is(prevState[key], state[key])) {\n devTrack(\"store:notify:key\", { key: String(key), listeners: set.size });\n for (const listener of [...set]) listener(state[key]);\n }\n }\n\n // Notify selector listeners only when selected value changed (Object.is)\n let selNotifies = 0;\n selectorListeners.forEach((entry) => {\n const nextValue = (entry.selector as (s: S) => unknown)(state);\n if (!Object.is(entry.lastValue, nextValue)) {\n entry.lastValue = nextValue as unknown;\n (entry.listener as (v: unknown) => void)(nextValue);\n selNotifies++;\n }\n });\n devTrack(\"store:notify:selector\", { listeners: selNotifies });\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n devTrack(\"store:sub:all:add\", { size: listeners.size });\n return () => {\n listeners.delete(listener);\n devTrack(\"store:sub:all:remove\", { size: listeners.size });\n };\n };\n\n const subscribeToKey = <K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ) => {\n const set =\n keyListeners.get(key) ?? new Set<BivariantListener<S[keyof S]>>();\n set.add(listener as unknown as BivariantListener<S[keyof S]>);\n keyListeners.set(key, set);\n devTrack(\"store:sub:key:add\", { key: String(key), size: set.size });\n return () => {\n set.delete(listener as unknown as BivariantListener<S[keyof S]>);\n if (set.size === 0) keyListeners.delete(key);\n devTrack(\"store:sub:key:remove\", { key: String(key), size: set.size });\n };\n };\n\n const subscribeWithSelector = <T>(\n selector: (state: S) => T,\n listener: (selected: T) => void\n ) => {\n const entry: SelectorEntry<T> = {\n selector,\n listener: listener as BivariantListener<T>,\n lastValue: selector(state),\n };\n selectorListeners.add(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:add\", { size: selectorListeners.size });\n return () => {\n selectorListeners.delete(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:remove\", { size: selectorListeners.size });\n };\n };\n\n return {\n getState,\n dispatch,\n subscribe,\n subscribeToKey,\n subscribeWithSelector,\n };\n}\n","import React, { createContext, useContext, useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Store, IState, IAction } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\nconst StoreContext = createContext<Store<IState, IAction> | undefined>(undefined);\n\nfunction useStoreInstance<S extends IState, A extends IAction>(): Store<S, A> {\n const store = useContext(StoreContext) as Store<S, A> | undefined;\n if (!store) {\n devTrack(\"store:provider:missing\");\n throw new Error(\n \"StoreProvider is missing in the React tree. Wrap your app with <StoreProvider store={...}>.\"\n );\n }\n return store;\n}\n\ninterface StoreProviderProps<S extends IState, A extends IAction> {\n store: Store<S, A>;\n children: ReactNode;\n}\n\nexport function StoreProvider<S extends IState, A extends IAction>({\n store,\n children,\n}: StoreProviderProps<S, A>) {\n useEffect(() => {\n devTrack(\"store:provider:mount\", { hasStore: !!store });\n return () => devTrack(\"store:provider:unmount\");\n }, [store]);\n return (\n <StoreContext.Provider value={store as unknown as Store<IState, IAction>}>\n {children}\n </StoreContext.Provider>\n );\n}\n\nexport function useStore<S extends IState>(): S {\n const store = useStoreInstance<S, IAction>();\n const [state, setState] = useState<S>(() => store.getState());\n const prevRef = React.useRef<S>(state);\n\n useEffect(() => {\n devTrack(\"store:react:subscribe\");\n const unsubscribe = store.subscribe(() => {\n const next = store.getState();\n if (!Object.is(prevRef.current, next)) {\n if (__DEV__) {\n try {\n const prev = prevRef.current as unknown as Record<string, unknown>;\n const cur = next as unknown as Record<string, unknown>;\n const changedKeys = Array.from(\n new Set([...Object.keys(prev || {}), ...Object.keys(cur || {})])\n ).filter((k) => !Object.is(prev?.[k], cur?.[k]));\n devTrack(\"store:react:update\", {\n changed: changedKeys,\n count: changedKeys.length,\n });\n } catch {}\n }\n prevRef.current = next;\n setState(next);\n } else {\n devTrack(\"store:react:no-op\");\n }\n });\n return () => {\n devTrack(\"store:react:unsubscribe\");\n unsubscribe();\n };\n }, [store]);\n\n return state;\n}\n\nexport function useDispatch<A extends IAction>(): Store<IState, A>[\"dispatch\"] {\n const store = useStoreInstance<IState, A>();\n // Return the store's dispatch directly; consumers can call dispatch(action).\n return store.dispatch as Store<IState, A>[\"dispatch\"];\n}\n","// metadata-store.ts\nexport class MetadataStore<T extends object, Meta extends object> {\n private readonly symbol: symbol;\n\n constructor(description: string) {\n this.symbol = Symbol(description);\n }\n\n set(target: T, meta: Meta) {\n Object.defineProperty(target, this.symbol as PropertyKey, {\n value: meta,\n writable: false,\n enumerable: false,\n });\n }\n\n get(target: T): Meta | undefined {\n return (target as Record<PropertyKey, Meta>)[this.symbol as PropertyKey];\n }\n\n has(target: T): boolean {\n return (this.symbol as PropertyKey) in target;\n }\n}\n"],"mappings":"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","names":["devTrack","useStore","useDispatch","import_react","import_jsx_runtime","__DEV__","devTrack","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/create-scoped-store.tsx","../src/freeze.ts","../src/store.ts","../src/provider.tsx","../src/metadata-store.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./create-scoped-store.js\";\nexport * from \"./store.js\";\nexport * from \"./provider.js\";\nexport * from \"./metadata-store.js\";\n","export type Reducer<S, A> = (state: S, action: A) => S;\nexport type Listener = () => void;\nexport type Unsubscribe = () => void;\nexport const __noop = null;","import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect, useMemo } from \"react\";\nimport type { IState, IAction, Store } from \"./store.js\";\nimport { createStore } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Local microtask-based batching (no react-dom dependency)\nconst _queue = new Set<() => void>();\nlet _queued = false;\nconst _schedule = typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn: () => void) => Promise.resolve().then(fn);\n\nfunction enqueue(fn: () => void) {\n _queue.add(fn);\n if (_queued) return;\n _queued = true;\n _schedule(() => {\n _queued = false;\n const fns = Array.from(_queue);\n _queue.clear();\n for (const f of fns) f();\n devTrack(\"scoped:batch:flush\", { size: fns.length });\n });\n}\n\nfunction makeBatchedSubscribe(subscribe: (l: () => void) => () => void) {\n return (onChange: () => void) => {\n devTrack(\"scoped:sub:add\");\n const wrapped = () => {\n devTrack(\"scoped:notify:enqueue\");\n enqueue(onChange);\n };\n const unsubscribe = subscribe(wrapped);\n return () => {\n devTrack(\"scoped:sub:remove\");\n unsubscribe();\n };\n };\n}\n\nfunction shallowEqual(a: any, b: any) {\n if (Object.is(a, b)) return true;\n if (\n typeof a !== \"object\" ||\n a === null ||\n typeof b !== \"object\" ||\n b === null\n )\n return false;\n const ak = Object.keys(a),\n bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (let i = 0; i < ak.length; i++) {\n const k = ak[i] as string;\n if (\n !Object.prototype.hasOwnProperty.call(b, k) ||\n !Object.is((a as any)[k], (b as any)[k])\n )\n return false;\n }\n return true;\n}\n\nexport function createScopedStoreContext<S extends IState, A extends IAction>(\n reducer: (state: S, action: A) => S,\n initialState: S\n) {\n const Context = createContext<Store<S, A> | null>(null);\n\n // Each Provider instance gets its own store.\n const Provider = ({\n children,\n initialState: override,\n }: {\n children: React.ReactNode;\n initialState?: S;\n }) => {\n const store = useMemo(() => {\n const next = createStore(reducer, override ?? initialState);\n devTrack(\"scoped:store:create\");\n return next;\n }, [reducer, override, initialState]);\n\n useEffect(() => {\n devTrack(\"scoped:provider:mount\");\n return () => devTrack(\"scoped:provider:unmount\");\n }, []);\n\n return <Context.Provider value={store}>{children}</Context.Provider>;\n };\n\n const useStore = (): S => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n devTrack(\"scoped:useStore\");\n return useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n };\n\n const useDispatch = (): ((action: A) => void) => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Dispatch not found in context\");\n return useCallback((action: A) => ctx.dispatch(action), [ctx]);\n };\n\n function useSelector<T>(\n selector: (state: S) => T,\n isEqual: (a: T, b: T) => boolean = shallowEqual\n ): T {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n\n const lastRef = useRef<{ selected: T } | null>(null);\n\n const getSnapshot = () => {\n const nextSelected = selector(ctx.getState());\n const last = lastRef.current;\n if (last && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:cache-hit\");\n return last.selected;\n }\n devTrack(\"scoped:selector:cache-miss\");\n lastRef.current = { selected: nextSelected };\n return nextSelected;\n };\n\n const subscribe = (onChange: () => void) => {\n devTrack(\"scoped:selector:sub:add\");\n const unsubscribe = ctx.subscribeWithSelector(selector, (nextSelected) => {\n const last = lastRef.current;\n if (last && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:skip\");\n return;\n }\n lastRef.current = { selected: nextSelected };\n devTrack(\"scoped:selector:notify\");\n enqueue(onChange);\n }, isEqual);\n return () => {\n devTrack(\"scoped:selector:sub:remove\");\n unsubscribe();\n };\n };\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n return {\n Context,\n Provider,\n useStore,\n useDispatch,\n useSelector,\n };\n}\n","// freeze.ts\nexport function deepFreeze<T>(obj: T, seen = new WeakSet<object>()): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const o = obj as unknown as object;\n if (seen.has(o)) return obj;\n seen.add(o);\n\n // Freeze children first\n for (const key of Object.getOwnPropertyNames(o)) {\n // @ts-expect-error index access\n const val = (o as any)[key];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n // Also handle symbols (rare but safe)\n for (const sym of Object.getOwnPropertySymbols(o)) {\n // @ts-expect-error index access\n const val = (o as any)[sym];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n\n return Object.freeze(obj);\n}\n","import type { Reducer, Listener } from \"./types.js\";\nimport { deepFreeze } from \"./freeze.js\";\n\nconst DEV =\n typeof import.meta !== \"undefined\"\n ? (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV\n : process.env.NODE_ENV !== \"production\";\n\n// Lightweight DEV-only tracker\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!DEV) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Allow narrower parameter types for callbacks without fighting variance\ntype BivariantListener<T> = {\n bivarianceHack(value: T): void;\n}[\"bivarianceHack\"];\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface IState {}\nexport interface IAction {\n type: string;\n}\n\nexport interface Store<S extends IState, A extends IAction> {\n getState(): S;\n dispatch(action: A): void;\n /**\n * Subscribe to all state changes.\n */\n subscribe(listener: Listener): () => void;\n /**\n * Subscribe to changes of a specific key in the state.\n */\n subscribeToKey<K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ): () => void;\n /**\n * Subscribe to changes in a selected value from the state.\n */\n subscribeWithSelector<T>(\n selector: (state: S) => T,\n listener: (selected: T) => void,\n isEqual?: (a: T, b: T) => boolean\n ): () => void;\n}\n\nexport function createStore<S extends IState, A extends IAction>(\n reducer: Reducer<S, A>,\n initialState: S\n): Store<S, A> {\n let state: S = DEV ? deepFreeze(initialState) : initialState;\n const listeners = new Set<Listener>();\n const keyListeners = new Map<keyof S, Set<BivariantListener<S[keyof S]>>>();\n\n interface SelectorEntry<T> {\n selector: (state: S) => T;\n listener: BivariantListener<T>;\n lastValue: T;\n isEqual?: (a: T, b: T) => boolean;\n }\n const selectorListeners = new Set<SelectorEntry<unknown>>();\n\n const getState = () => state;\n\n const dispatch = (action: A) => {\n const prevState = state;\n const nextState = reducer(state, action);\n\n if (DEV) deepFreeze(nextState);\n\n // Track the inbound action\n devTrack(\"store:dispatch\", { type: action?.type });\n\n // Distinct-until-changed: if the reducer returns the same reference,\n // skip all notifications (prevents unnecessary re-renders).\n if (Object.is(prevState, nextState)) {\n state = nextState; // keep any identity guarantees from reducer\n devTrack(\"store:no-op\", { type: action?.type });\n return;\n }\n\n state = nextState;\n\n // Compute changed keys (shallow) for diagnostics\n let changedKeys: (keyof S)[] | undefined;\n if (DEV) {\n changedKeys = Object.keys(nextState as Record<string, unknown>)\n .filter((k) => !Object.is((prevState as any)[k], (nextState as any)[k])) as (keyof S)[];\n devTrack(\"store:state-changed\", { type: action?.type, changedKeys });\n }\n\n // Notify global listeners (iterate over a snapshot so unsubscribe during\n // notify does not skip the next listener)\n const globalSnapshot = [...listeners];\n devTrack(\"store:notify:all\", { listeners: globalSnapshot.length });\n let firstError: unknown;\n for (const listener of globalSnapshot) {\n try {\n listener();\n } catch (err) {\n if (!firstError) firstError = err;\n }\n }\n\n // Notify key listeners only when that key actually changed (Object.is)\n for (const [key, set] of keyListeners.entries()) {\n if (!Object.is(prevState[key], state[key])) {\n devTrack(\"store:notify:key\", { key: String(key), listeners: set.size });\n for (const listener of [...set]) {\n try {\n listener(state[key]);\n } catch (err) {\n if (!firstError) firstError = err;\n }\n }\n }\n }\n\n // Notify selector listeners only when selected value changed (Object.is)\n let selNotifies = 0;\n for (const entry of [...selectorListeners]) {\n const nextValue = (entry.selector as (s: S) => unknown)(state);\n const equal = (entry.isEqual as ((a: unknown, b: unknown) => boolean) | undefined) ?? Object.is;\n let isSame = false;\n try {\n isSame = equal(entry.lastValue, nextValue);\n } catch (err) {\n if (!firstError) firstError = err;\n continue;\n }\n if (!isSame) {\n entry.lastValue = nextValue as unknown;\n try {\n (entry.listener as (v: unknown) => void)(nextValue);\n } catch (err) {\n if (!firstError) firstError = err;\n }\n selNotifies++;\n }\n }\n devTrack(\"store:notify:selector\", { listeners: selNotifies });\n if (firstError) throw firstError;\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n devTrack(\"store:sub:all:add\", { size: listeners.size });\n return () => {\n listeners.delete(listener);\n devTrack(\"store:sub:all:remove\", { size: listeners.size });\n };\n };\n\n const subscribeToKey = <K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ) => {\n const set =\n keyListeners.get(key) ?? new Set<BivariantListener<S[keyof S]>>();\n set.add(listener as unknown as BivariantListener<S[keyof S]>);\n keyListeners.set(key, set);\n devTrack(\"store:sub:key:add\", { key: String(key), size: set.size });\n return () => {\n set.delete(listener as unknown as BivariantListener<S[keyof S]>);\n if (set.size === 0) keyListeners.delete(key);\n devTrack(\"store:sub:key:remove\", { key: String(key), size: set.size });\n };\n };\n\n const subscribeWithSelector = <T>(\n selector: (state: S) => T,\n listener: (selected: T) => void,\n isEqual?: (a: T, b: T) => boolean\n ) => {\n const entry: SelectorEntry<T> = {\n selector,\n listener: listener as BivariantListener<T>,\n lastValue: selector(state),\n isEqual,\n };\n selectorListeners.add(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:add\", { size: selectorListeners.size });\n return () => {\n selectorListeners.delete(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:remove\", { size: selectorListeners.size });\n };\n };\n\n return {\n getState,\n dispatch,\n subscribe,\n subscribeToKey,\n subscribeWithSelector,\n };\n}\n","import React, { createContext, useContext, useEffect, useSyncExternalStore } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Store, IState, IAction } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\nconst StoreContext = createContext<Store<IState, IAction> | undefined>(undefined);\n\nfunction useStoreInstance<S extends IState, A extends IAction>(): Store<S, A> {\n const store = useContext(StoreContext) as Store<S, A> | undefined;\n if (!store) {\n devTrack(\"store:provider:missing\");\n throw new Error(\n \"StoreProvider is missing in the React tree. Wrap your app with <StoreProvider store={...}>.\"\n );\n }\n return store;\n}\n\ninterface StoreProviderProps<S extends IState, A extends IAction> {\n store: Store<S, A>;\n children: ReactNode;\n}\n\nexport function StoreProvider<S extends IState, A extends IAction>({\n store,\n children,\n}: StoreProviderProps<S, A>) {\n useEffect(() => {\n devTrack(\"store:provider:mount\", { hasStore: !!store });\n return () => devTrack(\"store:provider:unmount\");\n }, [store]);\n return (\n <StoreContext.Provider value={store as unknown as Store<IState, IAction>}>\n {children}\n </StoreContext.Provider>\n );\n}\n\nexport function useStore<S extends IState>(): S {\n const store = useStoreInstance<S, IAction>();\n return useSyncExternalStore(\n (onStoreChange) => {\n devTrack(\"store:react:subscribe\");\n const unsubscribe = store.subscribe(() => {\n devTrack(\"store:react:notify\");\n onStoreChange();\n });\n return () => {\n devTrack(\"store:react:unsubscribe\");\n unsubscribe();\n };\n },\n store.getState,\n store.getState\n );\n}\n\nexport function useDispatch<A extends IAction>(): Store<IState, A>[\"dispatch\"] {\n const store = useStoreInstance<IState, A>();\n // Return the store's dispatch directly; consumers can call dispatch(action).\n return store.dispatch as Store<IState, A>[\"dispatch\"];\n}\n","// metadata-store.ts\nexport class MetadataStore<T extends object, Meta extends object> {\n private readonly symbol: symbol;\n\n constructor(description: string) {\n this.symbol = Symbol(description);\n }\n\n set(target: T, meta: Meta) {\n Object.defineProperty(target, this.symbol as PropertyKey, {\n value: meta,\n writable: false,\n enumerable: false,\n });\n }\n\n get(target: T): Meta | undefined {\n return (target as Record<PropertyKey, Meta>)[this.symbol as PropertyKey];\n }\n\n has(target: T): boolean {\n return (this.symbol as PropertyKey) in target;\n }\n}\n"],"mappings":"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","names":["devTrack","useStore","useDispatch","import_react","import_jsx_runtime","__DEV__","devTrack"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -26,7 +26,7 @@ interface Store<S extends IState, A extends IAction> {
|
|
|
26
26
|
/**
|
|
27
27
|
* Subscribe to changes in a selected value from the state.
|
|
28
28
|
*/
|
|
29
|
-
subscribeWithSelector<T>(selector: (state: S) => T, listener: (selected: T) => void): () => void;
|
|
29
|
+
subscribeWithSelector<T>(selector: (state: S) => T, listener: (selected: T) => void, isEqual?: (a: T, b: T) => boolean): () => void;
|
|
30
30
|
}
|
|
31
31
|
declare function createStore<S extends IState, A extends IAction>(reducer: Reducer<S, A>, initialState: S): Store<S, A>;
|
|
32
32
|
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ interface Store<S extends IState, A extends IAction> {
|
|
|
26
26
|
/**
|
|
27
27
|
* Subscribe to changes in a selected value from the state.
|
|
28
28
|
*/
|
|
29
|
-
subscribeWithSelector<T>(selector: (state: S) => T, listener: (selected: T) => void): () => void;
|
|
29
|
+
subscribeWithSelector<T>(selector: (state: S) => T, listener: (selected: T) => void, isEqual?: (a: T, b: T) => boolean): () => void;
|
|
30
30
|
}
|
|
31
31
|
declare function createStore<S extends IState, A extends IAction>(reducer: Reducer<S, A>, initialState: S): Store<S, A>;
|
|
32
32
|
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var __noop = null;
|
|
3
3
|
|
|
4
4
|
// src/create-scoped-store.tsx
|
|
5
|
-
import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect } from "react";
|
|
5
|
+
import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect, useMemo } from "react";
|
|
6
6
|
|
|
7
7
|
// src/freeze.ts
|
|
8
8
|
function deepFreeze(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
@@ -55,23 +55,49 @@ function createStore(reducer, initialState) {
|
|
|
55
55
|
}
|
|
56
56
|
const globalSnapshot = [...listeners];
|
|
57
57
|
devTrack("store:notify:all", { listeners: globalSnapshot.length });
|
|
58
|
-
|
|
58
|
+
let firstError;
|
|
59
|
+
for (const listener of globalSnapshot) {
|
|
60
|
+
try {
|
|
61
|
+
listener();
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (!firstError) firstError = err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
59
66
|
for (const [key, set] of keyListeners.entries()) {
|
|
60
67
|
if (!Object.is(prevState[key], state[key])) {
|
|
61
68
|
devTrack("store:notify:key", { key: String(key), listeners: set.size });
|
|
62
|
-
for (const listener of [...set])
|
|
69
|
+
for (const listener of [...set]) {
|
|
70
|
+
try {
|
|
71
|
+
listener(state[key]);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
if (!firstError) firstError = err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
78
|
let selNotifies = 0;
|
|
66
|
-
|
|
79
|
+
for (const entry of [...selectorListeners]) {
|
|
67
80
|
const nextValue = entry.selector(state);
|
|
68
|
-
|
|
81
|
+
const equal = entry.isEqual ?? Object.is;
|
|
82
|
+
let isSame = false;
|
|
83
|
+
try {
|
|
84
|
+
isSame = equal(entry.lastValue, nextValue);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (!firstError) firstError = err;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (!isSame) {
|
|
69
90
|
entry.lastValue = nextValue;
|
|
70
|
-
|
|
91
|
+
try {
|
|
92
|
+
entry.listener(nextValue);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
if (!firstError) firstError = err;
|
|
95
|
+
}
|
|
71
96
|
selNotifies++;
|
|
72
97
|
}
|
|
73
|
-
}
|
|
98
|
+
}
|
|
74
99
|
devTrack("store:notify:selector", { listeners: selNotifies });
|
|
100
|
+
if (firstError) throw firstError;
|
|
75
101
|
};
|
|
76
102
|
const subscribe = (listener) => {
|
|
77
103
|
listeners.add(listener);
|
|
@@ -92,11 +118,12 @@ function createStore(reducer, initialState) {
|
|
|
92
118
|
devTrack("store:sub:key:remove", { key: String(key), size: set.size });
|
|
93
119
|
};
|
|
94
120
|
};
|
|
95
|
-
const subscribeWithSelector = (selector, listener) => {
|
|
121
|
+
const subscribeWithSelector = (selector, listener, isEqual) => {
|
|
96
122
|
const entry = {
|
|
97
123
|
selector,
|
|
98
124
|
listener,
|
|
99
|
-
lastValue: selector(state)
|
|
125
|
+
lastValue: selector(state),
|
|
126
|
+
isEqual
|
|
100
127
|
};
|
|
101
128
|
selectorListeners.add(entry);
|
|
102
129
|
devTrack("store:sub:selector:add", { size: selectorListeners.size });
|
|
@@ -173,16 +200,16 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
173
200
|
children,
|
|
174
201
|
initialState: override
|
|
175
202
|
}) => {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
storeRef.current = createStore(reducer, override ?? initialState);
|
|
203
|
+
const store = useMemo(() => {
|
|
204
|
+
const next = createStore(reducer, override ?? initialState);
|
|
179
205
|
devTrack2("scoped:store:create");
|
|
180
|
-
|
|
206
|
+
return next;
|
|
207
|
+
}, [reducer, override, initialState]);
|
|
181
208
|
useEffect(() => {
|
|
182
209
|
devTrack2("scoped:provider:mount");
|
|
183
210
|
return () => devTrack2("scoped:provider:unmount");
|
|
184
211
|
}, []);
|
|
185
|
-
return /* @__PURE__ */ jsx(Context.Provider, { value:
|
|
212
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value: store, children });
|
|
186
213
|
};
|
|
187
214
|
const useStore2 = () => {
|
|
188
215
|
const ctx = useContext(Context);
|
|
@@ -202,21 +229,36 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
202
229
|
function useSelector(selector, isEqual = shallowEqual) {
|
|
203
230
|
const ctx = useContext(Context);
|
|
204
231
|
if (!ctx) throw new Error("Store not found in context");
|
|
205
|
-
const state = useSyncExternalStore(
|
|
206
|
-
makeBatchedSubscribe(ctx.subscribe),
|
|
207
|
-
ctx.getState,
|
|
208
|
-
ctx.getState
|
|
209
|
-
);
|
|
210
232
|
const lastRef = useRef(null);
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
233
|
+
const getSnapshot = () => {
|
|
234
|
+
const nextSelected = selector(ctx.getState());
|
|
235
|
+
const last = lastRef.current;
|
|
236
|
+
if (last && isEqual(last.selected, nextSelected)) {
|
|
237
|
+
devTrack2("scoped:selector:cache-hit");
|
|
238
|
+
return last.selected;
|
|
239
|
+
}
|
|
240
|
+
devTrack2("scoped:selector:cache-miss");
|
|
241
|
+
lastRef.current = { selected: nextSelected };
|
|
242
|
+
return nextSelected;
|
|
243
|
+
};
|
|
244
|
+
const subscribe = (onChange) => {
|
|
245
|
+
devTrack2("scoped:selector:sub:add");
|
|
246
|
+
const unsubscribe = ctx.subscribeWithSelector(selector, (nextSelected) => {
|
|
247
|
+
const last = lastRef.current;
|
|
248
|
+
if (last && isEqual(last.selected, nextSelected)) {
|
|
249
|
+
devTrack2("scoped:selector:skip");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
lastRef.current = { selected: nextSelected };
|
|
253
|
+
devTrack2("scoped:selector:notify");
|
|
254
|
+
enqueue(onChange);
|
|
255
|
+
}, isEqual);
|
|
256
|
+
return () => {
|
|
257
|
+
devTrack2("scoped:selector:sub:remove");
|
|
258
|
+
unsubscribe();
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
220
262
|
}
|
|
221
263
|
return {
|
|
222
264
|
Context,
|
|
@@ -228,7 +270,7 @@ function createScopedStoreContext(reducer, initialState) {
|
|
|
228
270
|
}
|
|
229
271
|
|
|
230
272
|
// src/provider.tsx
|
|
231
|
-
import
|
|
273
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
232
274
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
233
275
|
var __DEV__2 = typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true;
|
|
234
276
|
function devTrack3(name, props) {
|
|
@@ -262,39 +304,21 @@ function StoreProvider({
|
|
|
262
304
|
}
|
|
263
305
|
function useStore() {
|
|
264
306
|
const store = useStoreInstance();
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
changed: changedKeys,
|
|
281
|
-
count: changedKeys.length
|
|
282
|
-
});
|
|
283
|
-
} catch {
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
prevRef.current = next;
|
|
287
|
-
setState(next);
|
|
288
|
-
} else {
|
|
289
|
-
devTrack3("store:react:no-op");
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
return () => {
|
|
293
|
-
devTrack3("store:react:unsubscribe");
|
|
294
|
-
unsubscribe();
|
|
295
|
-
};
|
|
296
|
-
}, [store]);
|
|
297
|
-
return state;
|
|
307
|
+
return useSyncExternalStore2(
|
|
308
|
+
(onStoreChange) => {
|
|
309
|
+
devTrack3("store:react:subscribe");
|
|
310
|
+
const unsubscribe = store.subscribe(() => {
|
|
311
|
+
devTrack3("store:react:notify");
|
|
312
|
+
onStoreChange();
|
|
313
|
+
});
|
|
314
|
+
return () => {
|
|
315
|
+
devTrack3("store:react:unsubscribe");
|
|
316
|
+
unsubscribe();
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
store.getState,
|
|
320
|
+
store.getState
|
|
321
|
+
);
|
|
298
322
|
}
|
|
299
323
|
function useDispatch() {
|
|
300
324
|
const store = useStoreInstance();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/create-scoped-store.tsx","../src/freeze.ts","../src/store.ts","../src/provider.tsx","../src/metadata-store.ts"],"sourcesContent":["export type Reducer<S, A> = (state: S, action: A) => S;\nexport type Listener = () => void;\nexport type Unsubscribe = () => void;\nexport const __noop = null;","import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect } from \"react\";\nimport type { IState, IAction, Store } from \"./store.js\";\nimport { createStore } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Local microtask-based batching (no react-dom dependency)\nconst _queue = new Set<() => void>();\nlet _queued = false;\nconst _schedule = typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn: () => void) => Promise.resolve().then(fn);\n\nfunction enqueue(fn: () => void) {\n _queue.add(fn);\n if (_queued) return;\n _queued = true;\n _schedule(() => {\n _queued = false;\n const fns = Array.from(_queue);\n _queue.clear();\n for (const f of fns) f();\n devTrack(\"scoped:batch:flush\", { size: fns.length });\n });\n}\n\nfunction makeBatchedSubscribe(subscribe: (l: () => void) => () => void) {\n return (onChange: () => void) => {\n devTrack(\"scoped:sub:add\");\n const wrapped = () => {\n devTrack(\"scoped:notify:enqueue\");\n enqueue(onChange);\n };\n const unsubscribe = subscribe(wrapped);\n return () => {\n devTrack(\"scoped:sub:remove\");\n unsubscribe();\n };\n };\n}\n\nfunction shallowEqual(a: any, b: any) {\n if (Object.is(a, b)) return true;\n if (\n typeof a !== \"object\" ||\n a === null ||\n typeof b !== \"object\" ||\n b === null\n )\n return false;\n const ak = Object.keys(a),\n bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (let i = 0; i < ak.length; i++) {\n const k = ak[i] as string;\n if (\n !Object.prototype.hasOwnProperty.call(b, k) ||\n !Object.is((a as any)[k], (b as any)[k])\n )\n return false;\n }\n return true;\n}\n\nexport function createScopedStoreContext<S extends IState, A extends IAction>(\n reducer: (state: S, action: A) => S,\n initialState: S\n) {\n const Context = createContext<Store<S, A> | null>(null);\n\n // Each Provider instance gets its own store.\n const Provider = ({\n children,\n initialState: override,\n }: {\n children: React.ReactNode;\n initialState?: S;\n }) => {\n const storeRef = useRef<Store<S, A> | null>(null);\n if (!storeRef.current) {\n storeRef.current = createStore(reducer, override ?? initialState);\n devTrack(\"scoped:store:create\");\n }\n\n useEffect(() => {\n devTrack(\"scoped:provider:mount\");\n return () => devTrack(\"scoped:provider:unmount\");\n }, []);\n\n return <Context.Provider value={storeRef.current}>{children}</Context.Provider>;\n };\n\n const useStore = (): S => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n devTrack(\"scoped:useStore\");\n return useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n };\n\n const useDispatch = (): ((action: A) => void) => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Dispatch not found in context\");\n return useCallback((action: A) => ctx.dispatch(action), [ctx]);\n };\n\n function useSelector<T>(\n selector: (state: S) => T,\n isEqual: (a: T, b: T) => boolean = shallowEqual\n ): T {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n\n // Subscribe to the raw state snapshot (stable reference until a dispatch)\n const state = useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n\n // Cache the selected slice per state snapshot to avoid returning fresh objects during render\n const lastRef = useRef<{ state: S; selected: T } | null>(null);\n const last = lastRef.current;\n const nextSelected = selector(state);\n\n if (last && last.state === state && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:cache-hit\");\n return last.selected; // return cached reference to satisfy getSnapshot caching\n }\n\n devTrack(\"scoped:selector:cache-miss\");\n lastRef.current = { state, selected: nextSelected };\n return nextSelected;\n }\n\n return {\n Context,\n Provider,\n useStore,\n useDispatch,\n useSelector,\n };\n}\n","// freeze.ts\nexport function deepFreeze<T>(obj: T, seen = new WeakSet<object>()): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const o = obj as unknown as object;\n if (seen.has(o)) return obj;\n seen.add(o);\n\n // Freeze children first\n for (const key of Object.getOwnPropertyNames(o)) {\n // @ts-expect-error index access\n const val = (o as any)[key];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n // Also handle symbols (rare but safe)\n for (const sym of Object.getOwnPropertySymbols(o)) {\n // @ts-expect-error index access\n const val = (o as any)[sym];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n\n return Object.freeze(obj);\n}\n","import type { Reducer, Listener } from \"./types.js\";\nimport { deepFreeze } from \"./freeze.js\";\n\nconst DEV =\n typeof import.meta !== \"undefined\"\n ? (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV\n : process.env.NODE_ENV !== \"production\";\n\n// Lightweight DEV-only tracker\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!DEV) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Allow narrower parameter types for callbacks without fighting variance\ntype BivariantListener<T> = {\n bivarianceHack(value: T): void;\n}[\"bivarianceHack\"];\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface IState {}\nexport interface IAction {\n type: string;\n}\n\nexport interface Store<S extends IState, A extends IAction> {\n getState(): S;\n dispatch(action: A): void;\n /**\n * Subscribe to all state changes.\n */\n subscribe(listener: Listener): () => void;\n /**\n * Subscribe to changes of a specific key in the state.\n */\n subscribeToKey<K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ): () => void;\n /**\n * Subscribe to changes in a selected value from the state.\n */\n subscribeWithSelector<T>(\n selector: (state: S) => T,\n listener: (selected: T) => void\n ): () => void;\n}\n\nexport function createStore<S extends IState, A extends IAction>(\n reducer: Reducer<S, A>,\n initialState: S\n): Store<S, A> {\n let state: S = DEV ? deepFreeze(initialState) : initialState;\n const listeners = new Set<Listener>();\n const keyListeners = new Map<keyof S, Set<BivariantListener<S[keyof S]>>>();\n\n interface SelectorEntry<T> {\n selector: (state: S) => T;\n listener: BivariantListener<T>;\n lastValue: T;\n }\n const selectorListeners = new Set<SelectorEntry<unknown>>();\n\n const getState = () => state;\n\n const dispatch = (action: A) => {\n const prevState = state;\n const nextState = reducer(state, action);\n\n if (DEV) deepFreeze(nextState);\n\n // Track the inbound action\n devTrack(\"store:dispatch\", { type: action?.type });\n\n // Distinct-until-changed: if the reducer returns the same reference,\n // skip all notifications (prevents unnecessary re-renders).\n if (Object.is(prevState, nextState)) {\n state = nextState; // keep any identity guarantees from reducer\n devTrack(\"store:no-op\", { type: action?.type });\n return;\n }\n\n state = nextState;\n\n // Compute changed keys (shallow) for diagnostics\n let changedKeys: (keyof S)[] | undefined;\n if (DEV) {\n changedKeys = Object.keys(nextState as Record<string, unknown>)\n .filter((k) => !Object.is((prevState as any)[k], (nextState as any)[k])) as (keyof S)[];\n devTrack(\"store:state-changed\", { type: action?.type, changedKeys });\n }\n\n // Notify global listeners (iterate over a snapshot so unsubscribe during\n // notify does not skip the next listener)\n const globalSnapshot = [...listeners];\n devTrack(\"store:notify:all\", { listeners: globalSnapshot.length });\n for (const listener of globalSnapshot) listener();\n\n // Notify key listeners only when that key actually changed (Object.is)\n for (const [key, set] of keyListeners.entries()) {\n if (!Object.is(prevState[key], state[key])) {\n devTrack(\"store:notify:key\", { key: String(key), listeners: set.size });\n for (const listener of [...set]) listener(state[key]);\n }\n }\n\n // Notify selector listeners only when selected value changed (Object.is)\n let selNotifies = 0;\n selectorListeners.forEach((entry) => {\n const nextValue = (entry.selector as (s: S) => unknown)(state);\n if (!Object.is(entry.lastValue, nextValue)) {\n entry.lastValue = nextValue as unknown;\n (entry.listener as (v: unknown) => void)(nextValue);\n selNotifies++;\n }\n });\n devTrack(\"store:notify:selector\", { listeners: selNotifies });\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n devTrack(\"store:sub:all:add\", { size: listeners.size });\n return () => {\n listeners.delete(listener);\n devTrack(\"store:sub:all:remove\", { size: listeners.size });\n };\n };\n\n const subscribeToKey = <K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ) => {\n const set =\n keyListeners.get(key) ?? new Set<BivariantListener<S[keyof S]>>();\n set.add(listener as unknown as BivariantListener<S[keyof S]>);\n keyListeners.set(key, set);\n devTrack(\"store:sub:key:add\", { key: String(key), size: set.size });\n return () => {\n set.delete(listener as unknown as BivariantListener<S[keyof S]>);\n if (set.size === 0) keyListeners.delete(key);\n devTrack(\"store:sub:key:remove\", { key: String(key), size: set.size });\n };\n };\n\n const subscribeWithSelector = <T>(\n selector: (state: S) => T,\n listener: (selected: T) => void\n ) => {\n const entry: SelectorEntry<T> = {\n selector,\n listener: listener as BivariantListener<T>,\n lastValue: selector(state),\n };\n selectorListeners.add(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:add\", { size: selectorListeners.size });\n return () => {\n selectorListeners.delete(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:remove\", { size: selectorListeners.size });\n };\n };\n\n return {\n getState,\n dispatch,\n subscribe,\n subscribeToKey,\n subscribeWithSelector,\n };\n}\n","import React, { createContext, useContext, useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Store, IState, IAction } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\nconst StoreContext = createContext<Store<IState, IAction> | undefined>(undefined);\n\nfunction useStoreInstance<S extends IState, A extends IAction>(): Store<S, A> {\n const store = useContext(StoreContext) as Store<S, A> | undefined;\n if (!store) {\n devTrack(\"store:provider:missing\");\n throw new Error(\n \"StoreProvider is missing in the React tree. Wrap your app with <StoreProvider store={...}>.\"\n );\n }\n return store;\n}\n\ninterface StoreProviderProps<S extends IState, A extends IAction> {\n store: Store<S, A>;\n children: ReactNode;\n}\n\nexport function StoreProvider<S extends IState, A extends IAction>({\n store,\n children,\n}: StoreProviderProps<S, A>) {\n useEffect(() => {\n devTrack(\"store:provider:mount\", { hasStore: !!store });\n return () => devTrack(\"store:provider:unmount\");\n }, [store]);\n return (\n <StoreContext.Provider value={store as unknown as Store<IState, IAction>}>\n {children}\n </StoreContext.Provider>\n );\n}\n\nexport function useStore<S extends IState>(): S {\n const store = useStoreInstance<S, IAction>();\n const [state, setState] = useState<S>(() => store.getState());\n const prevRef = React.useRef<S>(state);\n\n useEffect(() => {\n devTrack(\"store:react:subscribe\");\n const unsubscribe = store.subscribe(() => {\n const next = store.getState();\n if (!Object.is(prevRef.current, next)) {\n if (__DEV__) {\n try {\n const prev = prevRef.current as unknown as Record<string, unknown>;\n const cur = next as unknown as Record<string, unknown>;\n const changedKeys = Array.from(\n new Set([...Object.keys(prev || {}), ...Object.keys(cur || {})])\n ).filter((k) => !Object.is(prev?.[k], cur?.[k]));\n devTrack(\"store:react:update\", {\n changed: changedKeys,\n count: changedKeys.length,\n });\n } catch {}\n }\n prevRef.current = next;\n setState(next);\n } else {\n devTrack(\"store:react:no-op\");\n }\n });\n return () => {\n devTrack(\"store:react:unsubscribe\");\n unsubscribe();\n };\n }, [store]);\n\n return state;\n}\n\nexport function useDispatch<A extends IAction>(): Store<IState, A>[\"dispatch\"] {\n const store = useStoreInstance<IState, A>();\n // Return the store's dispatch directly; consumers can call dispatch(action).\n return store.dispatch as Store<IState, A>[\"dispatch\"];\n}\n","// metadata-store.ts\nexport class MetadataStore<T extends object, Meta extends object> {\n private readonly symbol: symbol;\n\n constructor(description: string) {\n this.symbol = Symbol(description);\n }\n\n set(target: T, meta: Meta) {\n Object.defineProperty(target, this.symbol as PropertyKey, {\n value: meta,\n writable: false,\n enumerable: false,\n });\n }\n\n get(target: T): Meta | undefined {\n return (target as Record<PropertyKey, Meta>)[this.symbol as PropertyKey];\n }\n\n has(target: T): boolean {\n return (this.symbol as PropertyKey) in target;\n }\n}\n"],"mappings":"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","names":["devTrack","useStore","useDispatch","createContext","useContext","useEffect","jsx","__DEV__","devTrack"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/create-scoped-store.tsx","../src/freeze.ts","../src/store.ts","../src/provider.tsx","../src/metadata-store.ts"],"sourcesContent":["export type Reducer<S, A> = (state: S, action: A) => S;\nexport type Listener = () => void;\nexport type Unsubscribe = () => void;\nexport const __noop = null;","import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useEffect, useMemo } from \"react\";\nimport type { IState, IAction, Store } from \"./store.js\";\nimport { createStore } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Local microtask-based batching (no react-dom dependency)\nconst _queue = new Set<() => void>();\nlet _queued = false;\nconst _schedule = typeof queueMicrotask === \"function\"\n ? queueMicrotask\n : (fn: () => void) => Promise.resolve().then(fn);\n\nfunction enqueue(fn: () => void) {\n _queue.add(fn);\n if (_queued) return;\n _queued = true;\n _schedule(() => {\n _queued = false;\n const fns = Array.from(_queue);\n _queue.clear();\n for (const f of fns) f();\n devTrack(\"scoped:batch:flush\", { size: fns.length });\n });\n}\n\nfunction makeBatchedSubscribe(subscribe: (l: () => void) => () => void) {\n return (onChange: () => void) => {\n devTrack(\"scoped:sub:add\");\n const wrapped = () => {\n devTrack(\"scoped:notify:enqueue\");\n enqueue(onChange);\n };\n const unsubscribe = subscribe(wrapped);\n return () => {\n devTrack(\"scoped:sub:remove\");\n unsubscribe();\n };\n };\n}\n\nfunction shallowEqual(a: any, b: any) {\n if (Object.is(a, b)) return true;\n if (\n typeof a !== \"object\" ||\n a === null ||\n typeof b !== \"object\" ||\n b === null\n )\n return false;\n const ak = Object.keys(a),\n bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n for (let i = 0; i < ak.length; i++) {\n const k = ak[i] as string;\n if (\n !Object.prototype.hasOwnProperty.call(b, k) ||\n !Object.is((a as any)[k], (b as any)[k])\n )\n return false;\n }\n return true;\n}\n\nexport function createScopedStoreContext<S extends IState, A extends IAction>(\n reducer: (state: S, action: A) => S,\n initialState: S\n) {\n const Context = createContext<Store<S, A> | null>(null);\n\n // Each Provider instance gets its own store.\n const Provider = ({\n children,\n initialState: override,\n }: {\n children: React.ReactNode;\n initialState?: S;\n }) => {\n const store = useMemo(() => {\n const next = createStore(reducer, override ?? initialState);\n devTrack(\"scoped:store:create\");\n return next;\n }, [reducer, override, initialState]);\n\n useEffect(() => {\n devTrack(\"scoped:provider:mount\");\n return () => devTrack(\"scoped:provider:unmount\");\n }, []);\n\n return <Context.Provider value={store}>{children}</Context.Provider>;\n };\n\n const useStore = (): S => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n devTrack(\"scoped:useStore\");\n return useSyncExternalStore(\n makeBatchedSubscribe(ctx.subscribe),\n ctx.getState,\n ctx.getState\n );\n };\n\n const useDispatch = (): ((action: A) => void) => {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Dispatch not found in context\");\n return useCallback((action: A) => ctx.dispatch(action), [ctx]);\n };\n\n function useSelector<T>(\n selector: (state: S) => T,\n isEqual: (a: T, b: T) => boolean = shallowEqual\n ): T {\n const ctx = useContext(Context);\n if (!ctx) throw new Error(\"Store not found in context\");\n\n const lastRef = useRef<{ selected: T } | null>(null);\n\n const getSnapshot = () => {\n const nextSelected = selector(ctx.getState());\n const last = lastRef.current;\n if (last && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:cache-hit\");\n return last.selected;\n }\n devTrack(\"scoped:selector:cache-miss\");\n lastRef.current = { selected: nextSelected };\n return nextSelected;\n };\n\n const subscribe = (onChange: () => void) => {\n devTrack(\"scoped:selector:sub:add\");\n const unsubscribe = ctx.subscribeWithSelector(selector, (nextSelected) => {\n const last = lastRef.current;\n if (last && isEqual(last.selected, nextSelected)) {\n devTrack(\"scoped:selector:skip\");\n return;\n }\n lastRef.current = { selected: nextSelected };\n devTrack(\"scoped:selector:notify\");\n enqueue(onChange);\n }, isEqual);\n return () => {\n devTrack(\"scoped:selector:sub:remove\");\n unsubscribe();\n };\n };\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n }\n\n return {\n Context,\n Provider,\n useStore,\n useDispatch,\n useSelector,\n };\n}\n","// freeze.ts\nexport function deepFreeze<T>(obj: T, seen = new WeakSet<object>()): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const o = obj as unknown as object;\n if (seen.has(o)) return obj;\n seen.add(o);\n\n // Freeze children first\n for (const key of Object.getOwnPropertyNames(o)) {\n // @ts-expect-error index access\n const val = (o as any)[key];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n // Also handle symbols (rare but safe)\n for (const sym of Object.getOwnPropertySymbols(o)) {\n // @ts-expect-error index access\n const val = (o as any)[sym];\n if (val && typeof val === \"object\") deepFreeze(val, seen);\n }\n\n return Object.freeze(obj);\n}\n","import type { Reducer, Listener } from \"./types.js\";\nimport { deepFreeze } from \"./freeze.js\";\n\nconst DEV =\n typeof import.meta !== \"undefined\"\n ? (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV\n : process.env.NODE_ENV !== \"production\";\n\n// Lightweight DEV-only tracker\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!DEV) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\n// Allow narrower parameter types for callbacks without fighting variance\ntype BivariantListener<T> = {\n bivarianceHack(value: T): void;\n}[\"bivarianceHack\"];\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface IState {}\nexport interface IAction {\n type: string;\n}\n\nexport interface Store<S extends IState, A extends IAction> {\n getState(): S;\n dispatch(action: A): void;\n /**\n * Subscribe to all state changes.\n */\n subscribe(listener: Listener): () => void;\n /**\n * Subscribe to changes of a specific key in the state.\n */\n subscribeToKey<K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ): () => void;\n /**\n * Subscribe to changes in a selected value from the state.\n */\n subscribeWithSelector<T>(\n selector: (state: S) => T,\n listener: (selected: T) => void,\n isEqual?: (a: T, b: T) => boolean\n ): () => void;\n}\n\nexport function createStore<S extends IState, A extends IAction>(\n reducer: Reducer<S, A>,\n initialState: S\n): Store<S, A> {\n let state: S = DEV ? deepFreeze(initialState) : initialState;\n const listeners = new Set<Listener>();\n const keyListeners = new Map<keyof S, Set<BivariantListener<S[keyof S]>>>();\n\n interface SelectorEntry<T> {\n selector: (state: S) => T;\n listener: BivariantListener<T>;\n lastValue: T;\n isEqual?: (a: T, b: T) => boolean;\n }\n const selectorListeners = new Set<SelectorEntry<unknown>>();\n\n const getState = () => state;\n\n const dispatch = (action: A) => {\n const prevState = state;\n const nextState = reducer(state, action);\n\n if (DEV) deepFreeze(nextState);\n\n // Track the inbound action\n devTrack(\"store:dispatch\", { type: action?.type });\n\n // Distinct-until-changed: if the reducer returns the same reference,\n // skip all notifications (prevents unnecessary re-renders).\n if (Object.is(prevState, nextState)) {\n state = nextState; // keep any identity guarantees from reducer\n devTrack(\"store:no-op\", { type: action?.type });\n return;\n }\n\n state = nextState;\n\n // Compute changed keys (shallow) for diagnostics\n let changedKeys: (keyof S)[] | undefined;\n if (DEV) {\n changedKeys = Object.keys(nextState as Record<string, unknown>)\n .filter((k) => !Object.is((prevState as any)[k], (nextState as any)[k])) as (keyof S)[];\n devTrack(\"store:state-changed\", { type: action?.type, changedKeys });\n }\n\n // Notify global listeners (iterate over a snapshot so unsubscribe during\n // notify does not skip the next listener)\n const globalSnapshot = [...listeners];\n devTrack(\"store:notify:all\", { listeners: globalSnapshot.length });\n let firstError: unknown;\n for (const listener of globalSnapshot) {\n try {\n listener();\n } catch (err) {\n if (!firstError) firstError = err;\n }\n }\n\n // Notify key listeners only when that key actually changed (Object.is)\n for (const [key, set] of keyListeners.entries()) {\n if (!Object.is(prevState[key], state[key])) {\n devTrack(\"store:notify:key\", { key: String(key), listeners: set.size });\n for (const listener of [...set]) {\n try {\n listener(state[key]);\n } catch (err) {\n if (!firstError) firstError = err;\n }\n }\n }\n }\n\n // Notify selector listeners only when selected value changed (Object.is)\n let selNotifies = 0;\n for (const entry of [...selectorListeners]) {\n const nextValue = (entry.selector as (s: S) => unknown)(state);\n const equal = (entry.isEqual as ((a: unknown, b: unknown) => boolean) | undefined) ?? Object.is;\n let isSame = false;\n try {\n isSame = equal(entry.lastValue, nextValue);\n } catch (err) {\n if (!firstError) firstError = err;\n continue;\n }\n if (!isSame) {\n entry.lastValue = nextValue as unknown;\n try {\n (entry.listener as (v: unknown) => void)(nextValue);\n } catch (err) {\n if (!firstError) firstError = err;\n }\n selNotifies++;\n }\n }\n devTrack(\"store:notify:selector\", { listeners: selNotifies });\n if (firstError) throw firstError;\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n devTrack(\"store:sub:all:add\", { size: listeners.size });\n return () => {\n listeners.delete(listener);\n devTrack(\"store:sub:all:remove\", { size: listeners.size });\n };\n };\n\n const subscribeToKey = <K extends keyof S>(\n key: K,\n listener: (value: S[K]) => void\n ) => {\n const set =\n keyListeners.get(key) ?? new Set<BivariantListener<S[keyof S]>>();\n set.add(listener as unknown as BivariantListener<S[keyof S]>);\n keyListeners.set(key, set);\n devTrack(\"store:sub:key:add\", { key: String(key), size: set.size });\n return () => {\n set.delete(listener as unknown as BivariantListener<S[keyof S]>);\n if (set.size === 0) keyListeners.delete(key);\n devTrack(\"store:sub:key:remove\", { key: String(key), size: set.size });\n };\n };\n\n const subscribeWithSelector = <T>(\n selector: (state: S) => T,\n listener: (selected: T) => void,\n isEqual?: (a: T, b: T) => boolean\n ) => {\n const entry: SelectorEntry<T> = {\n selector,\n listener: listener as BivariantListener<T>,\n lastValue: selector(state),\n isEqual,\n };\n selectorListeners.add(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:add\", { size: selectorListeners.size });\n return () => {\n selectorListeners.delete(entry as unknown as SelectorEntry<unknown>);\n devTrack(\"store:sub:selector:remove\", { size: selectorListeners.size });\n };\n };\n\n return {\n getState,\n dispatch,\n subscribe,\n subscribeToKey,\n subscribeWithSelector,\n };\n}\n","import React, { createContext, useContext, useEffect, useSyncExternalStore } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Store, IState, IAction } from \"./store.js\";\n\n// DEV-only tracking (no-op in production)\nconst __DEV__ = typeof process !== \"undefined\" ? process.env.NODE_ENV !== \"production\" : true;\nfunction devTrack(name: string, props?: Record<string, unknown>) {\n if (!__DEV__) return;\n try {\n const t = (globalThis as any)?.track;\n if (typeof t === \"function\") t(name, props);\n } catch {}\n}\n\nconst StoreContext = createContext<Store<IState, IAction> | undefined>(undefined);\n\nfunction useStoreInstance<S extends IState, A extends IAction>(): Store<S, A> {\n const store = useContext(StoreContext) as Store<S, A> | undefined;\n if (!store) {\n devTrack(\"store:provider:missing\");\n throw new Error(\n \"StoreProvider is missing in the React tree. Wrap your app with <StoreProvider store={...}>.\"\n );\n }\n return store;\n}\n\ninterface StoreProviderProps<S extends IState, A extends IAction> {\n store: Store<S, A>;\n children: ReactNode;\n}\n\nexport function StoreProvider<S extends IState, A extends IAction>({\n store,\n children,\n}: StoreProviderProps<S, A>) {\n useEffect(() => {\n devTrack(\"store:provider:mount\", { hasStore: !!store });\n return () => devTrack(\"store:provider:unmount\");\n }, [store]);\n return (\n <StoreContext.Provider value={store as unknown as Store<IState, IAction>}>\n {children}\n </StoreContext.Provider>\n );\n}\n\nexport function useStore<S extends IState>(): S {\n const store = useStoreInstance<S, IAction>();\n return useSyncExternalStore(\n (onStoreChange) => {\n devTrack(\"store:react:subscribe\");\n const unsubscribe = store.subscribe(() => {\n devTrack(\"store:react:notify\");\n onStoreChange();\n });\n return () => {\n devTrack(\"store:react:unsubscribe\");\n unsubscribe();\n };\n },\n store.getState,\n store.getState\n );\n}\n\nexport function useDispatch<A extends IAction>(): Store<IState, A>[\"dispatch\"] {\n const store = useStoreInstance<IState, A>();\n // Return the store's dispatch directly; consumers can call dispatch(action).\n return store.dispatch as Store<IState, A>[\"dispatch\"];\n}\n","// metadata-store.ts\nexport class MetadataStore<T extends object, Meta extends object> {\n private readonly symbol: symbol;\n\n constructor(description: string) {\n this.symbol = Symbol(description);\n }\n\n set(target: T, meta: Meta) {\n Object.defineProperty(target, this.symbol as PropertyKey, {\n value: meta,\n writable: false,\n enumerable: false,\n });\n }\n\n get(target: T): Meta | undefined {\n return (target as Record<PropertyKey, Meta>)[this.symbol as PropertyKey];\n }\n\n has(target: T): boolean {\n return (this.symbol as PropertyKey) in target;\n }\n}\n"],"mappings":";AAGO,IAAM,SAAS;;;ACHtB,SAAS,eAAe,YAAY,QAAQ,sBAAsB,aAAa,WAAW,eAAe;;;ACClG,SAAS,WAAc,KAAQ,OAAO,oBAAI,QAAgB,GAAM;AACrE,MAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU,QAAO;AACpD,QAAM,IAAI;AACV,MAAI,KAAK,IAAI,CAAC,EAAG,QAAO;AACxB,OAAK,IAAI,CAAC;AAGV,aAAW,OAAO,OAAO,oBAAoB,CAAC,GAAG;AAE/C,UAAM,MAAO,EAAU,GAAG;AAC1B,QAAI,OAAO,OAAO,QAAQ,SAAU,YAAW,KAAK,IAAI;AAAA,EAC1D;AAEA,aAAW,OAAO,OAAO,sBAAsB,CAAC,GAAG;AAEjD,UAAM,MAAO,EAAU,GAAG;AAC1B,QAAI,OAAO,OAAO,QAAQ,SAAU,YAAW,KAAK,IAAI;AAAA,EAC1D;AAEA,SAAO,OAAO,OAAO,GAAG;AAC1B;;;AClBA,IAAM,MACJ,OAAO,gBAAgB,cAClB,YAAuD,KAAK,MAC7D,QAAQ,IAAI,aAAa;AAG/B,SAAS,SAAS,MAAc,OAAiC;AAC/D,MAAI,CAAC,IAAK;AACV,MAAI;AACF,UAAM,IAAK,YAAoB;AAC/B,QAAI,OAAO,MAAM,WAAY,GAAE,MAAM,KAAK;AAAA,EAC5C,QAAQ;AAAA,EAAC;AACX;AAqCO,SAAS,YACd,SACA,cACa;AACb,MAAI,QAAW,MAAM,WAAW,YAAY,IAAI;AAChD,QAAM,YAAY,oBAAI,IAAc;AACpC,QAAM,eAAe,oBAAI,IAAiD;AAQ1E,QAAM,oBAAoB,oBAAI,IAA4B;AAE1D,QAAM,WAAW,MAAM;AAEvB,QAAM,WAAW,CAAC,WAAc;AAC9B,UAAM,YAAY;AAClB,UAAM,YAAY,QAAQ,OAAO,MAAM;AAEvC,QAAI,IAAK,YAAW,SAAS;AAG7B,aAAS,kBAAkB,EAAE,MAAM,QAAQ,KAAK,CAAC;AAIjD,QAAI,OAAO,GAAG,WAAW,SAAS,GAAG;AACnC,cAAQ;AACR,eAAS,eAAe,EAAE,MAAM,QAAQ,KAAK,CAAC;AAC9C;AAAA,IACF;AAEA,YAAQ;AAGR,QAAI;AACJ,QAAI,KAAK;AACP,oBAAc,OAAO,KAAK,SAAoC,EAC3D,OAAO,CAAC,MAAM,CAAC,OAAO,GAAI,UAAkB,CAAC,GAAI,UAAkB,CAAC,CAAC,CAAC;AACzE,eAAS,uBAAuB,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AAAA,IACrE;AAIA,UAAM,iBAAiB,CAAC,GAAG,SAAS;AACpC,aAAS,oBAAoB,EAAE,WAAW,eAAe,OAAO,CAAC;AACjE,QAAI;AACJ,eAAW,YAAY,gBAAgB;AACrC,UAAI;AACF,iBAAS;AAAA,MACX,SAAS,KAAK;AACZ,YAAI,CAAC,WAAY,cAAa;AAAA,MAChC;AAAA,IACF;AAGA,eAAW,CAAC,KAAK,GAAG,KAAK,aAAa,QAAQ,GAAG;AAC/C,UAAI,CAAC,OAAO,GAAG,UAAU,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG;AAC1C,iBAAS,oBAAoB,EAAE,KAAK,OAAO,GAAG,GAAG,WAAW,IAAI,KAAK,CAAC;AACtE,mBAAW,YAAY,CAAC,GAAG,GAAG,GAAG;AAC/B,cAAI;AACF,qBAAS,MAAM,GAAG,CAAC;AAAA,UACrB,SAAS,KAAK;AACZ,gBAAI,CAAC,WAAY,cAAa;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,cAAc;AAClB,eAAW,SAAS,CAAC,GAAG,iBAAiB,GAAG;AAC1C,YAAM,YAAa,MAAM,SAA+B,KAAK;AAC7D,YAAM,QAAS,MAAM,WAAiE,OAAO;AAC7F,UAAI,SAAS;AACb,UAAI;AACF,iBAAS,MAAM,MAAM,WAAW,SAAS;AAAA,MAC3C,SAAS,KAAK;AACZ,YAAI,CAAC,WAAY,cAAa;AAC9B;AAAA,MACF;AACA,UAAI,CAAC,QAAQ;AACX,cAAM,YAAY;AAClB,YAAI;AACF,UAAC,MAAM,SAAkC,SAAS;AAAA,QACpD,SAAS,KAAK;AACZ,cAAI,CAAC,WAAY,cAAa;AAAA,QAChC;AACA;AAAA,MACF;AAAA,IACF;AACA,aAAS,yBAAyB,EAAE,WAAW,YAAY,CAAC;AAC5D,QAAI,WAAY,OAAM;AAAA,EACxB;AAEA,QAAM,YAAY,CAAC,aAAuB;AACxC,cAAU,IAAI,QAAQ;AACtB,aAAS,qBAAqB,EAAE,MAAM,UAAU,KAAK,CAAC;AACtD,WAAO,MAAM;AACX,gBAAU,OAAO,QAAQ;AACzB,eAAS,wBAAwB,EAAE,MAAM,UAAU,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,iBAAiB,CACrB,KACA,aACG;AACH,UAAM,MACJ,aAAa,IAAI,GAAG,KAAK,oBAAI,IAAmC;AAClE,QAAI,IAAI,QAAoD;AAC5D,iBAAa,IAAI,KAAK,GAAG;AACzB,aAAS,qBAAqB,EAAE,KAAK,OAAO,GAAG,GAAG,MAAM,IAAI,KAAK,CAAC;AAClE,WAAO,MAAM;AACX,UAAI,OAAO,QAAoD;AAC/D,UAAI,IAAI,SAAS,EAAG,cAAa,OAAO,GAAG;AAC3C,eAAS,wBAAwB,EAAE,KAAK,OAAO,GAAG,GAAG,MAAM,IAAI,KAAK,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,wBAAwB,CAC5B,UACA,UACA,YACG;AACH,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,WAAW,SAAS,KAAK;AAAA,MACzB;AAAA,IACF;AACA,sBAAkB,IAAI,KAA0C;AAChE,aAAS,0BAA0B,EAAE,MAAM,kBAAkB,KAAK,CAAC;AACnE,WAAO,MAAM;AACX,wBAAkB,OAAO,KAA0C;AACnE,eAAS,6BAA6B,EAAE,MAAM,kBAAkB,KAAK,CAAC;AAAA,IACxE;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AFxGW;AA5FX,IAAM,UAAU,OAAO,YAAY,cAAc,QAAQ,IAAI,aAAa,eAAe;AACzF,SAASA,UAAS,MAAc,OAAiC;AAC/D,MAAI,CAAC,QAAS;AACd,MAAI;AACF,UAAM,IAAK,YAAoB;AAC/B,QAAI,OAAO,MAAM,WAAY,GAAE,MAAM,KAAK;AAAA,EAC5C,QAAQ;AAAA,EAAC;AACX;AAGA,IAAM,SAAS,oBAAI,IAAgB;AACnC,IAAI,UAAU;AACd,IAAM,YAAY,OAAO,mBAAmB,aACxC,iBACA,CAAC,OAAmB,QAAQ,QAAQ,EAAE,KAAK,EAAE;AAEjD,SAAS,QAAQ,IAAgB;AAC/B,SAAO,IAAI,EAAE;AACb,MAAI,QAAS;AACb,YAAU;AACV,YAAU,MAAM;AACd,cAAU;AACV,UAAM,MAAM,MAAM,KAAK,MAAM;AAC7B,WAAO,MAAM;AACb,eAAW,KAAK,IAAK,GAAE;AACvB,IAAAA,UAAS,sBAAsB,EAAE,MAAM,IAAI,OAAO,CAAC;AAAA,EACrD,CAAC;AACH;AAEA,SAAS,qBAAqB,WAA0C;AACtE,SAAO,CAAC,aAAyB;AAC/B,IAAAA,UAAS,gBAAgB;AACzB,UAAM,UAAU,MAAM;AACpB,MAAAA,UAAS,uBAAuB;AAChC,cAAQ,QAAQ;AAAA,IAClB;AACA,UAAM,cAAc,UAAU,OAAO;AACrC,WAAO,MAAM;AACX,MAAAA,UAAS,mBAAmB;AAC5B,kBAAY;AAAA,IACd;AAAA,EACF;AACF;AAEA,SAAS,aAAa,GAAQ,GAAQ;AACpC,MAAI,OAAO,GAAG,GAAG,CAAC,EAAG,QAAO;AAC5B,MACE,OAAO,MAAM,YACb,MAAM,QACN,OAAO,MAAM,YACb,MAAM;AAEN,WAAO;AACT,QAAM,KAAK,OAAO,KAAK,CAAC,GACtB,KAAK,OAAO,KAAK,CAAC;AACpB,MAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,WAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,UAAM,IAAI,GAAG,CAAC;AACd,QACE,CAAC,OAAO,UAAU,eAAe,KAAK,GAAG,CAAC,KAC1C,CAAC,OAAO,GAAI,EAAU,CAAC,GAAI,EAAU,CAAC,CAAC;AAEvC,aAAO;AAAA,EACX;AACA,SAAO;AACT;AAEO,SAAS,yBACd,SACA,cACA;AACA,QAAM,UAAU,cAAkC,IAAI;AAGtD,QAAM,WAAW,CAAC;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,EAChB,MAGM;AACJ,UAAM,QAAQ,QAAQ,MAAM;AAC1B,YAAM,OAAO,YAAY,SAAS,YAAY,YAAY;AAC1D,MAAAA,UAAS,qBAAqB;AAC9B,aAAO;AAAA,IACT,GAAG,CAAC,SAAS,UAAU,YAAY,CAAC;AAEpC,cAAU,MAAM;AACd,MAAAA,UAAS,uBAAuB;AAChC,aAAO,MAAMA,UAAS,yBAAyB;AAAA,IACjD,GAAG,CAAC,CAAC;AAEL,WAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,OAAQ,UAAS;AAAA,EACnD;AAEA,QAAMC,YAAW,MAAS;AACxB,UAAM,MAAM,WAAW,OAAO;AAC9B,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4BAA4B;AACtD,IAAAD,UAAS,iBAAiB;AAC1B,WAAO;AAAA,MACL,qBAAqB,IAAI,SAAS;AAAA,MAClC,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAEA,QAAME,eAAc,MAA6B;AAC/C,UAAM,MAAM,WAAW,OAAO;AAC9B,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+BAA+B;AACzD,WAAO,YAAY,CAAC,WAAc,IAAI,SAAS,MAAM,GAAG,CAAC,GAAG,CAAC;AAAA,EAC/D;AAEA,WAAS,YACP,UACA,UAAmC,cAChC;AACH,UAAM,MAAM,WAAW,OAAO;AAC9B,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4BAA4B;AAEtD,UAAM,UAAU,OAA+B,IAAI;AAEnD,UAAM,cAAc,MAAM;AACxB,YAAM,eAAe,SAAS,IAAI,SAAS,CAAC;AAC5C,YAAM,OAAO,QAAQ;AACrB,UAAI,QAAQ,QAAQ,KAAK,UAAU,YAAY,GAAG;AAChD,QAAAF,UAAS,2BAA2B;AACpC,eAAO,KAAK;AAAA,MACd;AACA,MAAAA,UAAS,4BAA4B;AACrC,cAAQ,UAAU,EAAE,UAAU,aAAa;AAC3C,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,CAAC,aAAyB;AAC1C,MAAAA,UAAS,yBAAyB;AAClC,YAAM,cAAc,IAAI,sBAAsB,UAAU,CAAC,iBAAiB;AACxE,cAAM,OAAO,QAAQ;AACrB,YAAI,QAAQ,QAAQ,KAAK,UAAU,YAAY,GAAG;AAChD,UAAAA,UAAS,sBAAsB;AAC/B;AAAA,QACF;AACA,gBAAQ,UAAU,EAAE,UAAU,aAAa;AAC3C,QAAAA,UAAS,wBAAwB;AACjC,gBAAQ,QAAQ;AAAA,MAClB,GAAG,OAAO;AACV,aAAO,MAAM;AACX,QAAAA,UAAS,4BAA4B;AACrC,oBAAY;AAAA,MACd;AAAA,IACF;AAEA,WAAO,qBAAqB,WAAW,aAAa,WAAW;AAAA,EACjE;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA;AAAA,EACF;AACF;;;AGtKA,SAAgB,iBAAAC,gBAAe,cAAAC,aAAY,aAAAC,YAAW,wBAAAC,6BAA4B;AAyC9E,gBAAAC,YAAA;AApCJ,IAAMC,WAAU,OAAO,YAAY,cAAc,QAAQ,IAAI,aAAa,eAAe;AACzF,SAASC,UAAS,MAAc,OAAiC;AAC/D,MAAI,CAACD,SAAS;AACd,MAAI;AACF,UAAM,IAAK,YAAoB;AAC/B,QAAI,OAAO,MAAM,WAAY,GAAE,MAAM,KAAK;AAAA,EAC5C,QAAQ;AAAA,EAAC;AACX;AAEA,IAAM,eAAeL,eAAkD,MAAS;AAEhF,SAAS,mBAAqE;AAC5E,QAAM,QAAQC,YAAW,YAAY;AACrC,MAAI,CAAC,OAAO;AACV,IAAAK,UAAS,wBAAwB;AACjC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,cAAmD;AAAA,EACjE;AAAA,EACA;AACF,GAA6B;AAC3B,EAAAJ,WAAU,MAAM;AACd,IAAAI,UAAS,wBAAwB,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC;AACtD,WAAO,MAAMA,UAAS,wBAAwB;AAAA,EAChD,GAAG,CAAC,KAAK,CAAC;AACV,SACE,gBAAAF,KAAC,aAAa,UAAb,EAAsB,OAAO,OAC3B,UACH;AAEJ;AAEO,SAAS,WAAgC;AAC9C,QAAM,QAAQ,iBAA6B;AAC3C,SAAOD;AAAA,IACL,CAAC,kBAAkB;AACjB,MAAAG,UAAS,uBAAuB;AAChC,YAAM,cAAc,MAAM,UAAU,MAAM;AACxC,QAAAA,UAAS,oBAAoB;AAC7B,sBAAc;AAAA,MAChB,CAAC;AACD,aAAO,MAAM;AACX,QAAAA,UAAS,yBAAyB;AAClC,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAEO,SAAS,cAA+D;AAC7E,QAAM,QAAQ,iBAA4B;AAE1C,SAAO,MAAM;AACf;;;ACrEO,IAAM,gBAAN,MAA2D;AAAA,EAC/C;AAAA,EAEjB,YAAY,aAAqB;AAC/B,SAAK,SAAS,OAAO,WAAW;AAAA,EAClC;AAAA,EAEA,IAAI,QAAW,MAAY;AACzB,WAAO,eAAe,QAAQ,KAAK,QAAuB;AAAA,MACxD,OAAO;AAAA,MACP,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,QAA6B;AAC/B,WAAQ,OAAqC,KAAK,MAAqB;AAAA,EACzE;AAAA,EAEA,IAAI,QAAoB;AACtB,WAAQ,KAAK,UAA0B;AAAA,EACzC;AACF;","names":["devTrack","useStore","useDispatch","createContext","useContext","useEffect","useSyncExternalStore","jsx","__DEV__","devTrack"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plasius/react-state",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Tiny, testable, typesafe React Scoped Store helper.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"react": "^19"
|
|
72
|
+
"react": "^18.2 || ^19"
|
|
73
73
|
},
|
|
74
74
|
"funding": [
|
|
75
75
|
{
|