@tanstack/angular-store 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+ import { Injector, assertInInjectionContext, effect, inject, runInInjectionContext, signal, } from '@angular/core';
2
+ export function injectStore(store, selector = (d) => d, options = {
3
+ equal: shallow,
4
+ }) {
5
+ !options.injector && assertInInjectionContext(injectStore);
6
+ if (!options.injector) {
7
+ options.injector = inject(Injector);
8
+ }
9
+ return runInInjectionContext(options.injector, () => {
10
+ const slice = signal(selector(store.state), options);
11
+ effect((onCleanup) => {
12
+ const unsub = store.subscribe(() => {
13
+ slice.set(selector(store.state));
14
+ });
15
+ onCleanup(unsub);
16
+ }, { allowSignalWrites: true });
17
+ return slice.asReadonly();
18
+ });
19
+ }
20
+ function shallow(objA, objB) {
21
+ if (Object.is(objA, objB)) {
22
+ return true;
23
+ }
24
+ if (typeof objA !== 'object' ||
25
+ objA === null ||
26
+ typeof objB !== 'object' ||
27
+ objB === null) {
28
+ return false;
29
+ }
30
+ const keysA = Object.keys(objA);
31
+ if (keysA.length !== Object.keys(objB).length) {
32
+ return false;
33
+ }
34
+ for (let i = 0; i < keysA.length; i++) {
35
+ if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
36
+ !Object.is(objA[keysA[i]], objB[keysA[i]])) {
37
+ return false;
38
+ }
39
+ }
40
+ return true;
41
+ }
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFFBQVEsRUFDUix3QkFBd0IsRUFDeEIsTUFBTSxFQUNOLE1BQU0sRUFDTixxQkFBcUIsRUFDckIsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFBO0FBTXRCLE1BQU0sVUFBVSxXQUFXLENBS3pCLEtBQThCLEVBQzlCLFdBQWtELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFjLEVBQ3ZFLFVBQW9FO0lBQ2xFLEtBQUssRUFBRSxPQUFPO0NBQ2Y7SUFFRCxDQUFDLE9BQU8sQ0FBQyxRQUFRLElBQUksd0JBQXdCLENBQUMsV0FBVyxDQUFDLENBQUE7SUFFMUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN0QixPQUFPLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUNyQyxDQUFDO0lBRUQsT0FBTyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRTtRQUNsRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUVwRCxNQUFNLENBQ0osQ0FBQyxTQUFTLEVBQUUsRUFBRTtZQUNaLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO2dCQUNqQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtZQUNsQyxDQUFDLENBQUMsQ0FBQTtZQUNGLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUNsQixDQUFDLEVBQ0QsRUFBRSxpQkFBaUIsRUFBRSxJQUFJLEVBQUUsQ0FDNUIsQ0FBQTtRQUVELE9BQU8sS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQzNCLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQztBQUVELFNBQVMsT0FBTyxDQUFJLElBQU8sRUFBRSxJQUFPO0lBQ2xDLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUMxQixPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7SUFFRCxJQUNFLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFDeEIsSUFBSSxLQUFLLElBQUk7UUFDYixPQUFPLElBQUksS0FBSyxRQUFRO1FBQ3hCLElBQUksS0FBSyxJQUFJLEVBQ2IsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDL0IsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDOUMsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBRUQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUN0QyxJQUNFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFXLENBQUM7WUFDL0QsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFZLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBWSxDQUFDLENBQUMsRUFDaEUsQ0FBQztZQUNELE9BQU8sS0FBSyxDQUFBO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQTtBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBJbmplY3RvcixcbiAgYXNzZXJ0SW5JbmplY3Rpb25Db250ZXh0LFxuICBlZmZlY3QsXG4gIGluamVjdCxcbiAgcnVuSW5JbmplY3Rpb25Db250ZXh0LFxuICBzaWduYWwsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQgdHlwZSB7IEFueVVwZGF0ZXIsIFN0b3JlIH0gZnJvbSAnQHRhbnN0YWNrL3N0b3JlJ1xuaW1wb3J0IHR5cGUgeyBDcmVhdGVTaWduYWxPcHRpb25zIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcblxudHlwZSBOb0luZmVyPFQ+ID0gW1RdW1QgZXh0ZW5kcyBhbnkgPyAwIDogbmV2ZXJdXG5cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RTdG9yZTxcbiAgVFN0YXRlLFxuICBUU2VsZWN0ZWQgPSBOb0luZmVyPFRTdGF0ZT4sXG4gIFRVcGRhdGVyIGV4dGVuZHMgQW55VXBkYXRlciA9IEFueVVwZGF0ZXIsXG4+KFxuICBzdG9yZTogU3RvcmU8VFN0YXRlLCBUVXBkYXRlcj4sXG4gIHNlbGVjdG9yOiAoc3RhdGU6IE5vSW5mZXI8VFN0YXRlPikgPT4gVFNlbGVjdGVkID0gKGQpID0+IGQgYXMgVFNlbGVjdGVkLFxuICBvcHRpb25zOiBDcmVhdGVTaWduYWxPcHRpb25zPFRTZWxlY3RlZD4gJiB7IGluamVjdG9yPzogSW5qZWN0b3IgfSA9IHtcbiAgICBlcXVhbDogc2hhbGxvdyxcbiAgfSxcbikge1xuICAhb3B0aW9ucy5pbmplY3RvciAmJiBhc3NlcnRJbkluamVjdGlvbkNvbnRleHQoaW5qZWN0U3RvcmUpXG5cbiAgaWYgKCFvcHRpb25zLmluamVjdG9yKSB7XG4gICAgb3B0aW9ucy5pbmplY3RvciA9IGluamVjdChJbmplY3RvcilcbiAgfVxuXG4gIHJldHVybiBydW5JbkluamVjdGlvbkNvbnRleHQob3B0aW9ucy5pbmplY3RvciwgKCkgPT4ge1xuICAgIGNvbnN0IHNsaWNlID0gc2lnbmFsKHNlbGVjdG9yKHN0b3JlLnN0YXRlKSwgb3B0aW9ucylcblxuICAgIGVmZmVjdChcbiAgICAgIChvbkNsZWFudXApID0+IHtcbiAgICAgICAgY29uc3QgdW5zdWIgPSBzdG9yZS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHNsaWNlLnNldChzZWxlY3RvcihzdG9yZS5zdGF0ZSkpXG4gICAgICAgIH0pXG4gICAgICAgIG9uQ2xlYW51cCh1bnN1YilcbiAgICAgIH0sXG4gICAgICB7IGFsbG93U2lnbmFsV3JpdGVzOiB0cnVlIH0sXG4gICAgKVxuXG4gICAgcmV0dXJuIHNsaWNlLmFzUmVhZG9ubHkoKVxuICB9KVxufVxuXG5mdW5jdGlvbiBzaGFsbG93PFQ+KG9iakE6IFQsIG9iakI6IFQpIHtcbiAgaWYgKE9iamVjdC5pcyhvYmpBLCBvYmpCKSkge1xuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBpZiAoXG4gICAgdHlwZW9mIG9iakEgIT09ICdvYmplY3QnIHx8XG4gICAgb2JqQSA9PT0gbnVsbCB8fFxuICAgIHR5cGVvZiBvYmpCICE9PSAnb2JqZWN0JyB8fFxuICAgIG9iakIgPT09IG51bGxcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBjb25zdCBrZXlzQSA9IE9iamVjdC5rZXlzKG9iakEpXG4gIGlmIChrZXlzQS5sZW5ndGggIT09IE9iamVjdC5rZXlzKG9iakIpLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzQS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChcbiAgICAgICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqQiwga2V5c0FbaV0gYXMgc3RyaW5nKSB8fFxuICAgICAgIU9iamVjdC5pcyhvYmpBW2tleXNBW2ldIGFzIGtleW9mIFRdLCBvYmpCW2tleXNBW2ldIGFzIGtleW9mIFRdKVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlXG59XG4iXX0=
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './index';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFuc3RhY2stYW5ndWxhci1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90YW5zdGFjay1hbmd1bGFyLXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vaW5kZXgnO1xuIl19
@@ -0,0 +1,49 @@
1
+ import { assertInInjectionContext, inject, Injector, runInInjectionContext, signal, effect } from '@angular/core';
2
+
3
+ function injectStore(store, selector = (d) => d, options = {
4
+ equal: shallow,
5
+ }) {
6
+ !options.injector && assertInInjectionContext(injectStore);
7
+ if (!options.injector) {
8
+ options.injector = inject(Injector);
9
+ }
10
+ return runInInjectionContext(options.injector, () => {
11
+ const slice = signal(selector(store.state), options);
12
+ effect((onCleanup) => {
13
+ const unsub = store.subscribe(() => {
14
+ slice.set(selector(store.state));
15
+ });
16
+ onCleanup(unsub);
17
+ }, { allowSignalWrites: true });
18
+ return slice.asReadonly();
19
+ });
20
+ }
21
+ function shallow(objA, objB) {
22
+ if (Object.is(objA, objB)) {
23
+ return true;
24
+ }
25
+ if (typeof objA !== 'object' ||
26
+ objA === null ||
27
+ typeof objB !== 'object' ||
28
+ objB === null) {
29
+ return false;
30
+ }
31
+ const keysA = Object.keys(objA);
32
+ if (keysA.length !== Object.keys(objB).length) {
33
+ return false;
34
+ }
35
+ for (let i = 0; i < keysA.length; i++) {
36
+ if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
37
+ !Object.is(objA[keysA[i]], objB[keysA[i]])) {
38
+ return false;
39
+ }
40
+ }
41
+ return true;
42
+ }
43
+
44
+ /**
45
+ * Generated bundle index. Do not edit.
46
+ */
47
+
48
+ export { injectStore };
49
+ //# sourceMappingURL=tanstack-angular-store.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-angular-store.mjs","sources":["../../src/index.ts","../../src/tanstack-angular-store.ts"],"sourcesContent":["import {\n Injector,\n assertInInjectionContext,\n effect,\n inject,\n runInInjectionContext,\n signal,\n} from '@angular/core'\nimport type { AnyUpdater, Store } from '@tanstack/store'\nimport type { CreateSignalOptions } from '@angular/core'\n\ntype NoInfer<T> = [T][T extends any ? 0 : never]\n\nexport function injectStore<\n TState,\n TSelected = NoInfer<TState>,\n TUpdater extends AnyUpdater = AnyUpdater,\n>(\n store: Store<TState, TUpdater>,\n selector: (state: NoInfer<TState>) => TSelected = (d) => d as TSelected,\n options: CreateSignalOptions<TSelected> & { injector?: Injector } = {\n equal: shallow,\n },\n) {\n !options.injector && assertInInjectionContext(injectStore)\n\n if (!options.injector) {\n options.injector = inject(Injector)\n }\n\n return runInInjectionContext(options.injector, () => {\n const slice = signal(selector(store.state), options)\n\n effect(\n (onCleanup) => {\n const unsub = store.subscribe(() => {\n slice.set(selector(store.state))\n })\n onCleanup(unsub)\n },\n { allowSignalWrites: true },\n )\n\n return slice.asReadonly()\n })\n}\n\nfunction shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAagB,SAAA,WAAW,CAKzB,KAA8B,EAC9B,QAAA,GAAkD,CAAC,CAAC,KAAK,CAAc,EACvE,OAAoE,GAAA;AAClE,IAAA,KAAK,EAAE,OAAO;AACf,CAAA,EAAA;IAED,CAAC,OAAO,CAAC,QAAQ,IAAI,wBAAwB,CAAC,WAAW,CAAC,CAAA;AAE1D,IAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;AACrB,QAAA,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;KACpC;AAED,IAAA,OAAO,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAK;AAClD,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAA;AAEpD,QAAA,MAAM,CACJ,CAAC,SAAS,KAAI;AACZ,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,MAAK;gBACjC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;AAClC,aAAC,CAAC,CAAA;YACF,SAAS,CAAC,KAAK,CAAC,CAAA;AAClB,SAAC,EACD,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAC5B,CAAA;AAED,QAAA,OAAO,KAAK,CAAC,UAAU,EAAE,CAAA;AAC3B,KAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,OAAO,CAAI,IAAO,EAAE,IAAO,EAAA;IAClC,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;AACzB,QAAA,OAAO,IAAI,CAAA;KACZ;IAED,IACE,OAAO,IAAI,KAAK,QAAQ;AACxB,QAAA,IAAI,KAAK,IAAI;QACb,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI,EACb;AACA,QAAA,OAAO,KAAK,CAAA;KACb;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC/B,IAAA,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;AAC7C,QAAA,OAAO,KAAK,CAAA;KACb;AAED,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,QAAA,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAW,CAAC;YAC/D,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAY,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAY,CAAC,CAAC,EAChE;AACA,YAAA,OAAO,KAAK,CAAA;SACb;KACF;AACD,IAAA,OAAO,IAAI,CAAA;AACb;;AC3EA;;AAEG;;;;"}
@@ -1,8 +1,8 @@
1
- import { Injector, CreateSignalOptions } from '@angular/core';
2
- import { AnyUpdater, Store } from '@tanstack/store';
3
-
1
+ import { Injector } from '@angular/core';
2
+ import type { AnyUpdater, Store } from '@tanstack/store';
3
+ import type { CreateSignalOptions } from '@angular/core';
4
4
  type NoInfer<T> = [T][T extends any ? 0 : never];
5
5
  export declare function injectStore<TState, TSelected = NoInfer<TState>, TUpdater extends AnyUpdater = AnyUpdater>(store: Store<TState, TUpdater>, selector?: (state: NoInfer<TState>) => TSelected, options?: CreateSignalOptions<TSelected> & {
6
6
  injector?: Injector;
7
- }): import('@angular/core').Signal<TSelected>;
7
+ }): import("@angular/core").Signal<TSelected>;
8
8
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/angular-store",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.4.1",
4
+ "version": "0.5.1",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/store",
7
7
  "homepage": "https://tanstack.com/store",
@@ -19,21 +19,18 @@
19
19
  "url": "https://github.com/sponsors/tannerlinsley"
20
20
  },
21
21
  "type": "module",
22
- "types": "dist/esm/index.d.ts",
23
- "main": "dist/cjs/index.cjs",
24
- "module": "dist/esm/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "module": "dist/fesm2022/tanstack-angular-store.mjs",
25
24
  "exports": {
26
- ".": {
27
- "import": {
28
- "types": "./dist/esm/index.d.ts",
29
- "default": "./dist/esm/index.js"
30
- },
31
- "require": {
32
- "types": "./dist/cjs/index.d.cts",
33
- "default": "./dist/cjs/index.cjs"
34
- }
25
+ "./package.json": {
26
+ "default": "./package.json"
35
27
  },
36
- "./package.json": "./package.json"
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "esm2022": "./dist/esm2022/tanstack-angular-store.mjs",
31
+ "esm": "./dist/esm2022/tanstack-angular-store.mjs",
32
+ "default": "./dist/fesm2022/tanstack-angular-store.mjs"
33
+ }
37
34
  },
38
35
  "sideEffects": false,
39
36
  "files": [
@@ -41,16 +38,18 @@
41
38
  "src"
42
39
  ],
43
40
  "dependencies": {
44
- "@tanstack/store": "0.4.1"
41
+ "tslib": "^2.3.0",
42
+ "@tanstack/store": "0.5.0"
45
43
  },
46
44
  "devDependencies": {
47
- "@analogjs/vite-plugin-angular": "^0.2.32",
48
- "@angular/common": "^17.1.2",
49
- "@angular/compiler": "^17.1.2",
50
- "@angular/compiler-cli": "^17.1.2",
51
- "@angular/core": "^17.1.2",
52
- "@angular/platform-browser": "^17.1.2",
53
- "@angular/platform-browser-dynamic": "^17.1.2",
45
+ "@analogjs/vite-plugin-angular": "^1.5.0",
46
+ "@angular/common": "^17.3.0",
47
+ "@angular/compiler": "^17.3.0",
48
+ "@angular/compiler-cli": "^17.3.0",
49
+ "@angular/core": "^17.3.0",
50
+ "@angular/platform-browser": "^17.3.0",
51
+ "@angular/platform-browser-dynamic": "^17.3.0",
52
+ "ng-packagr": "^17.3.0",
54
53
  "zone.js": "^0.14.3"
55
54
  },
56
55
  "peerDependencies": {
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const core = require("@angular/core");
4
- function injectStore(store, selector = (d) => d, options = {
5
- equal: shallow
6
- }) {
7
- !options.injector && core.assertInInjectionContext(injectStore);
8
- if (!options.injector) {
9
- options.injector = core.inject(core.Injector);
10
- }
11
- return core.runInInjectionContext(options.injector, () => {
12
- const slice = core.signal(selector(store.state), options);
13
- core.effect(
14
- (onCleanup) => {
15
- const unsub = store.subscribe(() => {
16
- slice.set(selector(store.state));
17
- });
18
- onCleanup(unsub);
19
- },
20
- { allowSignalWrites: true }
21
- );
22
- return slice.asReadonly();
23
- });
24
- }
25
- function shallow(objA, objB) {
26
- if (Object.is(objA, objB)) {
27
- return true;
28
- }
29
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
30
- return false;
31
- }
32
- const keysA = Object.keys(objA);
33
- if (keysA.length !== Object.keys(objB).length) {
34
- return false;
35
- }
36
- for (let i = 0; i < keysA.length; i++) {
37
- if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
38
- return false;
39
- }
40
- }
41
- return true;
42
- }
43
- exports.injectStore = injectStore;
44
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["import {\n Injector,\n assertInInjectionContext,\n effect,\n inject,\n runInInjectionContext,\n signal,\n} from '@angular/core'\nimport type { AnyUpdater, Store } from '@tanstack/store'\nimport type { CreateSignalOptions } from '@angular/core'\n\ntype NoInfer<T> = [T][T extends any ? 0 : never]\n\nexport function injectStore<\n TState,\n TSelected = NoInfer<TState>,\n TUpdater extends AnyUpdater = AnyUpdater,\n>(\n store: Store<TState, TUpdater>,\n selector: (state: NoInfer<TState>) => TSelected = (d) => d as TSelected,\n options: CreateSignalOptions<TSelected> & { injector?: Injector } = {\n equal: shallow,\n },\n) {\n !options.injector && assertInInjectionContext(injectStore)\n\n if (!options.injector) {\n options.injector = inject(Injector)\n }\n\n return runInInjectionContext(options.injector, () => {\n const slice = signal(selector(store.state), options)\n\n effect(\n (onCleanup) => {\n const unsub = store.subscribe(() => {\n slice.set(selector(store.state))\n })\n onCleanup(unsub)\n },\n { allowSignalWrites: true },\n )\n\n return slice.asReadonly()\n })\n}\n\nfunction shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n"],"names":["assertInInjectionContext","inject","Injector","runInInjectionContext","signal","effect"],"mappings":";;;AAaO,SAAS,YAKd,OACA,WAAkD,CAAC,MAAM,GACzD,UAAoE;AAAA,EAClE,OAAO;AACT,GACA;AACC,GAAA,QAAQ,YAAYA,KAAA,yBAAyB,WAAW;AAErD,MAAA,CAAC,QAAQ,UAAU;AACb,YAAA,WAAWC,YAAOC,KAAAA,QAAQ;AAAA,EACpC;AAEO,SAAAC,KAAA,sBAAsB,QAAQ,UAAU,MAAM;AACnD,UAAM,QAAQC,KAAAA,OAAO,SAAS,MAAM,KAAK,GAAG,OAAO;AAEnDC,SAAA;AAAA,MACE,CAAC,cAAc;AACP,cAAA,QAAQ,MAAM,UAAU,MAAM;AAClC,gBAAM,IAAI,SAAS,MAAM,KAAK,CAAC;AAAA,QAAA,CAChC;AACD,kBAAU,KAAK;AAAA,MACjB;AAAA,MACA,EAAE,mBAAmB,KAAK;AAAA,IAAA;AAG5B,WAAO,MAAM;EAAW,CACzB;AACH;AAEA,SAAS,QAAW,MAAS,MAAS;AACpC,MAAI,OAAO,GAAG,MAAM,IAAI,GAAG;AAClB,WAAA;AAAA,EACT;AAGE,MAAA,OAAO,SAAS,YAChB,SAAS,QACT,OAAO,SAAS,YAChB,SAAS,MACT;AACO,WAAA;AAAA,EACT;AAEM,QAAA,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,OAAO,KAAK,IAAI,EAAE,QAAQ;AACtC,WAAA;AAAA,EACT;AAEA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AAEnC,QAAA,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,MAAM,CAAC,CAAW,KAC9D,CAAC,OAAO,GAAG,KAAK,MAAM,CAAC,CAAY,GAAG,KAAK,MAAM,CAAC,CAAY,CAAC,GAC/D;AACO,aAAA;AAAA,IACT;AAAA,EACF;AACO,SAAA;AACT;;"}
@@ -1,8 +0,0 @@
1
- import { Injector, CreateSignalOptions } from '@angular/core';
2
- import { AnyUpdater, Store } from '@tanstack/store';
3
-
4
- type NoInfer<T> = [T][T extends any ? 0 : never];
5
- export declare function injectStore<TState, TSelected = NoInfer<TState>, TUpdater extends AnyUpdater = AnyUpdater>(store: Store<TState, TUpdater>, selector?: (state: NoInfer<TState>) => TSelected, options?: CreateSignalOptions<TSelected> & {
6
- injector?: Injector;
7
- }): import('@angular/core').Signal<TSelected>;
8
- export {};
package/dist/esm/index.js DELETED
@@ -1,44 +0,0 @@
1
- import { assertInInjectionContext, inject, Injector, runInInjectionContext, signal, effect } from "@angular/core";
2
- function injectStore(store, selector = (d) => d, options = {
3
- equal: shallow
4
- }) {
5
- !options.injector && assertInInjectionContext(injectStore);
6
- if (!options.injector) {
7
- options.injector = inject(Injector);
8
- }
9
- return runInInjectionContext(options.injector, () => {
10
- const slice = signal(selector(store.state), options);
11
- effect(
12
- (onCleanup) => {
13
- const unsub = store.subscribe(() => {
14
- slice.set(selector(store.state));
15
- });
16
- onCleanup(unsub);
17
- },
18
- { allowSignalWrites: true }
19
- );
20
- return slice.asReadonly();
21
- });
22
- }
23
- function shallow(objA, objB) {
24
- if (Object.is(objA, objB)) {
25
- return true;
26
- }
27
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
28
- return false;
29
- }
30
- const keysA = Object.keys(objA);
31
- if (keysA.length !== Object.keys(objB).length) {
32
- return false;
33
- }
34
- for (let i = 0; i < keysA.length; i++) {
35
- if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
36
- return false;
37
- }
38
- }
39
- return true;
40
- }
41
- export {
42
- injectStore
43
- };
44
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["import {\n Injector,\n assertInInjectionContext,\n effect,\n inject,\n runInInjectionContext,\n signal,\n} from '@angular/core'\nimport type { AnyUpdater, Store } from '@tanstack/store'\nimport type { CreateSignalOptions } from '@angular/core'\n\ntype NoInfer<T> = [T][T extends any ? 0 : never]\n\nexport function injectStore<\n TState,\n TSelected = NoInfer<TState>,\n TUpdater extends AnyUpdater = AnyUpdater,\n>(\n store: Store<TState, TUpdater>,\n selector: (state: NoInfer<TState>) => TSelected = (d) => d as TSelected,\n options: CreateSignalOptions<TSelected> & { injector?: Injector } = {\n equal: shallow,\n },\n) {\n !options.injector && assertInInjectionContext(injectStore)\n\n if (!options.injector) {\n options.injector = inject(Injector)\n }\n\n return runInInjectionContext(options.injector, () => {\n const slice = signal(selector(store.state), options)\n\n effect(\n (onCleanup) => {\n const unsub = store.subscribe(() => {\n slice.set(selector(store.state))\n })\n onCleanup(unsub)\n },\n { allowSignalWrites: true },\n )\n\n return slice.asReadonly()\n })\n}\n\nfunction shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n"],"names":[],"mappings":";AAaO,SAAS,YAKd,OACA,WAAkD,CAAC,MAAM,GACzD,UAAoE;AAAA,EAClE,OAAO;AACT,GACA;AACC,GAAA,QAAQ,YAAY,yBAAyB,WAAW;AAErD,MAAA,CAAC,QAAQ,UAAU;AACb,YAAA,WAAW,OAAO,QAAQ;AAAA,EACpC;AAEO,SAAA,sBAAsB,QAAQ,UAAU,MAAM;AACnD,UAAM,QAAQ,OAAO,SAAS,MAAM,KAAK,GAAG,OAAO;AAEnD;AAAA,MACE,CAAC,cAAc;AACP,cAAA,QAAQ,MAAM,UAAU,MAAM;AAClC,gBAAM,IAAI,SAAS,MAAM,KAAK,CAAC;AAAA,QAAA,CAChC;AACD,kBAAU,KAAK;AAAA,MACjB;AAAA,MACA,EAAE,mBAAmB,KAAK;AAAA,IAAA;AAG5B,WAAO,MAAM;EAAW,CACzB;AACH;AAEA,SAAS,QAAW,MAAS,MAAS;AACpC,MAAI,OAAO,GAAG,MAAM,IAAI,GAAG;AAClB,WAAA;AAAA,EACT;AAGE,MAAA,OAAO,SAAS,YAChB,SAAS,QACT,OAAO,SAAS,YAChB,SAAS,MACT;AACO,WAAA;AAAA,EACT;AAEM,QAAA,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,OAAO,KAAK,IAAI,EAAE,QAAQ;AACtC,WAAA;AAAA,EACT;AAEA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AAEnC,QAAA,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,MAAM,CAAC,CAAW,KAC9D,CAAC,OAAO,GAAG,KAAK,MAAM,CAAC,CAAY,GAAG,KAAK,MAAM,CAAC,CAAY,CAAC,GAC/D;AACO,aAAA;AAAA,IACT;AAAA,EACF;AACO,SAAA;AACT;"}
@@ -1,95 +0,0 @@
1
- import { describe, expect, test } from 'vitest'
2
- import { Component, effect } from '@angular/core'
3
- import { TestBed } from '@angular/core/testing'
4
- import { By } from '@angular/platform-browser'
5
- import { Store } from '@tanstack/store'
6
- import { injectStore } from '../index'
7
-
8
- describe('injectStore', () => {
9
- test(`allows us to select state using a selector`, () => {
10
- const store = new Store({ select: 0, ignored: 1 })
11
-
12
- @Component({
13
- template: `<p>Store: {{ storeVal() }}</p>`,
14
- standalone: true,
15
- })
16
- class MyCmp {
17
- storeVal = injectStore(store, (state) => state.select)
18
- }
19
-
20
- const fixture = TestBed.createComponent(MyCmp)
21
- fixture.detectChanges()
22
-
23
- const element = fixture.nativeElement
24
- expect(element.textContent).toContain('Store: 0')
25
- })
26
-
27
- test('only triggers a re-render when selector state is updated', async () => {
28
- const store = new Store({ select: 0, ignored: 1 })
29
- let count = 0
30
-
31
- @Component({
32
- template: `
33
- <div>
34
- <p>Store: {{ storeVal() }}</p>
35
- <button id="updateSelect" (click)="updateSelect()">
36
- Update select
37
- </button>
38
- <button id="updateIgnored" (click)="updateIgnored()">
39
- Update ignored
40
- </button>
41
- </div>
42
- `,
43
- standalone: true,
44
- })
45
- class MyCmp {
46
- storeVal = injectStore(store, (state) => state.select)
47
-
48
- constructor() {
49
- effect(() => {
50
- console.log(this.storeVal())
51
- count++
52
- })
53
- }
54
-
55
- updateSelect() {
56
- store.setState((v) => ({
57
- ...v,
58
- select: 10,
59
- }))
60
- }
61
-
62
- updateIgnored() {
63
- store.setState((v) => ({
64
- ...v,
65
- ignored: 10,
66
- }))
67
- }
68
- }
69
-
70
- const fixture = TestBed.createComponent(MyCmp)
71
- fixture.detectChanges()
72
-
73
- const element = fixture.nativeElement
74
- const debugElement = fixture.debugElement
75
-
76
- expect(element.textContent).toContain('Store: 0')
77
- expect(count).toEqual(1)
78
-
79
- debugElement
80
- .query(By.css('button#updateSelect'))
81
- .triggerEventHandler('click', null)
82
-
83
- fixture.detectChanges()
84
- expect(element.textContent).toContain('Store: 10')
85
- expect(count).toEqual(2)
86
-
87
- debugElement
88
- .query(By.css('button#updateIgnored'))
89
- .triggerEventHandler('click', null)
90
-
91
- fixture.detectChanges()
92
- expect(element.textContent).toContain('Store: 10')
93
- expect(count).toEqual(2)
94
- })
95
- })
@@ -1,12 +0,0 @@
1
- import '@analogjs/vite-plugin-angular/setup-vitest'
2
-
3
- import {
4
- BrowserDynamicTestingModule,
5
- platformBrowserDynamicTesting,
6
- } from '@angular/platform-browser-dynamic/testing'
7
- import { getTestBed } from '@angular/core/testing'
8
-
9
- getTestBed().initTestEnvironment(
10
- BrowserDynamicTestingModule,
11
- platformBrowserDynamicTesting(),
12
- )