@codebelt/classy-store 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/equality-5F2bPn7E.d.mts +13 -0
- package/dist/equality-5F2bPn7E.d.mts.map +1 -0
- package/dist/equality-BA46H9AL.mjs +27 -0
- package/dist/equality-BA46H9AL.mjs.map +1 -0
- package/dist/equality-C1s0kqxg.d.cts +13 -0
- package/dist/equality-C1s0kqxg.d.cts.map +1 -0
- package/dist/equality-Cz6riknL.cjs +33 -0
- package/dist/equality-Cz6riknL.cjs.map +1 -0
- package/dist/index.cjs +3 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -11
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -26
- package/dist/index.mjs.map +1 -1
- package/dist/react/react.cjs +30 -1
- package/dist/react/react.cjs.map +1 -1
- package/dist/react/react.d.cts +26 -1
- package/dist/react/react.d.cts.map +1 -1
- package/dist/react/react.d.mts +27 -2
- package/dist/react/react.d.mts.map +1 -1
- package/dist/react/react.mjs +31 -3
- package/dist/react/react.mjs.map +1 -1
- package/dist/{snapshot-P0QPV1ER.mjs → snapshot-COzEerMu.mjs} +27 -2
- package/dist/snapshot-COzEerMu.mjs.map +1 -0
- package/dist/{snapshot-BKVFJLuo.cjs → snapshot-CbVbxG7s.cjs} +27 -2
- package/dist/snapshot-CbVbxG7s.cjs.map +1 -0
- package/dist/{types-vWYkF3tH.d.mts → types-Cf8Fp7kA.d.mts} +1 -1
- package/dist/{types-vWYkF3tH.d.mts.map → types-Cf8Fp7kA.d.mts.map} +1 -1
- package/dist/utils/index.cjs +176 -5
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +89 -1
- package/dist/utils/index.d.cts.map +1 -1
- package/dist/utils/index.d.mts +89 -1
- package/dist/utils/index.d.mts.map +1 -1
- package/dist/utils/index.mjs +173 -6
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +1 -22
- package/README.md +0 -48
- package/dist/snapshot-BKVFJLuo.cjs.map +0 -1
- package/dist/snapshot-P0QPV1ER.mjs.map +0 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/utils/equality/equality.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shallow-equal comparison for objects and arrays.
|
|
4
|
+
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
5
|
+
*
|
|
6
|
+
* - Primitives compared with `Object.is`.
|
|
7
|
+
* - Arrays: length + element-wise `Object.is`.
|
|
8
|
+
* - Objects: key count + value-wise `Object.is`.
|
|
9
|
+
*/
|
|
10
|
+
declare function shallowEqual<T>(a: T, b: T): boolean;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { shallowEqual as t };
|
|
13
|
+
//# sourceMappingURL=equality-5F2bPn7E.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equality-5F2bPn7E.d.mts","names":[],"sources":["../src/utils/equality/equality.ts"],"mappings":";;AAQA;;;;;;;iBAAgB,YAAA,GAAA,CAAgB,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/utils/equality/equality.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shallow-equal comparison for objects and arrays.
|
|
4
|
+
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
5
|
+
*
|
|
6
|
+
* - Primitives compared with `Object.is`.
|
|
7
|
+
* - Arrays: length + element-wise `Object.is`.
|
|
8
|
+
* - Objects: key count + value-wise `Object.is`.
|
|
9
|
+
*/
|
|
10
|
+
function shallowEqual(a, b) {
|
|
11
|
+
if (Object.is(a, b)) return true;
|
|
12
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
13
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
14
|
+
if (a.length !== b.length) return false;
|
|
15
|
+
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const keysA = Object.keys(a);
|
|
19
|
+
const keysB = Object.keys(b);
|
|
20
|
+
if (keysA.length !== keysB.length) return false;
|
|
21
|
+
for (const key of keysA) if (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) return false;
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { shallowEqual as t };
|
|
27
|
+
//# sourceMappingURL=equality-BA46H9AL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equality-BA46H9AL.mjs","names":[],"sources":["../src/utils/equality/equality.ts"],"sourcesContent":["/**\n * Shallow-equal comparison for objects and arrays.\n * Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.\n *\n * - Primitives compared with `Object.is`.\n * - Arrays: length + element-wise `Object.is`.\n * - Objects: key count + value-wise `Object.is`.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\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 }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (\n !Object.hasOwn(b, key) ||\n !Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n )\n ) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,aAAgB,GAAM,GAAe;AACnD,KAAI,OAAO,GAAG,GAAG,EAAE,CAAE,QAAO;AAC5B,KACE,OAAO,MAAM,YACb,MAAM,QACN,OAAO,MAAM,YACb,MAAM,KAEN,QAAO;AAGT,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,EAAE;AACxC,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,OAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,SAAO;;CAGT,MAAM,QAAQ,OAAO,KAAK,EAAE;CAC5B,MAAM,QAAQ,OAAO,KAAK,EAAE;AAC5B,KAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,MAAK,MAAM,OAAO,MAChB,KACE,CAAC,OAAO,OAAO,GAAG,IAAI,IACtB,CAAC,OAAO,GACL,EAA8B,MAC9B,EAA8B,KAChC,CAED,QAAO;AAGX,QAAO"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/utils/equality/equality.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shallow-equal comparison for objects and arrays.
|
|
4
|
+
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
5
|
+
*
|
|
6
|
+
* - Primitives compared with `Object.is`.
|
|
7
|
+
* - Arrays: length + element-wise `Object.is`.
|
|
8
|
+
* - Objects: key count + value-wise `Object.is`.
|
|
9
|
+
*/
|
|
10
|
+
declare function shallowEqual<T>(a: T, b: T): boolean;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { shallowEqual as t };
|
|
13
|
+
//# sourceMappingURL=equality-C1s0kqxg.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equality-C1s0kqxg.d.cts","names":[],"sources":["../src/utils/equality/equality.ts"],"mappings":";;AAQA;;;;;;;iBAAgB,YAAA,GAAA,CAAgB,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/utils/equality/equality.ts
|
|
3
|
+
/**
|
|
4
|
+
* Shallow-equal comparison for objects and arrays.
|
|
5
|
+
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
6
|
+
*
|
|
7
|
+
* - Primitives compared with `Object.is`.
|
|
8
|
+
* - Arrays: length + element-wise `Object.is`.
|
|
9
|
+
* - Objects: key count + value-wise `Object.is`.
|
|
10
|
+
*/
|
|
11
|
+
function shallowEqual(a, b) {
|
|
12
|
+
if (Object.is(a, b)) return true;
|
|
13
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
14
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
15
|
+
if (a.length !== b.length) return false;
|
|
16
|
+
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const keysA = Object.keys(a);
|
|
20
|
+
const keysB = Object.keys(b);
|
|
21
|
+
if (keysA.length !== keysB.length) return false;
|
|
22
|
+
for (const key of keysA) if (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) return false;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
Object.defineProperty(exports, 'shallowEqual', {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () {
|
|
30
|
+
return shallowEqual;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=equality-Cz6riknL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equality-Cz6riknL.cjs","names":[],"sources":["../src/utils/equality/equality.ts"],"sourcesContent":["/**\n * Shallow-equal comparison for objects and arrays.\n * Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.\n *\n * - Primitives compared with `Object.is`.\n * - Arrays: length + element-wise `Object.is`.\n * - Objects: key count + value-wise `Object.is`.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\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 }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (\n !Object.hasOwn(b, key) ||\n !Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n )\n ) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,aAAgB,GAAM,GAAe;AACnD,KAAI,OAAO,GAAG,GAAG,EAAE,CAAE,QAAO;AAC5B,KACE,OAAO,MAAM,YACb,MAAM,QACN,OAAO,MAAM,YACb,MAAM,KAEN,QAAO;AAGT,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,EAAE;AACxC,MAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,OAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,SAAO;;CAGT,MAAM,QAAQ,OAAO,KAAK,EAAE;CAC5B,MAAM,QAAQ,OAAO,KAAK,EAAE;AAC5B,KAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,MAAK,MAAM,OAAO,MAChB,KACE,CAAC,OAAO,OAAO,GAAG,IAAI,IACtB,CAAC,OAAO,GACL,EAA8B,MAC9B,EAA8B,KAChC,CAED,QAAO;AAGX,QAAO"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_snapshot = require('./snapshot-
|
|
2
|
+
const require_snapshot = require('./snapshot-CbVbxG7s.cjs');
|
|
3
|
+
const require_equality = require('./equality-Cz6riknL.cjs');
|
|
3
4
|
|
|
4
5
|
//#region src/collections/collections.ts
|
|
5
6
|
/**
|
|
@@ -166,37 +167,12 @@ function reactiveSet(initial) {
|
|
|
166
167
|
return new ReactiveSet(initial);
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
//#endregion
|
|
170
|
-
//#region src/utils/equality/equality.ts
|
|
171
|
-
/**
|
|
172
|
-
* Shallow-equal comparison for objects and arrays.
|
|
173
|
-
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
174
|
-
*
|
|
175
|
-
* - Primitives compared with `Object.is`.
|
|
176
|
-
* - Arrays: length + element-wise `Object.is`.
|
|
177
|
-
* - Objects: key count + value-wise `Object.is`.
|
|
178
|
-
*/
|
|
179
|
-
function shallowEqual(a, b) {
|
|
180
|
-
if (Object.is(a, b)) return true;
|
|
181
|
-
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
182
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
183
|
-
if (a.length !== b.length) return false;
|
|
184
|
-
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
const keysA = Object.keys(a);
|
|
188
|
-
const keysB = Object.keys(b);
|
|
189
|
-
if (keysA.length !== keysB.length) return false;
|
|
190
|
-
for (const key of keysA) if (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) return false;
|
|
191
|
-
return true;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
170
|
//#endregion
|
|
195
171
|
exports.createClassyStore = require_snapshot.createClassyStore;
|
|
196
172
|
exports.getVersion = require_snapshot.getVersion;
|
|
197
173
|
exports.reactiveMap = reactiveMap;
|
|
198
174
|
exports.reactiveSet = reactiveSet;
|
|
199
|
-
exports.shallowEqual = shallowEqual;
|
|
175
|
+
exports.shallowEqual = require_equality.shallowEqual;
|
|
200
176
|
exports.snapshot = require_snapshot.snapshot;
|
|
201
177
|
exports.subscribe = require_snapshot.subscribe;
|
|
202
178
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["PROXYABLE"],"sources":["../src/collections/collections.ts","../src/utils/equality/equality.ts"],"sourcesContent":["import {PROXYABLE} from '../utils/internal/internal';\n\n// ── ReactiveMap ───────────────────────────────────────────────────────────────\n\n/**\n * A Map-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.set()` would be invisible to the store. `ReactiveMap` solves this by\n * storing entries in a plain array (`_entries`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ users: reactiveMap<string, User>() });\n * myStore.users.set('id1', { name: 'Alice' }); // reactive\n * ```\n */\nexport class ReactiveMap<K, V> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _entries: [K, V][] = [];\n\n /** Deduplicates initial entries by key (last value wins, matching native `Map`). */\n constructor(initial?: Iterable<[K, V]>) {\n if (initial) {\n for (const [k, v] of initial) {\n const index = this._entries.findIndex(([ek]) => Object.is(ek, k));\n if (index !== -1) {\n this._entries[index] = [k, v];\n } else {\n this._entries.push([k, v]);\n }\n }\n }\n }\n\n /** Returns the number of entries. */\n get size(): number {\n return this._entries.length;\n }\n\n /** Returns the value for `key`, or `undefined`. O(n) linear scan. */\n get(key: K): V | undefined {\n const entry = this._entries.find(([k]) => Object.is(k, key));\n return entry ? entry[1] : undefined;\n }\n\n /** Returns `true` if `key` exists. O(n) linear scan. */\n has(key: K): boolean {\n return this._entries.some(([k]) => Object.is(k, key));\n }\n\n /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */\n set(key: K, value: V): this {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index !== -1) {\n this._entries[index] = [key, value];\n } else {\n this._entries.push([key, value]);\n }\n return this;\n }\n\n /** Removes the entry for `key`. Returns `true` if found. */\n delete(key: K): boolean {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index === -1) return false;\n this._entries.splice(index, 1);\n return true;\n }\n\n /** Removes all entries. Uses splice to trigger proxy notification. */\n clear(): void {\n this._entries.splice(0, this._entries.length);\n }\n\n /** Returns an iterator over the keys. */\n keys(): IterableIterator<K> {\n return this._entries.map(([k]) => k)[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<V> {\n return this._entries.map(([, v]) => v)[Symbol.iterator]();\n }\n\n /** Returns an iterator over [key, value] pairs. */\n entries(): IterableIterator<[K, V]> {\n return this._entries.map(([k, v]) => [k, v] as [K, V])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */\n forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void {\n for (const [k, v] of this._entries) {\n callback(v, k, this);\n }\n }\n\n /** Enables `for...of` iteration over [key, value] pairs. */\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n}\n\n// ── ReactiveSet ───────────────────────────────────────────────────────────────\n\n/**\n * A Set-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.add()` would be invisible to the store. `ReactiveSet` solves this by\n * storing items in a plain array (`_items`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ tags: reactiveSet<string>(['urgent']) });\n * myStore.tags.add('bug'); // reactive\n * ```\n */\nexport class ReactiveSet<T> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _items: T[] = [];\n\n /** Deduplicates initial values using `Object.is` comparison. */\n constructor(initial?: Iterable<T>) {\n if (initial) {\n for (const v of initial) {\n if (!this._items.some((item) => Object.is(item, v))) {\n this._items.push(v);\n }\n }\n }\n }\n\n /** Returns the number of unique items. */\n get size(): number {\n return this._items.length;\n }\n\n /** Returns `true` if `value` exists. O(n) linear scan. */\n has(value: T): boolean {\n return this._items.some((item) => Object.is(item, value));\n }\n\n /** Adds `value` if not already present (no-op for duplicates). */\n add(value: T): this {\n if (!this.has(value)) {\n this._items.push(value);\n }\n return this;\n }\n\n /** Removes `value`. Returns `true` if found. */\n delete(value: T): boolean {\n const index = this._items.findIndex((item) => Object.is(item, value));\n if (index === -1) return false;\n this._items.splice(index, 1);\n return true;\n }\n\n /** Removes all items. Uses splice to trigger proxy notification. */\n clear(): void {\n this._items.splice(0, this._items.length);\n }\n\n /** Returns an iterator over the values (same as `values()`, matching Set API). */\n keys(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over [value, value] pairs, matching the native Set API. */\n entries(): IterableIterator<[T, T]> {\n return this._items.map((v) => [v, v] as [T, T])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each item, matching the native `Set.forEach` signature. */\n forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void {\n for (const v of this._items) {\n callback(v, v, this);\n }\n }\n\n /** Enables `for...of` iteration over values. */\n [Symbol.iterator](): IterableIterator<T> {\n return this.values();\n }\n}\n\n// ── Factory functions ─────────────────────────────────────────────────────────\n\n/**\n * Creates a reactive Map-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of `[key, value]` pairs.\n */\nexport function reactiveMap<K, V>(\n initial?: Iterable<[K, V]>,\n): ReactiveMap<K, V> {\n return new ReactiveMap(initial);\n}\n\n/**\n * Creates a reactive Set-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of values.\n */\nexport function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T> {\n return new ReactiveSet(initial);\n}\n","/**\n * Shallow-equal comparison for objects and arrays.\n * Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.\n *\n * - Primitives compared with `Object.is`.\n * - Arrays: length + element-wise `Object.is`.\n * - Objects: key count + value-wise `Object.is`.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\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 }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (\n !Object.hasOwn(b, key) ||\n !Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n )\n ) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["PROXYABLE"],"sources":["../src/collections/collections.ts"],"sourcesContent":["import {PROXYABLE} from '../utils/internal/internal';\n\n// ── ReactiveMap ───────────────────────────────────────────────────────────────\n\n/**\n * A Map-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.set()` would be invisible to the store. `ReactiveMap` solves this by\n * storing entries in a plain array (`_entries`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ users: reactiveMap<string, User>() });\n * myStore.users.set('id1', { name: 'Alice' }); // reactive\n * ```\n */\nexport class ReactiveMap<K, V> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _entries: [K, V][] = [];\n\n /** Deduplicates initial entries by key (last value wins, matching native `Map`). */\n constructor(initial?: Iterable<[K, V]>) {\n if (initial) {\n for (const [k, v] of initial) {\n const index = this._entries.findIndex(([ek]) => Object.is(ek, k));\n if (index !== -1) {\n this._entries[index] = [k, v];\n } else {\n this._entries.push([k, v]);\n }\n }\n }\n }\n\n /** Returns the number of entries. */\n get size(): number {\n return this._entries.length;\n }\n\n /** Returns the value for `key`, or `undefined`. O(n) linear scan. */\n get(key: K): V | undefined {\n const entry = this._entries.find(([k]) => Object.is(k, key));\n return entry ? entry[1] : undefined;\n }\n\n /** Returns `true` if `key` exists. O(n) linear scan. */\n has(key: K): boolean {\n return this._entries.some(([k]) => Object.is(k, key));\n }\n\n /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */\n set(key: K, value: V): this {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index !== -1) {\n this._entries[index] = [key, value];\n } else {\n this._entries.push([key, value]);\n }\n return this;\n }\n\n /** Removes the entry for `key`. Returns `true` if found. */\n delete(key: K): boolean {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index === -1) return false;\n this._entries.splice(index, 1);\n return true;\n }\n\n /** Removes all entries. Uses splice to trigger proxy notification. */\n clear(): void {\n this._entries.splice(0, this._entries.length);\n }\n\n /** Returns an iterator over the keys. */\n keys(): IterableIterator<K> {\n return this._entries.map(([k]) => k)[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<V> {\n return this._entries.map(([, v]) => v)[Symbol.iterator]();\n }\n\n /** Returns an iterator over [key, value] pairs. */\n entries(): IterableIterator<[K, V]> {\n return this._entries.map(([k, v]) => [k, v] as [K, V])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */\n forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void {\n for (const [k, v] of this._entries) {\n callback(v, k, this);\n }\n }\n\n /** Enables `for...of` iteration over [key, value] pairs. */\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n}\n\n// ── ReactiveSet ───────────────────────────────────────────────────────────────\n\n/**\n * A Set-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.add()` would be invisible to the store. `ReactiveSet` solves this by\n * storing items in a plain array (`_items`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ tags: reactiveSet<string>(['urgent']) });\n * myStore.tags.add('bug'); // reactive\n * ```\n */\nexport class ReactiveSet<T> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _items: T[] = [];\n\n /** Deduplicates initial values using `Object.is` comparison. */\n constructor(initial?: Iterable<T>) {\n if (initial) {\n for (const v of initial) {\n if (!this._items.some((item) => Object.is(item, v))) {\n this._items.push(v);\n }\n }\n }\n }\n\n /** Returns the number of unique items. */\n get size(): number {\n return this._items.length;\n }\n\n /** Returns `true` if `value` exists. O(n) linear scan. */\n has(value: T): boolean {\n return this._items.some((item) => Object.is(item, value));\n }\n\n /** Adds `value` if not already present (no-op for duplicates). */\n add(value: T): this {\n if (!this.has(value)) {\n this._items.push(value);\n }\n return this;\n }\n\n /** Removes `value`. Returns `true` if found. */\n delete(value: T): boolean {\n const index = this._items.findIndex((item) => Object.is(item, value));\n if (index === -1) return false;\n this._items.splice(index, 1);\n return true;\n }\n\n /** Removes all items. Uses splice to trigger proxy notification. */\n clear(): void {\n this._items.splice(0, this._items.length);\n }\n\n /** Returns an iterator over the values (same as `values()`, matching Set API). */\n keys(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over [value, value] pairs, matching the native Set API. */\n entries(): IterableIterator<[T, T]> {\n return this._items.map((v) => [v, v] as [T, T])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each item, matching the native `Set.forEach` signature. */\n forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void {\n for (const v of this._items) {\n callback(v, v, this);\n }\n }\n\n /** Enables `for...of` iteration over values. */\n [Symbol.iterator](): IterableIterator<T> {\n return this.values();\n }\n}\n\n// ── Factory functions ─────────────────────────────────────────────────────────\n\n/**\n * Creates a reactive Map-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of `[key, value]` pairs.\n */\nexport function reactiveMap<K, V>(\n initial?: Iterable<[K, V]>,\n): ReactiveMap<K, V> {\n return new ReactiveMap(initial);\n}\n\n/**\n * Creates a reactive Set-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of values.\n */\nexport function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T> {\n return new ReactiveSet(initial);\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as Snapshot } from "./types-B6RZUB86.cjs";
|
|
2
|
+
import { t as shallowEqual } from "./equality-C1s0kqxg.cjs";
|
|
2
3
|
|
|
3
4
|
//#region src/utils/internal/internal.d.ts
|
|
4
5
|
/**
|
|
@@ -162,16 +163,5 @@ declare function getVersion(proxy: object): number;
|
|
|
162
163
|
*/
|
|
163
164
|
declare function snapshot<T extends object>(proxyStore: T): Snapshot<T>;
|
|
164
165
|
//#endregion
|
|
165
|
-
//#region src/utils/equality/equality.d.ts
|
|
166
|
-
/**
|
|
167
|
-
* Shallow-equal comparison for objects and arrays.
|
|
168
|
-
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
169
|
-
*
|
|
170
|
-
* - Primitives compared with `Object.is`.
|
|
171
|
-
* - Arrays: length + element-wise `Object.is`.
|
|
172
|
-
* - Objects: key count + value-wise `Object.is`.
|
|
173
|
-
*/
|
|
174
|
-
declare function shallowEqual<T>(a: T, b: T): boolean;
|
|
175
|
-
//#endregion
|
|
176
166
|
export { type ReactiveMap, type ReactiveSet, type Snapshot, createClassyStore, getVersion, reactiveMap, reactiveSet, shallowEqual, snapshot, subscribe };
|
|
177
167
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/utils/internal/internal.ts","../src/collections/collections.ts","../src/core/core.ts","../src/snapshot/snapshot.ts"
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/utils/internal/internal.ts","../src/collections/collections.ts","../src/core/core.ts","../src/snapshot/snapshot.ts"],"mappings":";;;;;;;;AAOA;cAAa,SAAA;;;;;;AAAb;;;;;;;;ACUA;;cAAa,WAAA;EAAA,QACH,SAAA;EAGG;EAAX,QAAA,GAAW,CAAA,EAAG,CAAA;EAGkB;cAApB,OAAA,GAAU,QAAA,EAAU,CAAA,EAAG,CAAA;EAAb;EAAA,IAclB,IAAA,CAAA;EAKS;EAAb,GAAA,CAAI,GAAA,EAAK,CAAA,GAAI,CAAA;EAWJ;EALT,GAAA,CAAI,GAAA,EAAK,CAAA;EAgBG;EAXZ,GAAA,CAAI,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAA;EAwBX;EAbR,MAAA,CAAO,GAAA,EAAK,CAAA;EAkBF;EAVV,KAAA,CAAA;EAegC;EAVhC,IAAA,CAAA,GAAQ,gBAAA,CAAiB,CAAA;EAeC;EAV1B,MAAA,CAAA,GAAU,gBAAA,CAAiB,CAAA;EAU2B;EALtD,OAAA,CAAA,GAAW,gBAAA,EAAkB,CAAA,EAAG,CAAA;EAKU;EAA1C,OAAA,CAAQ,QAAA,GAAW,KAAA,EAAO,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAK,WAAA,CAAY,CAAA,EAAG,CAAA;EAOf;EAAA,CAAzC,MAAA,CAAO,QAAA,KAAa,gBAAA,EAAkB,CAAA,EAAG,CAAA;AAAA;;;;;;;;;;;;;;cAoB/B,WAAA;EAAA,QACH,SAAA;EA9EC;EAiFT,MAAA,EAAQ,CAAA;EAjFK;cAoFD,OAAA,GAAU,QAAA,CAAS,CAAA;EA9EtB;EAAA,IAyFL,IAAA,CAAA;EApFJ;EAyFA,GAAA,CAAI,KAAA,EAAO,CAAA;EAzFP;EA8FJ,GAAA,CAAI,KAAA,EAAO,CAAA;EA9FC;EAsGZ,MAAA,CAAO,KAAA,EAAO,CAAA;EA3FF;EAmGZ,KAAA,CAAA;EA3FA;EAgGA,IAAA,CAAA,GAAQ,gBAAA,CAAiB,CAAA;EA3FjB;EAgGR,MAAA,CAAA,GAAU,gBAAA,CAAiB,CAAA;EA3F3B;EAgGA,OAAA,CAAA,GAAW,gBAAA,EAAkB,CAAA,EAAG,CAAA;EAhGL;EAqG3B,OAAA,CAAQ,QAAA,GAAW,KAAA,EAAO,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAK,WAAA,CAAY,CAAA;EAhG3C;EAAA,CAuGV,MAAA,CAAO,QAAA,KAAa,gBAAA,CAAiB,CAAA;AAAA;;;;;;;iBAaxB,WAAA,MAAA,CACd,OAAA,GAAU,QAAA,EAAU,CAAA,EAAG,CAAA,KACtB,WAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;iBAUF,WAAA,GAAA,CAAe,OAAA,GAAU,QAAA,CAAS,CAAA,IAAK,WAAA,CAAY,CAAA;;;;;;;;;AAvMnE;;;;;;;;;;;iBCiTgB,iBAAA,kBAAA,CAAoC,QAAA,EAAU,CAAA,GAAI,CAAA;;;;;;;;;iBAYlD,SAAA,CAAU,KAAA,UAAe,QAAA;;;;;;;;iBAkBzB,UAAA,CAAW,KAAA;;;;;;AFzV3B;;;;;;;;ACUA;;;;;iBEwUgB,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { t as Snapshot } from "./types-
|
|
1
|
+
import { t as Snapshot } from "./types-Cf8Fp7kA.mjs";
|
|
2
|
+
import { t as shallowEqual } from "./equality-5F2bPn7E.mjs";
|
|
2
3
|
|
|
3
4
|
//#region src/utils/internal/internal.d.ts
|
|
4
5
|
/**
|
|
@@ -162,16 +163,5 @@ declare function getVersion(proxy: object): number;
|
|
|
162
163
|
*/
|
|
163
164
|
declare function snapshot<T extends object>(proxyStore: T): Snapshot<T>;
|
|
164
165
|
//#endregion
|
|
165
|
-
//#region src/utils/equality/equality.d.ts
|
|
166
|
-
/**
|
|
167
|
-
* Shallow-equal comparison for objects and arrays.
|
|
168
|
-
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
169
|
-
*
|
|
170
|
-
* - Primitives compared with `Object.is`.
|
|
171
|
-
* - Arrays: length + element-wise `Object.is`.
|
|
172
|
-
* - Objects: key count + value-wise `Object.is`.
|
|
173
|
-
*/
|
|
174
|
-
declare function shallowEqual<T>(a: T, b: T): boolean;
|
|
175
|
-
//#endregion
|
|
176
166
|
export { type ReactiveMap, type ReactiveSet, type Snapshot, createClassyStore, getVersion, reactiveMap, reactiveSet, shallowEqual, snapshot, subscribe };
|
|
177
167
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/utils/internal/internal.ts","../src/collections/collections.ts","../src/core/core.ts","../src/snapshot/snapshot.ts"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/utils/internal/internal.ts","../src/collections/collections.ts","../src/core/core.ts","../src/snapshot/snapshot.ts"],"mappings":";;;;;;;;AAOA;cAAa,SAAA;;;;;;AAAb;;;;;;;;ACUA;;cAAa,WAAA;EAAA,QACH,SAAA;EAGG;EAAX,QAAA,GAAW,CAAA,EAAG,CAAA;EAGkB;cAApB,OAAA,GAAU,QAAA,EAAU,CAAA,EAAG,CAAA;EAAb;EAAA,IAclB,IAAA,CAAA;EAKS;EAAb,GAAA,CAAI,GAAA,EAAK,CAAA,GAAI,CAAA;EAWJ;EALT,GAAA,CAAI,GAAA,EAAK,CAAA;EAgBG;EAXZ,GAAA,CAAI,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAA;EAwBX;EAbR,MAAA,CAAO,GAAA,EAAK,CAAA;EAkBF;EAVV,KAAA,CAAA;EAegC;EAVhC,IAAA,CAAA,GAAQ,gBAAA,CAAiB,CAAA;EAeC;EAV1B,MAAA,CAAA,GAAU,gBAAA,CAAiB,CAAA;EAU2B;EALtD,OAAA,CAAA,GAAW,gBAAA,EAAkB,CAAA,EAAG,CAAA;EAKU;EAA1C,OAAA,CAAQ,QAAA,GAAW,KAAA,EAAO,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAK,WAAA,CAAY,CAAA,EAAG,CAAA;EAOf;EAAA,CAAzC,MAAA,CAAO,QAAA,KAAa,gBAAA,EAAkB,CAAA,EAAG,CAAA;AAAA;;;;;;;;;;;;;;cAoB/B,WAAA;EAAA,QACH,SAAA;EA9EC;EAiFT,MAAA,EAAQ,CAAA;EAjFK;cAoFD,OAAA,GAAU,QAAA,CAAS,CAAA;EA9EtB;EAAA,IAyFL,IAAA,CAAA;EApFJ;EAyFA,GAAA,CAAI,KAAA,EAAO,CAAA;EAzFP;EA8FJ,GAAA,CAAI,KAAA,EAAO,CAAA;EA9FC;EAsGZ,MAAA,CAAO,KAAA,EAAO,CAAA;EA3FF;EAmGZ,KAAA,CAAA;EA3FA;EAgGA,IAAA,CAAA,GAAQ,gBAAA,CAAiB,CAAA;EA3FjB;EAgGR,MAAA,CAAA,GAAU,gBAAA,CAAiB,CAAA;EA3F3B;EAgGA,OAAA,CAAA,GAAW,gBAAA,EAAkB,CAAA,EAAG,CAAA;EAhGL;EAqG3B,OAAA,CAAQ,QAAA,GAAW,KAAA,EAAO,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAK,WAAA,CAAY,CAAA;EAhG3C;EAAA,CAuGV,MAAA,CAAO,QAAA,KAAa,gBAAA,CAAiB,CAAA;AAAA;;;;;;;iBAaxB,WAAA,MAAA,CACd,OAAA,GAAU,QAAA,EAAU,CAAA,EAAG,CAAA,KACtB,WAAA,CAAY,CAAA,EAAG,CAAA;;;;;;;iBAUF,WAAA,GAAA,CAAe,OAAA,GAAU,QAAA,CAAS,CAAA,IAAK,WAAA,CAAY,CAAA;;;;;;;;;AAvMnE;;;;;;;;;;;iBCiTgB,iBAAA,kBAAA,CAAoC,QAAA,EAAU,CAAA,GAAI,CAAA;;;;;;;;;iBAYlD,SAAA,CAAU,KAAA,UAAe,QAAA;;;;;;;;iBAkBzB,UAAA,CAAW,KAAA;;;;;;AFzV3B;;;;;;;;ACUA;;;;;iBEwUgB,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as subscribe, i as getVersion, n as createClassyStore, o as PROXYABLE, t as snapshot } from "./snapshot-
|
|
1
|
+
import { a as subscribe, i as getVersion, n as createClassyStore, o as PROXYABLE, t as snapshot } from "./snapshot-COzEerMu.mjs";
|
|
2
|
+
import { t as shallowEqual } from "./equality-BA46H9AL.mjs";
|
|
2
3
|
|
|
3
4
|
//#region src/collections/collections.ts
|
|
4
5
|
/**
|
|
@@ -165,31 +166,6 @@ function reactiveSet(initial) {
|
|
|
165
166
|
return new ReactiveSet(initial);
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
//#endregion
|
|
169
|
-
//#region src/utils/equality/equality.ts
|
|
170
|
-
/**
|
|
171
|
-
* Shallow-equal comparison for objects and arrays.
|
|
172
|
-
* Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.
|
|
173
|
-
*
|
|
174
|
-
* - Primitives compared with `Object.is`.
|
|
175
|
-
* - Arrays: length + element-wise `Object.is`.
|
|
176
|
-
* - Objects: key count + value-wise `Object.is`.
|
|
177
|
-
*/
|
|
178
|
-
function shallowEqual(a, b) {
|
|
179
|
-
if (Object.is(a, b)) return true;
|
|
180
|
-
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
181
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
182
|
-
if (a.length !== b.length) return false;
|
|
183
|
-
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
const keysA = Object.keys(a);
|
|
187
|
-
const keysB = Object.keys(b);
|
|
188
|
-
if (keysA.length !== keysB.length) return false;
|
|
189
|
-
for (const key of keysA) if (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) return false;
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
169
|
//#endregion
|
|
194
170
|
export { createClassyStore, getVersion, reactiveMap, reactiveSet, shallowEqual, snapshot, subscribe };
|
|
195
171
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/collections/collections.ts","../src/utils/equality/equality.ts"],"sourcesContent":["import {PROXYABLE} from '../utils/internal/internal';\n\n// ── ReactiveMap ───────────────────────────────────────────────────────────────\n\n/**\n * A Map-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.set()` would be invisible to the store. `ReactiveMap` solves this by\n * storing entries in a plain array (`_entries`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ users: reactiveMap<string, User>() });\n * myStore.users.set('id1', { name: 'Alice' }); // reactive\n * ```\n */\nexport class ReactiveMap<K, V> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _entries: [K, V][] = [];\n\n /** Deduplicates initial entries by key (last value wins, matching native `Map`). */\n constructor(initial?: Iterable<[K, V]>) {\n if (initial) {\n for (const [k, v] of initial) {\n const index = this._entries.findIndex(([ek]) => Object.is(ek, k));\n if (index !== -1) {\n this._entries[index] = [k, v];\n } else {\n this._entries.push([k, v]);\n }\n }\n }\n }\n\n /** Returns the number of entries. */\n get size(): number {\n return this._entries.length;\n }\n\n /** Returns the value for `key`, or `undefined`. O(n) linear scan. */\n get(key: K): V | undefined {\n const entry = this._entries.find(([k]) => Object.is(k, key));\n return entry ? entry[1] : undefined;\n }\n\n /** Returns `true` if `key` exists. O(n) linear scan. */\n has(key: K): boolean {\n return this._entries.some(([k]) => Object.is(k, key));\n }\n\n /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */\n set(key: K, value: V): this {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index !== -1) {\n this._entries[index] = [key, value];\n } else {\n this._entries.push([key, value]);\n }\n return this;\n }\n\n /** Removes the entry for `key`. Returns `true` if found. */\n delete(key: K): boolean {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index === -1) return false;\n this._entries.splice(index, 1);\n return true;\n }\n\n /** Removes all entries. Uses splice to trigger proxy notification. */\n clear(): void {\n this._entries.splice(0, this._entries.length);\n }\n\n /** Returns an iterator over the keys. */\n keys(): IterableIterator<K> {\n return this._entries.map(([k]) => k)[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<V> {\n return this._entries.map(([, v]) => v)[Symbol.iterator]();\n }\n\n /** Returns an iterator over [key, value] pairs. */\n entries(): IterableIterator<[K, V]> {\n return this._entries.map(([k, v]) => [k, v] as [K, V])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */\n forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void {\n for (const [k, v] of this._entries) {\n callback(v, k, this);\n }\n }\n\n /** Enables `for...of` iteration over [key, value] pairs. */\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n}\n\n// ── ReactiveSet ───────────────────────────────────────────────────────────────\n\n/**\n * A Set-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.add()` would be invisible to the store. `ReactiveSet` solves this by\n * storing items in a plain array (`_items`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ tags: reactiveSet<string>(['urgent']) });\n * myStore.tags.add('bug'); // reactive\n * ```\n */\nexport class ReactiveSet<T> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _items: T[] = [];\n\n /** Deduplicates initial values using `Object.is` comparison. */\n constructor(initial?: Iterable<T>) {\n if (initial) {\n for (const v of initial) {\n if (!this._items.some((item) => Object.is(item, v))) {\n this._items.push(v);\n }\n }\n }\n }\n\n /** Returns the number of unique items. */\n get size(): number {\n return this._items.length;\n }\n\n /** Returns `true` if `value` exists. O(n) linear scan. */\n has(value: T): boolean {\n return this._items.some((item) => Object.is(item, value));\n }\n\n /** Adds `value` if not already present (no-op for duplicates). */\n add(value: T): this {\n if (!this.has(value)) {\n this._items.push(value);\n }\n return this;\n }\n\n /** Removes `value`. Returns `true` if found. */\n delete(value: T): boolean {\n const index = this._items.findIndex((item) => Object.is(item, value));\n if (index === -1) return false;\n this._items.splice(index, 1);\n return true;\n }\n\n /** Removes all items. Uses splice to trigger proxy notification. */\n clear(): void {\n this._items.splice(0, this._items.length);\n }\n\n /** Returns an iterator over the values (same as `values()`, matching Set API). */\n keys(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over [value, value] pairs, matching the native Set API. */\n entries(): IterableIterator<[T, T]> {\n return this._items.map((v) => [v, v] as [T, T])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each item, matching the native `Set.forEach` signature. */\n forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void {\n for (const v of this._items) {\n callback(v, v, this);\n }\n }\n\n /** Enables `for...of` iteration over values. */\n [Symbol.iterator](): IterableIterator<T> {\n return this.values();\n }\n}\n\n// ── Factory functions ─────────────────────────────────────────────────────────\n\n/**\n * Creates a reactive Map-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of `[key, value]` pairs.\n */\nexport function reactiveMap<K, V>(\n initial?: Iterable<[K, V]>,\n): ReactiveMap<K, V> {\n return new ReactiveMap(initial);\n}\n\n/**\n * Creates a reactive Set-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of values.\n */\nexport function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T> {\n return new ReactiveSet(initial);\n}\n","/**\n * Shallow-equal comparison for objects and arrays.\n * Useful as a custom `isEqual` for `useStore` selectors that return objects/arrays.\n *\n * - Primitives compared with `Object.is`.\n * - Arrays: length + element-wise `Object.is`.\n * - Objects: key count + value-wise `Object.is`.\n */\nexport function shallowEqual<T>(a: T, b: T): boolean {\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 }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (\n !Object.hasOwn(b, key) ||\n !Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n )\n ) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/collections/collections.ts"],"sourcesContent":["import {PROXYABLE} from '../utils/internal/internal';\n\n// ── ReactiveMap ───────────────────────────────────────────────────────────────\n\n/**\n * A Map-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Map` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.set()` would be invisible to the store. `ReactiveMap` solves this by\n * storing entries in a plain array (`_entries`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ users: reactiveMap<string, User>() });\n * myStore.users.set('id1', { name: 'Alice' }); // reactive\n * ```\n */\nexport class ReactiveMap<K, V> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _entries: [K, V][] = [];\n\n /** Deduplicates initial entries by key (last value wins, matching native `Map`). */\n constructor(initial?: Iterable<[K, V]>) {\n if (initial) {\n for (const [k, v] of initial) {\n const index = this._entries.findIndex(([ek]) => Object.is(ek, k));\n if (index !== -1) {\n this._entries[index] = [k, v];\n } else {\n this._entries.push([k, v]);\n }\n }\n }\n }\n\n /** Returns the number of entries. */\n get size(): number {\n return this._entries.length;\n }\n\n /** Returns the value for `key`, or `undefined`. O(n) linear scan. */\n get(key: K): V | undefined {\n const entry = this._entries.find(([k]) => Object.is(k, key));\n return entry ? entry[1] : undefined;\n }\n\n /** Returns `true` if `key` exists. O(n) linear scan. */\n has(key: K): boolean {\n return this._entries.some(([k]) => Object.is(k, key));\n }\n\n /** Sets `key` to `value`. Updates in-place if key exists, appends otherwise. */\n set(key: K, value: V): this {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index !== -1) {\n this._entries[index] = [key, value];\n } else {\n this._entries.push([key, value]);\n }\n return this;\n }\n\n /** Removes the entry for `key`. Returns `true` if found. */\n delete(key: K): boolean {\n const index = this._entries.findIndex(([k]) => Object.is(k, key));\n if (index === -1) return false;\n this._entries.splice(index, 1);\n return true;\n }\n\n /** Removes all entries. Uses splice to trigger proxy notification. */\n clear(): void {\n this._entries.splice(0, this._entries.length);\n }\n\n /** Returns an iterator over the keys. */\n keys(): IterableIterator<K> {\n return this._entries.map(([k]) => k)[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<V> {\n return this._entries.map(([, v]) => v)[Symbol.iterator]();\n }\n\n /** Returns an iterator over [key, value] pairs. */\n entries(): IterableIterator<[K, V]> {\n return this._entries.map(([k, v]) => [k, v] as [K, V])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each entry, matching the native `Map.forEach` signature. */\n forEach(callback: (value: V, key: K, map: ReactiveMap<K, V>) => void): void {\n for (const [k, v] of this._entries) {\n callback(v, k, this);\n }\n }\n\n /** Enables `for...of` iteration over [key, value] pairs. */\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n}\n\n// ── ReactiveSet ───────────────────────────────────────────────────────────────\n\n/**\n * A Set-like class backed by a plain array so `createClassyStore()` can proxy mutations.\n *\n * Native `Set` uses internal slots that ES6 Proxy can't intercept, so mutations\n * like `.add()` would be invisible to the store. `ReactiveSet` solves this by\n * storing items in a plain array (`_items`) that the proxy can track.\n *\n * Usage:\n * ```ts\n * const myStore = createClassyStore({ tags: reactiveSet<string>(['urgent']) });\n * myStore.tags.add('bug'); // reactive\n * ```\n */\nexport class ReactiveSet<T> {\n static [PROXYABLE] = true;\n\n /** @internal Backing storage — proxied by store(). */\n _items: T[] = [];\n\n /** Deduplicates initial values using `Object.is` comparison. */\n constructor(initial?: Iterable<T>) {\n if (initial) {\n for (const v of initial) {\n if (!this._items.some((item) => Object.is(item, v))) {\n this._items.push(v);\n }\n }\n }\n }\n\n /** Returns the number of unique items. */\n get size(): number {\n return this._items.length;\n }\n\n /** Returns `true` if `value` exists. O(n) linear scan. */\n has(value: T): boolean {\n return this._items.some((item) => Object.is(item, value));\n }\n\n /** Adds `value` if not already present (no-op for duplicates). */\n add(value: T): this {\n if (!this.has(value)) {\n this._items.push(value);\n }\n return this;\n }\n\n /** Removes `value`. Returns `true` if found. */\n delete(value: T): boolean {\n const index = this._items.findIndex((item) => Object.is(item, value));\n if (index === -1) return false;\n this._items.splice(index, 1);\n return true;\n }\n\n /** Removes all items. Uses splice to trigger proxy notification. */\n clear(): void {\n this._items.splice(0, this._items.length);\n }\n\n /** Returns an iterator over the values (same as `values()`, matching Set API). */\n keys(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over the values. */\n values(): IterableIterator<T> {\n return this._items[Symbol.iterator]();\n }\n\n /** Returns an iterator over [value, value] pairs, matching the native Set API. */\n entries(): IterableIterator<[T, T]> {\n return this._items.map((v) => [v, v] as [T, T])[Symbol.iterator]();\n }\n\n /** Calls `callback` for each item, matching the native `Set.forEach` signature. */\n forEach(callback: (value: T, key: T, set: ReactiveSet<T>) => void): void {\n for (const v of this._items) {\n callback(v, v, this);\n }\n }\n\n /** Enables `for...of` iteration over values. */\n [Symbol.iterator](): IterableIterator<T> {\n return this.values();\n }\n}\n\n// ── Factory functions ─────────────────────────────────────────────────────────\n\n/**\n * Creates a reactive Map-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of `[key, value]` pairs.\n */\nexport function reactiveMap<K, V>(\n initial?: Iterable<[K, V]>,\n): ReactiveMap<K, V> {\n return new ReactiveMap(initial);\n}\n\n/**\n * Creates a reactive Set-like collection backed by a plain array.\n * Wrap the parent object with `createClassyStore()` for full reactivity.\n *\n * @param initial - Optional iterable of values.\n */\nexport function reactiveSet<T>(initial?: Iterable<T>): ReactiveSet<T> {\n return new ReactiveSet(initial);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,IAAa,cAAb,MAA+B;CAC7B,QAAQ,aAAa;;CAGrB,WAAqB,EAAE;;CAGvB,YAAY,SAA4B;AACtC,MAAI,QACF,MAAK,MAAM,CAAC,GAAG,MAAM,SAAS;GAC5B,MAAM,QAAQ,KAAK,SAAS,WAAW,CAAC,QAAQ,OAAO,GAAG,IAAI,EAAE,CAAC;AACjE,OAAI,UAAU,GACZ,MAAK,SAAS,SAAS,CAAC,GAAG,EAAE;OAE7B,MAAK,SAAS,KAAK,CAAC,GAAG,EAAE,CAAC;;;;CAOlC,IAAI,OAAe;AACjB,SAAO,KAAK,SAAS;;;CAIvB,IAAI,KAAuB;EACzB,MAAM,QAAQ,KAAK,SAAS,MAAM,CAAC,OAAO,OAAO,GAAG,GAAG,IAAI,CAAC;AAC5D,SAAO,QAAQ,MAAM,KAAK;;;CAI5B,IAAI,KAAiB;AACnB,SAAO,KAAK,SAAS,MAAM,CAAC,OAAO,OAAO,GAAG,GAAG,IAAI,CAAC;;;CAIvD,IAAI,KAAQ,OAAgB;EAC1B,MAAM,QAAQ,KAAK,SAAS,WAAW,CAAC,OAAO,OAAO,GAAG,GAAG,IAAI,CAAC;AACjE,MAAI,UAAU,GACZ,MAAK,SAAS,SAAS,CAAC,KAAK,MAAM;MAEnC,MAAK,SAAS,KAAK,CAAC,KAAK,MAAM,CAAC;AAElC,SAAO;;;CAIT,OAAO,KAAiB;EACtB,MAAM,QAAQ,KAAK,SAAS,WAAW,CAAC,OAAO,OAAO,GAAG,GAAG,IAAI,CAAC;AACjE,MAAI,UAAU,GAAI,QAAO;AACzB,OAAK,SAAS,OAAO,OAAO,EAAE;AAC9B,SAAO;;;CAIT,QAAc;AACZ,OAAK,SAAS,OAAO,GAAG,KAAK,SAAS,OAAO;;;CAI/C,OAA4B;AAC1B,SAAO,KAAK,SAAS,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,WAAW;;;CAIzD,SAA8B;AAC5B,SAAO,KAAK,SAAS,KAAK,GAAG,OAAO,EAAE,CAAC,OAAO,WAAW;;;CAI3D,UAAoC;AAClC,SAAO,KAAK,SAAS,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAW,CAAC,OAAO,WAAW;;;CAI3E,QAAQ,UAAoE;AAC1E,OAAK,MAAM,CAAC,GAAG,MAAM,KAAK,SACxB,UAAS,GAAG,GAAG,KAAK;;;CAKxB,CAAC,OAAO,YAAsC;AAC5C,SAAO,KAAK,SAAS;;;;;;;;;;;;;;;;AAmBzB,IAAa,cAAb,MAA4B;CAC1B,QAAQ,aAAa;;CAGrB,SAAc,EAAE;;CAGhB,YAAY,SAAuB;AACjC,MAAI,SACF;QAAK,MAAM,KAAK,QACd,KAAI,CAAC,KAAK,OAAO,MAAM,SAAS,OAAO,GAAG,MAAM,EAAE,CAAC,CACjD,MAAK,OAAO,KAAK,EAAE;;;;CAO3B,IAAI,OAAe;AACjB,SAAO,KAAK,OAAO;;;CAIrB,IAAI,OAAmB;AACrB,SAAO,KAAK,OAAO,MAAM,SAAS,OAAO,GAAG,MAAM,MAAM,CAAC;;;CAI3D,IAAI,OAAgB;AAClB,MAAI,CAAC,KAAK,IAAI,MAAM,CAClB,MAAK,OAAO,KAAK,MAAM;AAEzB,SAAO;;;CAIT,OAAO,OAAmB;EACxB,MAAM,QAAQ,KAAK,OAAO,WAAW,SAAS,OAAO,GAAG,MAAM,MAAM,CAAC;AACrE,MAAI,UAAU,GAAI,QAAO;AACzB,OAAK,OAAO,OAAO,OAAO,EAAE;AAC5B,SAAO;;;CAIT,QAAc;AACZ,OAAK,OAAO,OAAO,GAAG,KAAK,OAAO,OAAO;;;CAI3C,OAA4B;AAC1B,SAAO,KAAK,OAAO,OAAO,WAAW;;;CAIvC,SAA8B;AAC5B,SAAO,KAAK,OAAO,OAAO,WAAW;;;CAIvC,UAAoC;AAClC,SAAO,KAAK,OAAO,KAAK,MAAM,CAAC,GAAG,EAAE,CAAW,CAAC,OAAO,WAAW;;;CAIpE,QAAQ,UAAiE;AACvE,OAAK,MAAM,KAAK,KAAK,OACnB,UAAS,GAAG,GAAG,KAAK;;;CAKxB,CAAC,OAAO,YAAiC;AACvC,SAAO,KAAK,QAAQ;;;;;;;;;AAYxB,SAAgB,YACd,SACmB;AACnB,QAAO,IAAI,YAAY,QAAQ;;;;;;;;AASjC,SAAgB,YAAe,SAAuC;AACpE,QAAO,IAAI,YAAY,QAAQ"}
|
package/dist/react/react.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_snapshot = require('../snapshot-
|
|
2
|
+
const require_snapshot = require('../snapshot-CbVbxG7s.cjs');
|
|
3
3
|
let proxy_compare = require("proxy-compare");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
|
|
@@ -55,7 +55,36 @@ function getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wra
|
|
|
55
55
|
wrappedRef.current = wrapped;
|
|
56
56
|
return wrapped;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a component-scoped reactive store that lives for the lifetime of the
|
|
60
|
+
* component. When the component unmounts, the store becomes unreferenced and is
|
|
61
|
+
* garbage collected (all internal bookkeeping uses `WeakMap`).
|
|
62
|
+
*
|
|
63
|
+
* The factory function runs **once** per mount (via `useState` initializer).
|
|
64
|
+
* Each component instance gets its own isolated store.
|
|
65
|
+
*
|
|
66
|
+
* Use the returned proxy with `useStore()` to read state in the same component
|
|
67
|
+
* or pass it down via props/context to share within a subtree.
|
|
68
|
+
*
|
|
69
|
+
* @param factory - A function that returns a class instance (or plain object).
|
|
70
|
+
* Called once per component mount.
|
|
71
|
+
* @returns A reactive store proxy scoped to the component's lifetime.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* function Counter() {
|
|
76
|
+
* const store = useLocalStore(() => new CounterStore());
|
|
77
|
+
* const count = useStore(store, s => s.count);
|
|
78
|
+
* return <button onClick={() => store.increment()}>{count}</button>;
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
function useLocalStore(factory) {
|
|
83
|
+
const [store] = (0, react.useState)(() => require_snapshot.createClassyStore(factory()));
|
|
84
|
+
return store;
|
|
85
|
+
}
|
|
58
86
|
|
|
59
87
|
//#endregion
|
|
88
|
+
exports.useLocalStore = useLocalStore;
|
|
60
89
|
exports.useStore = useStore;
|
|
61
90
|
//# sourceMappingURL=react.cjs.map
|
package/dist/react/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.cjs","names":["subscribe","coreSubscribe","snapshot"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useSyncExternalStore} from 'react';\nimport {subscribe as coreSubscribe
|
|
1
|
+
{"version":3,"file":"react.cjs","names":["subscribe","coreSubscribe","snapshot","createClassyStore"],"sources":["../../src/react/react.ts"],"sourcesContent":["import {createProxy, isChanged} from 'proxy-compare';\nimport {useCallback, useRef, useState, useSyncExternalStore} from 'react';\nimport {\n subscribe as coreSubscribe,\n createClassyStore,\n getInternal,\n} from '../core/core';\nimport {snapshot} from '../snapshot/snapshot';\nimport type {Snapshot} from '../types';\n\n// ── Overloads ─────────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to a store proxy with an explicit selector.\n *\n * Re-renders only when the selected value changes (compared via `Object.is`\n * by default, or a custom `isEqual`).\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n * @param selector - Picks data from the immutable snapshot.\n * @param isEqual - Optional custom equality function (default: `Object.is`).\n */\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S;\n\n/**\n * Subscribe to a store proxy **without** a selector (auto-tracked mode).\n *\n * Returns a `proxy-compare` tracking proxy over the immutable snapshot.\n * The component only re-renders when a property it actually read changes.\n *\n * @param proxyStore - A reactive proxy created by `store()`.\n */\nexport function useStore<T extends object>(proxyStore: T): Snapshot<T>;\n\n// ── Implementation ────────────────────────────────────────────────────────────\n\nexport function useStore<T extends object, S>(\n proxyStore: T,\n selector?: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): Snapshot<T> | S {\n // Validate that the argument is actually a store proxy (throws if not).\n getInternal(proxyStore);\n\n // Stable subscribe function (internal identity never changes for a given store).\n const subscribe = useCallback(\n (onStoreChange: () => void) => coreSubscribe(proxyStore, onStoreChange),\n [proxyStore],\n );\n\n // ── Refs used by both modes (always allocated to satisfy Rules of Hooks) ──\n\n // Selector mode refs\n const snapRef = useRef<Snapshot<T> | undefined>(undefined);\n const resultRef = useRef<S | undefined>(undefined);\n\n // Auto-track mode refs\n const affected = useRef(new WeakMap<object, unknown>()).current;\n const proxyCache = useRef(new WeakMap<object, unknown>()).current;\n const prevSnapRef = useRef<Snapshot<T> | undefined>(undefined);\n const wrappedRef = useRef<Snapshot<T> | undefined>(undefined);\n\n // ── Single getSnapshot for useSyncExternalStore ───────────────────────────\n\n const getSnapshot = (): Snapshot<T> | S =>\n selector\n ? getSelectorSnapshot(proxyStore, snapRef, resultRef, selector, isEqual)\n : getAutoTrackSnapshot(\n proxyStore,\n affected,\n proxyCache,\n prevSnapRef,\n wrappedRef,\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n// ── Selector mode logic (pure function, no hooks) ─────────────────────────────\n\n/**\n * `getSnapshot` implementation for selector mode.\n *\n * Fast-paths when the snapshot reference hasn't changed (O(1)). Otherwise\n * runs the selector against the new snapshot and compares the result to the\n * previous one via `Object.is` (or a custom `isEqual`). Returns the previous\n * result reference when equal, preventing unnecessary React re-renders.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getSelectorSnapshot<T extends object, S>(\n proxyStore: T,\n snapRef: React.RefObject<Snapshot<T> | undefined>,\n resultRef: React.RefObject<S | undefined>,\n selector: (snap: Snapshot<T>) => S,\n isEqual?: (a: S, b: S) => boolean,\n): S {\n const nextSnap = snapshot(proxyStore);\n\n // Fast path: same snapshot reference → same result.\n if (snapRef.current === nextSnap && resultRef.current !== undefined) {\n return resultRef.current;\n }\n\n const nextResult = selector(nextSnap);\n snapRef.current = nextSnap;\n\n // Check equality with previous result.\n if (\n resultRef.current !== undefined &&\n (isEqual\n ? isEqual(resultRef.current, nextResult)\n : Object.is(resultRef.current, nextResult))\n ) {\n return resultRef.current;\n }\n\n resultRef.current = nextResult;\n return nextResult;\n}\n\n// ── Auto-tracked (selectorless) mode logic (pure function, no hooks) ──────────\n\n/**\n * `getSnapshot` implementation for auto-tracked (selectorless) mode.\n *\n * Uses `proxy-compare` to diff only the properties the component actually read.\n * If the snapshot reference is the same, returns the cached tracking proxy.\n * If the snapshot changed but no tracked property differs (`isChanged` returns\n * false), also returns the cached proxy -- avoiding re-render. Only when a\n * relevant property changed does it create a new `createProxy` wrapper.\n *\n * Pure function -- no hooks, safe to call from `useSyncExternalStore`.\n */\nfunction getAutoTrackSnapshot<T extends object>(\n proxyStore: T,\n affected: WeakMap<object, unknown>,\n proxyCache: WeakMap<object, unknown>,\n prevSnapRef: React.RefObject<Snapshot<T> | undefined>,\n wrappedRef: React.RefObject<Snapshot<T> | undefined>,\n): Snapshot<T> {\n const nextSnap = snapshot(proxyStore);\n\n // If the raw snapshot is the same reference, nothing changed.\n if (prevSnapRef.current === nextSnap) {\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Check if any property the component actually read has changed.\n if (\n prevSnapRef.current !== undefined &&\n !isChanged(prevSnapRef.current, nextSnap, affected)\n ) {\n // No property the component cares about changed → return same wrapped proxy.\n return wrappedRef.current as Snapshot<T>;\n }\n\n // Something relevant changed — create a new tracking proxy.\n prevSnapRef.current = nextSnap;\n const wrapped = createProxy(nextSnap, affected, proxyCache) as Snapshot<T>;\n wrappedRef.current = wrapped;\n return wrapped;\n}\n\n// ── Component-scoped store ────────────────────────────────────────────────────\n\n/**\n * Create a component-scoped reactive store that lives for the lifetime of the\n * component. When the component unmounts, the store becomes unreferenced and is\n * garbage collected (all internal bookkeeping uses `WeakMap`).\n *\n * The factory function runs **once** per mount (via `useState` initializer).\n * Each component instance gets its own isolated store.\n *\n * Use the returned proxy with `useStore()` to read state in the same component\n * or pass it down via props/context to share within a subtree.\n *\n * @param factory - A function that returns a class instance (or plain object).\n * Called once per component mount.\n * @returns A reactive store proxy scoped to the component's lifetime.\n *\n * @example\n * ```tsx\n * function Counter() {\n * const store = useLocalStore(() => new CounterStore());\n * const count = useStore(store, s => s.count);\n * return <button onClick={() => store.increment()}>{count}</button>;\n * }\n * ```\n */\nexport function useLocalStore<T extends object>(factory: () => T): T {\n const [store] = useState(() => createClassyStore(factory()));\n return store;\n}\n"],"mappings":";;;;;;AAwCA,SAAgB,SACd,YACA,UACA,SACiB;AAEjB,8BAAY,WAAW;CAGvB,MAAMA,sCACH,kBAA8BC,2BAAc,YAAY,cAAc,EACvE,CAAC,WAAW,CACb;CAKD,MAAM,4BAA0C,OAAU;CAC1D,MAAM,8BAAkC,OAAU;CAGlD,MAAM,6CAAkB,IAAI,SAA0B,CAAC,CAAC;CACxD,MAAM,+CAAoB,IAAI,SAA0B,CAAC,CAAC;CAC1D,MAAM,gCAA8C,OAAU;CAC9D,MAAM,+BAA6C,OAAU;CAI7D,MAAM,oBACJ,WACI,oBAAoB,YAAY,SAAS,WAAW,UAAU,QAAQ,GACtE,qBACE,YACA,UACA,YACA,aACA,WACD;AAEP,wCAA4BD,aAAW,aAAa,YAAY;;;;;;;;;;;;AAelE,SAAS,oBACP,YACA,SACA,WACA,UACA,SACG;CACH,MAAM,WAAWE,0BAAS,WAAW;AAGrC,KAAI,QAAQ,YAAY,YAAY,UAAU,YAAY,OACxD,QAAO,UAAU;CAGnB,MAAM,aAAa,SAAS,SAAS;AACrC,SAAQ,UAAU;AAGlB,KACE,UAAU,YAAY,WACrB,UACG,QAAQ,UAAU,SAAS,WAAW,GACtC,OAAO,GAAG,UAAU,SAAS,WAAW,EAE5C,QAAO,UAAU;AAGnB,WAAU,UAAU;AACpB,QAAO;;;;;;;;;;;;;AAgBT,SAAS,qBACP,YACA,UACA,YACA,aACA,YACa;CACb,MAAM,WAAWA,0BAAS,WAAW;AAGrC,KAAI,YAAY,YAAY,SAC1B,QAAO,WAAW;AAIpB,KACE,YAAY,YAAY,UACxB,8BAAW,YAAY,SAAS,UAAU,SAAS,CAGnD,QAAO,WAAW;AAIpB,aAAY,UAAU;CACtB,MAAM,yCAAsB,UAAU,UAAU,WAAW;AAC3D,YAAW,UAAU;AACrB,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,cAAgC,SAAqB;CACnE,MAAM,CAAC,mCAAwBC,mCAAkB,SAAS,CAAC,CAAC;AAC5D,QAAO"}
|
package/dist/react/react.d.cts
CHANGED
|
@@ -21,6 +21,31 @@ declare function useStore<T extends object, S>(proxyStore: T, selector: (snap: S
|
|
|
21
21
|
* @param proxyStore - A reactive proxy created by `store()`.
|
|
22
22
|
*/
|
|
23
23
|
declare function useStore<T extends object>(proxyStore: T): Snapshot<T>;
|
|
24
|
+
/**
|
|
25
|
+
* Create a component-scoped reactive store that lives for the lifetime of the
|
|
26
|
+
* component. When the component unmounts, the store becomes unreferenced and is
|
|
27
|
+
* garbage collected (all internal bookkeeping uses `WeakMap`).
|
|
28
|
+
*
|
|
29
|
+
* The factory function runs **once** per mount (via `useState` initializer).
|
|
30
|
+
* Each component instance gets its own isolated store.
|
|
31
|
+
*
|
|
32
|
+
* Use the returned proxy with `useStore()` to read state in the same component
|
|
33
|
+
* or pass it down via props/context to share within a subtree.
|
|
34
|
+
*
|
|
35
|
+
* @param factory - A function that returns a class instance (or plain object).
|
|
36
|
+
* Called once per component mount.
|
|
37
|
+
* @returns A reactive store proxy scoped to the component's lifetime.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* function Counter() {
|
|
42
|
+
* const store = useLocalStore(() => new CounterStore());
|
|
43
|
+
* const count = useStore(store, s => s.count);
|
|
44
|
+
* return <button onClick={() => store.increment()}>{count}</button>;
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function useLocalStore<T extends object>(factory: () => T): T;
|
|
24
49
|
//#endregion
|
|
25
|
-
export { useStore };
|
|
50
|
+
export { useLocalStore, useStore };
|
|
26
51
|
//# sourceMappingURL=react.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.cts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"react.d.cts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAsBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA;;;;;;;;;;;;AAApE;;;;;;;;;;;;;iBA8JgB,aAAA,kBAAA,CAAgC,OAAA,QAAe,CAAA,GAAI,CAAA"}
|
package/dist/react/react.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Snapshot } from "../types-
|
|
1
|
+
import { t as Snapshot } from "../types-Cf8Fp7kA.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/react/react.d.ts
|
|
4
4
|
/**
|
|
@@ -21,6 +21,31 @@ declare function useStore<T extends object, S>(proxyStore: T, selector: (snap: S
|
|
|
21
21
|
* @param proxyStore - A reactive proxy created by `store()`.
|
|
22
22
|
*/
|
|
23
23
|
declare function useStore<T extends object>(proxyStore: T): Snapshot<T>;
|
|
24
|
+
/**
|
|
25
|
+
* Create a component-scoped reactive store that lives for the lifetime of the
|
|
26
|
+
* component. When the component unmounts, the store becomes unreferenced and is
|
|
27
|
+
* garbage collected (all internal bookkeeping uses `WeakMap`).
|
|
28
|
+
*
|
|
29
|
+
* The factory function runs **once** per mount (via `useState` initializer).
|
|
30
|
+
* Each component instance gets its own isolated store.
|
|
31
|
+
*
|
|
32
|
+
* Use the returned proxy with `useStore()` to read state in the same component
|
|
33
|
+
* or pass it down via props/context to share within a subtree.
|
|
34
|
+
*
|
|
35
|
+
* @param factory - A function that returns a class instance (or plain object).
|
|
36
|
+
* Called once per component mount.
|
|
37
|
+
* @returns A reactive store proxy scoped to the component's lifetime.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```tsx
|
|
41
|
+
* function Counter() {
|
|
42
|
+
* const store = useLocalStore(() => new CounterStore());
|
|
43
|
+
* const count = useStore(store, s => s.count);
|
|
44
|
+
* return <button onClick={() => store.increment()}>{count}</button>;
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function useLocalStore<T extends object>(factory: () => T): T;
|
|
24
49
|
//#endregion
|
|
25
|
-
export { useStore };
|
|
50
|
+
export { useLocalStore, useStore };
|
|
26
51
|
//# sourceMappingURL=react.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.mts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"react.d.mts","names":[],"sources":["../../src/react/react.ts"],"mappings":";;;;;AAsBA;;;;;;;;iBAAgB,QAAA,qBAAA,CACd,UAAA,EAAY,CAAA,EACZ,QAAA,GAAW,IAAA,EAAM,QAAA,CAAS,CAAA,MAAO,CAAA,EACjC,OAAA,IAAW,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,eACnB,CAAA;;;;;;;;;iBAUa,QAAA,kBAAA,CAA2B,UAAA,EAAY,CAAA,GAAI,QAAA,CAAS,CAAA;;;;;;;;;;;;AAApE;;;;;;;;;;;;;iBA8JgB,aAAA,kBAAA,CAAgC,OAAA,QAAe,CAAA,GAAI,CAAA"}
|
package/dist/react/react.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as subscribe, r as getInternal, t as snapshot } from "../snapshot-
|
|
1
|
+
import { a as subscribe, n as createClassyStore, r as getInternal, t as snapshot } from "../snapshot-COzEerMu.mjs";
|
|
2
2
|
import { createProxy, isChanged } from "proxy-compare";
|
|
3
|
-
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
3
|
+
import { useCallback, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react/react.ts
|
|
6
6
|
function useStore(proxyStore, selector, isEqual) {
|
|
@@ -54,7 +54,35 @@ function getAutoTrackSnapshot(proxyStore, affected, proxyCache, prevSnapRef, wra
|
|
|
54
54
|
wrappedRef.current = wrapped;
|
|
55
55
|
return wrapped;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a component-scoped reactive store that lives for the lifetime of the
|
|
59
|
+
* component. When the component unmounts, the store becomes unreferenced and is
|
|
60
|
+
* garbage collected (all internal bookkeeping uses `WeakMap`).
|
|
61
|
+
*
|
|
62
|
+
* The factory function runs **once** per mount (via `useState` initializer).
|
|
63
|
+
* Each component instance gets its own isolated store.
|
|
64
|
+
*
|
|
65
|
+
* Use the returned proxy with `useStore()` to read state in the same component
|
|
66
|
+
* or pass it down via props/context to share within a subtree.
|
|
67
|
+
*
|
|
68
|
+
* @param factory - A function that returns a class instance (or plain object).
|
|
69
|
+
* Called once per component mount.
|
|
70
|
+
* @returns A reactive store proxy scoped to the component's lifetime.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```tsx
|
|
74
|
+
* function Counter() {
|
|
75
|
+
* const store = useLocalStore(() => new CounterStore());
|
|
76
|
+
* const count = useStore(store, s => s.count);
|
|
77
|
+
* return <button onClick={() => store.increment()}>{count}</button>;
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
function useLocalStore(factory) {
|
|
82
|
+
const [store] = useState(() => createClassyStore(factory()));
|
|
83
|
+
return store;
|
|
84
|
+
}
|
|
57
85
|
|
|
58
86
|
//#endregion
|
|
59
|
-
export { useStore };
|
|
87
|
+
export { useLocalStore, useStore };
|
|
60
88
|
//# sourceMappingURL=react.mjs.map
|