@mmstack/primitives 19.5.1 → 19.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -11
- package/fesm2022/mmstack-primitives.mjs +694 -411
- package/fesm2022/mmstack-primitives.mjs.map +1 -1
- package/lib/chunked.d.ts +7 -0
- package/lib/concurrent/pausable-pure.d.ts +12 -0
- package/lib/concurrent/pausable.d.ts +23 -2
- package/lib/concurrent/suspense-boundary.d.ts +6 -0
- package/lib/sensors/index.d.ts +1 -0
- package/lib/sensors/pointer-drag.d.ts +88 -0
- package/lib/sensors/sensor.d.ts +14 -0
- package/lib/store/fork-store.d.ts +8 -18
- package/lib/store/internals.d.ts +34 -0
- package/lib/store/leaf.d.ts +36 -0
- package/lib/store/opaque.d.ts +44 -0
- package/lib/store/predicates.d.ts +28 -0
- package/lib/store/public_api.d.ts +5 -1
- package/lib/store/store.d.ts +39 -170
- package/lib/store/types.d.ts +85 -0
- package/lib/stored.d.ts +15 -2
- package/lib/tab-sync.d.ts +9 -1
- package/lib/throttled.d.ts +8 -4
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { type Signal, type WritableSignal } from '@angular/core';
|
|
2
|
+
import { type MutableSignal } from '../mutable';
|
|
3
|
+
import { type LEAF } from './leaf';
|
|
4
|
+
import { type OPAQUE, type UnwrapOpaque } from './opaque';
|
|
5
|
+
type BaseType = string | number | boolean | symbol | bigint | undefined | null | Function | Date | RegExp | {
|
|
6
|
+
readonly [OPAQUE]: true;
|
|
7
|
+
};
|
|
8
|
+
export type Key = string | number;
|
|
9
|
+
export type AnyRecord = Record<Key, any>;
|
|
10
|
+
/**
|
|
11
|
+
* @internal Resolves to `true` only for `any`. In a conditional type, `any` distributes across
|
|
12
|
+
* *both* branches (`unknown | object`), and `unknown | X` collapses to `unknown` — which would
|
|
13
|
+
* erase a store's property access and `extend`. Guarding on this routes an `any`-typed store to
|
|
14
|
+
* the full object shape instead.
|
|
15
|
+
*/
|
|
16
|
+
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
17
|
+
/**
|
|
18
|
+
* @internal Flattens an intersection (`A & B & C`) into a single object literal so editor
|
|
19
|
+
* tooltips show the resolved members instead of the raw intersection chain. Display-only —
|
|
20
|
+
* structurally identical to its input.
|
|
21
|
+
*/
|
|
22
|
+
export type Simplify<T> = {
|
|
23
|
+
[K in keyof T]: T[K];
|
|
24
|
+
} & {};
|
|
25
|
+
export type SignalArrayStore<T extends any[]> = Signal<T> & {
|
|
26
|
+
readonly [index: number]: SignalStore<T[number]>;
|
|
27
|
+
readonly length: Signal<number>;
|
|
28
|
+
[Symbol.iterator](): Iterator<SignalStore<T[number]>>;
|
|
29
|
+
};
|
|
30
|
+
export type WritableArrayStore<T extends any[]> = WritableSignal<T> & {
|
|
31
|
+
readonly asReadonlyStore: () => SignalArrayStore<T>;
|
|
32
|
+
readonly [index: number]: WritableSignalStore<T[number]>;
|
|
33
|
+
readonly length: Signal<number>;
|
|
34
|
+
[Symbol.iterator](): Iterator<WritableSignalStore<T[number]>>;
|
|
35
|
+
};
|
|
36
|
+
export type MutableArrayStore<T extends any[]> = MutableSignal<T> & {
|
|
37
|
+
readonly asReadonlyStore: () => SignalArrayStore<T>;
|
|
38
|
+
readonly [index: number]: MutableSignalStore<T[number]>;
|
|
39
|
+
readonly length: Signal<number>;
|
|
40
|
+
[Symbol.iterator](): Iterator<MutableSignalStore<T[number]>>;
|
|
41
|
+
};
|
|
42
|
+
/** @internal The object shape of a readonly store: a child store per key, plus `extend`. */
|
|
43
|
+
type SignalStoreObject<T> = Simplify<Readonly<{
|
|
44
|
+
[K in keyof Required<T>]: SignalStore<NonNullable<T>[K]>;
|
|
45
|
+
}> & {
|
|
46
|
+
/** @deprecated Use the standalone `extendStore(store, …)`; the `extend` key is removed next minor. */
|
|
47
|
+
readonly extend: {
|
|
48
|
+
<L extends AnyRecord>(source: Signal<L>): SignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
49
|
+
<L extends AnyRecord>(props: L): SignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
50
|
+
};
|
|
51
|
+
}>;
|
|
52
|
+
/** @internal The object shape of a writable store. */
|
|
53
|
+
type WritableSignalStoreObject<T> = Simplify<Readonly<{
|
|
54
|
+
[K in keyof Required<T>]: WritableSignalStore<NonNullable<T>[K]>;
|
|
55
|
+
}> & {
|
|
56
|
+
/** @deprecated Use the standalone `extendStore(store, …)`; the `extend` key is removed next minor. */
|
|
57
|
+
readonly extend: {
|
|
58
|
+
<L extends AnyRecord>(source: WritableSignal<L>): WritableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
59
|
+
<L extends AnyRecord>(props: L): WritableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
60
|
+
};
|
|
61
|
+
}>;
|
|
62
|
+
/** @internal The object shape of a mutable store. */
|
|
63
|
+
type MutableSignalStoreObject<T> = Simplify<Readonly<{
|
|
64
|
+
[K in keyof Required<T>]: MutableSignalStore<NonNullable<T>[K]>;
|
|
65
|
+
}> & {
|
|
66
|
+
/** @deprecated Use the standalone `extendStore(store, …)`; the `extend` key is removed next minor. */
|
|
67
|
+
readonly extend: {
|
|
68
|
+
<L extends AnyRecord>(source: MutableSignal<L>): MutableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
69
|
+
<L extends AnyRecord>(props: L): MutableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
70
|
+
};
|
|
71
|
+
}>;
|
|
72
|
+
export type SignalStore<T> = Signal<UnwrapOpaque<T>> & (IsAny<T> extends true ? SignalStoreObject<T> : NonNullable<T> extends BaseType ? {
|
|
73
|
+
readonly [LEAF]: () => boolean;
|
|
74
|
+
} : NonNullable<T> extends any[] ? SignalArrayStore<NonNullable<T>> : SignalStoreObject<T>);
|
|
75
|
+
export type WritableSignalStore<T> = WritableSignal<UnwrapOpaque<T>> & {
|
|
76
|
+
readonly asReadonlyStore: () => SignalStore<T>;
|
|
77
|
+
} & (IsAny<T> extends true ? WritableSignalStoreObject<T> : NonNullable<T> extends BaseType ? {
|
|
78
|
+
readonly [LEAF]: () => boolean;
|
|
79
|
+
} : NonNullable<T> extends any[] ? WritableArrayStore<NonNullable<T>> : WritableSignalStoreObject<T>);
|
|
80
|
+
export type MutableSignalStore<T> = MutableSignal<UnwrapOpaque<T>> & {
|
|
81
|
+
readonly asReadonlyStore: () => SignalStore<T>;
|
|
82
|
+
} & (IsAny<T> extends true ? MutableSignalStoreObject<T> : NonNullable<T> extends BaseType ? {
|
|
83
|
+
readonly [LEAF]: () => boolean;
|
|
84
|
+
} : NonNullable<T> extends any[] ? MutableArrayStore<NonNullable<T>> : MutableSignalStoreObject<T>);
|
|
85
|
+
export {};
|
package/lib/stored.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type CreateSignalOptions, type Signal, type WritableSignal } from '@angular/core';
|
|
1
|
+
import { Injector, type CreateSignalOptions, type Signal, type WritableSignal } from '@angular/core';
|
|
2
|
+
import { type PauseOption } from './concurrent/pausable';
|
|
2
3
|
/**
|
|
3
4
|
* Interface for storage mechanisms compatible with the `stored` signal.
|
|
4
5
|
* Matches the essential parts of the `Storage` interface (`localStorage`, `sessionStorage`).
|
|
@@ -65,6 +66,18 @@ export type CreateStoredOptions<T> = CreateSignalOptions<T> & {
|
|
|
65
66
|
* Optional validator, which is called on load of value. Store will be set to fallback if value is false
|
|
66
67
|
*/
|
|
67
68
|
validate?: (value: T) => boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Opt-in pause: gate the persistence effect on an ambient Activity boundary (`true`), a custom
|
|
71
|
+
* predicate, or `false` (default — no pausing). While paused the value stays live; persistence is
|
|
72
|
+
* skipped and flushes the latest value on resume. The inbound `storage` listener stays live.
|
|
73
|
+
* See {@link PauseOption}.
|
|
74
|
+
*/
|
|
75
|
+
pause?: PauseOption;
|
|
76
|
+
/**
|
|
77
|
+
* Injector used when `stored` is created outside an injection context, and to resolve the ambient
|
|
78
|
+
* pause boundary when `pause` is `true`.
|
|
79
|
+
*/
|
|
80
|
+
injector?: Injector;
|
|
68
81
|
};
|
|
69
82
|
/**
|
|
70
83
|
* A specialized `WritableSignal` returned by the `stored()` function.
|
|
@@ -136,5 +149,5 @@ export type StoredSignal<T> = WritableSignal<T> & {
|
|
|
136
149
|
* }
|
|
137
150
|
* ```
|
|
138
151
|
*/
|
|
139
|
-
export declare function stored<T>(fallback: T, { key, store: providedStore, serialize, deserialize, syncTabs, equal, onKeyChange, cleanupOldKey, validate, ...rest }: CreateStoredOptions<T>): StoredSignal<T>;
|
|
152
|
+
export declare function stored<T>(fallback: T, { key, store: providedStore, serialize, deserialize, syncTabs, equal, onKeyChange, cleanupOldKey, validate, pause, injector: providedInjector, ...rest }: CreateStoredOptions<T>): StoredSignal<T>;
|
|
140
153
|
export {};
|
package/lib/tab-sync.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OnDestroy, type WritableSignal } from '@angular/core';
|
|
1
|
+
import { Injector, type OnDestroy, type WritableSignal } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
export declare class MessageBus implements OnDestroy {
|
|
4
4
|
private readonly channel;
|
|
@@ -22,6 +22,14 @@ type LegacySyncSignalOptions = {
|
|
|
22
22
|
};
|
|
23
23
|
export type SyncSignalOptions = {
|
|
24
24
|
id: string;
|
|
25
|
+
/**
|
|
26
|
+
* Injector used when `tabSync` is called outside an injection context.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: `tabSync` is intentionally NOT pausable. Pausing the outbound broadcast would let its
|
|
29
|
+
* mount-time echo guard swallow a value changed while hidden, so other tabs would silently miss
|
|
30
|
+
* it — a cross-tab consistency gap not worth the negligible saving. The channel stays live.
|
|
31
|
+
*/
|
|
32
|
+
injector?: Injector;
|
|
25
33
|
};
|
|
26
34
|
/**
|
|
27
35
|
* @example tabSync(signal('dark'), { id: 'theme' })
|
package/lib/throttled.d.ts
CHANGED
|
@@ -37,12 +37,16 @@ export type CreateThrottledOptions<T> = CreateSignalOptions<T> & {
|
|
|
37
37
|
/**
|
|
38
38
|
* A specialized `WritableSignal` whose publicly readable value updates are throttled.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
40
|
+
* Provides access to the underlying, non-throttled signal via `original`, and a
|
|
41
|
+
* `flush()` that emits the current value immediately (clearing any open window) —
|
|
42
|
+
* useful for terminal transitions that shouldn't wait for the trailing edge.
|
|
41
43
|
*
|
|
42
44
|
* @template T The type of value held by the signal.
|
|
43
|
-
* @see {DebouncedSignal} as the output type has the same structure.
|
|
44
45
|
*/
|
|
45
|
-
export type ThrottledSignal<T> = DebouncedSignal<T
|
|
46
|
+
export type ThrottledSignal<T> = DebouncedSignal<T> & {
|
|
47
|
+
/** Emit the latest value now, bypassing the remaining throttle window. */
|
|
48
|
+
flush: () => void;
|
|
49
|
+
};
|
|
46
50
|
/**
|
|
47
51
|
* A convenience function that creates and throttles a new `WritableSignal` in one step.
|
|
48
52
|
*
|
|
@@ -63,7 +67,7 @@ export type ThrottledSignal<T> = DebouncedSignal<T>;
|
|
|
63
67
|
* // With a trailing-edge throttle, the final value 'c' would be set
|
|
64
68
|
* // after the 500ms cooldown.
|
|
65
69
|
*/
|
|
66
|
-
export declare function throttled<T>(initial: T, opt?: CreateThrottledOptions<T>):
|
|
70
|
+
export declare function throttled<T>(initial: T, opt?: CreateThrottledOptions<T>): ThrottledSignal<T>;
|
|
67
71
|
/**
|
|
68
72
|
* Wraps an existing `WritableSignal` to create a new one whose readable value is throttled.
|
|
69
73
|
*
|