@mmstack/primitives 19.5.2 → 19.7.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 +30 -3
- package/fesm2022/mmstack-primitives.mjs +217 -114
- package/fesm2022/mmstack-primitives.mjs.map +1 -1
- package/lib/concurrent/start-transition.d.ts +3 -2
- package/lib/concurrent/suspense-boundary.d.ts +1 -2
- package/lib/concurrent/transaction.d.ts +2 -1
- package/lib/concurrent/transition-scope.d.ts +9 -0
- package/lib/sensors/pointer-drag.d.ts +28 -1
- package/lib/store/fork-store.d.ts +8 -18
- package/lib/store/internals.d.ts +8 -11
- package/lib/store/public_api.d.ts +5 -1
- package/lib/store/store.d.ts +39 -10
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type Signal } from '@angular/core';
|
|
2
2
|
/**
|
|
3
|
-
* Handle for an in-progress transition: a `pending` signal (true while the transition's
|
|
4
|
-
* resources are in flight
|
|
3
|
+
* Handle for an in-progress transition: a `pending` signal (true while the transition's OWN
|
|
4
|
+
* resources are in flight — loads already in flight when it started are not attributed) and a
|
|
5
|
+
* `done` promise that resolves once they all settle.
|
|
5
6
|
*/
|
|
6
7
|
export type TransitionRef = {
|
|
7
8
|
readonly pending: Signal<boolean>;
|
|
@@ -41,8 +41,7 @@ export declare class SuspenseBoundary extends SuspenseBoundaryBase {
|
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
43
|
* Unscoped suspense boundary — **reads the ambient scope** instead of providing one. For cases where
|
|
44
|
-
* the resources to coordinate are registered *above* the boundary
|
|
45
|
-
* manifests/connectors register at a higher injector), so the boundary observes that outer scope
|
|
44
|
+
* the resources to coordinate are registered *above* the boundary so the boundary observes that outer scope
|
|
46
45
|
* rather than opening a fresh one. Pair with a `provideTransitionScope()` (or another boundary) in an
|
|
47
46
|
* ancestor.
|
|
48
47
|
*/
|
|
@@ -15,7 +15,8 @@ export type Transaction = {
|
|
|
15
15
|
export declare function createTransaction(): Transaction;
|
|
16
16
|
/** The transaction in effect right now, or `null`. Stateful actions consult this to record undo. */
|
|
17
17
|
export declare function activeTransaction(): Transaction | null;
|
|
18
|
-
/** Handle for an in-progress transaction (Tier 3): the
|
|
18
|
+
/** Handle for an in-progress transaction (Tier 3): the transaction's own `pending`/`done`
|
|
19
|
+
* (loads already in flight at start are not attributed to it), plus `abort`. */
|
|
19
20
|
export type TransactionRef = {
|
|
20
21
|
readonly pending: Signal<boolean>;
|
|
21
22
|
readonly done: Promise<void>;
|
|
@@ -78,6 +78,15 @@ export declare function createForwardingScope(): ForwardingTransitionScope;
|
|
|
78
78
|
export declare function provideForwardingTransitionScope(): Provider;
|
|
79
79
|
/** Read the transition scope reachable from `injector`, or null if none is provided there. */
|
|
80
80
|
export declare function getTransitionScope(injector: Injector): TransitionScope | null;
|
|
81
|
+
/**
|
|
82
|
+
* @internal Transaction-attributed pending for `startTransition`/`startTransaction`: like
|
|
83
|
+
* `scope.pending`, but loads already in flight when the tracker is created are NOT attributed —
|
|
84
|
+
* a pre-existing background load can neither settle the transaction early nor block its settle
|
|
85
|
+
* forever. A pre-existing flight is excluded only until it first settles; a later re-trigger of
|
|
86
|
+
* the same resource (e.g. the transaction's write changed its request) counts as the
|
|
87
|
+
* transaction's own work.
|
|
88
|
+
*/
|
|
89
|
+
export declare function createAttributedPending(scope: TransitionScope): Signal<boolean>;
|
|
81
90
|
/**
|
|
82
91
|
* Returns a register function bound to the nearest transition scope: it adds a resource
|
|
83
92
|
* to the scope and removes it when the caller's injection context is destroyed. Pass any
|
|
@@ -25,6 +25,21 @@ export type PointerDragState = {
|
|
|
25
25
|
modifiers: PointerModifiers;
|
|
26
26
|
/** Mouse button that started the gesture (`-1` when idle). */
|
|
27
27
|
button: number;
|
|
28
|
+
/** The pointing device: `'mouse' | 'touch' | 'pen'` (`''` when idle). */
|
|
29
|
+
pointerType: string;
|
|
30
|
+
/**
|
|
31
|
+
* The element the gesture started on: the `handleSelector` match when one is
|
|
32
|
+
* set (so a single delegated listener can tell which child started the drag),
|
|
33
|
+
* otherwise the listener's element. `null` when idle.
|
|
34
|
+
*/
|
|
35
|
+
origin: HTMLElement | null;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the LAST gesture ended by being aborted (`pointercancel` /
|
|
38
|
+
* `lostpointercapture` / Escape / `cancel()`) rather than a normal `pointerup`.
|
|
39
|
+
* Only meaningful on the idle transition — consumers ending a drag branch on it
|
|
40
|
+
* to distinguish "drop here" from "abort". Sticky until the next `pointerdown`.
|
|
41
|
+
*/
|
|
42
|
+
cancelled: boolean;
|
|
28
43
|
};
|
|
29
44
|
export type PointerDragOptions = SensorRunOptions & {
|
|
30
45
|
/**
|
|
@@ -37,12 +52,24 @@ export type PointerDragOptions = SensorRunOptions & {
|
|
|
37
52
|
coordinateSpace?: 'client' | 'page';
|
|
38
53
|
/** Pixels the pointer must travel before `active` flips true. @default 3 */
|
|
39
54
|
activationThreshold?: number;
|
|
40
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* Throttle (ms) for `current`/`delta` updates. @default 16
|
|
57
|
+
*
|
|
58
|
+
* Note: a final sub-throttle move right before `pointerup` may not surface on
|
|
59
|
+
* the throttled view (it coalesces into the terminal idle). Logic that must act
|
|
60
|
+
* on the *exact* release position should read {@link PointerDragSignal.unthrottled}.
|
|
61
|
+
*/
|
|
41
62
|
throttle?: number;
|
|
42
63
|
/** Only start when the pointerdown target matches this selector (delegated handles). */
|
|
43
64
|
handleSelector?: string;
|
|
44
65
|
/** Mouse buttons that may start a gesture. @default [0] (primary) */
|
|
45
66
|
buttons?: number[];
|
|
67
|
+
/**
|
|
68
|
+
* Stop the `pointerdown` from propagating once this sensor claims it. Lets an
|
|
69
|
+
* inner sensor win over an outer one on the same element tree (e.g. a nested
|
|
70
|
+
* sortable inside another). @default false
|
|
71
|
+
*/
|
|
72
|
+
stopPropagation?: boolean;
|
|
46
73
|
};
|
|
47
74
|
/** A gesture signal with an `unthrottled` view and an imperative `cancel()`. */
|
|
48
75
|
export type PointerDragSignal = Signal<PointerDragState> & {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import {
|
|
3
|
-
import { type WritableSignalStore } from './store';
|
|
1
|
+
import { type toStoreOptions } from './store';
|
|
2
|
+
import type { WritableSignalStore } from './types';
|
|
4
3
|
/**
|
|
5
4
|
* A 3-way merge of a forked value against a changed base: given the common `ancestor` (the base
|
|
6
5
|
* value the fork last diverged from), `mine` (the fork's current value), and `theirs` (the base
|
|
@@ -61,19 +60,10 @@ export type Fork<T> = {
|
|
|
61
60
|
* leaves compare by value, so equal primitives are correctly seen as unchanged.
|
|
62
61
|
*/
|
|
63
62
|
export declare function merge3<T>(ancestor: T, mine: T, theirs: T): T;
|
|
64
|
-
|
|
63
|
+
/**
|
|
64
|
+
* ForkStoreOptions, vivify/noUnionLeaves should remain the same & are automatically inherited, override carefully (advanced usecases)
|
|
65
|
+
*/
|
|
66
|
+
export type ForkStoreOptions<T> = toStoreOptions & {
|
|
65
67
|
strategy?: ForkStrategy<T>;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* Store config for the FORK's store — NOT inherited from `base` (it's closed over inside
|
|
69
|
-
* the base's `toStore` and can't be read back). If the base was created with these, pass
|
|
70
|
-
* the same values or the fork's write semantics will differ:
|
|
71
|
-
* - `vivify`: without it, a write through a `null`/`undefined` path is silently dropped on
|
|
72
|
-
* the fork even though the base would have created the container. Match the base.
|
|
73
|
-
* - `noUnionLeaves`: a perf promise; off just means the slower reactive leaf-probe. NOTE it
|
|
74
|
-
* is a whole-store guarantee — a fork that flips a node's type (leaf↔substore) violates it,
|
|
75
|
-
* and on `commit` the base receives the flipped value with stale cached leaf-ness.
|
|
76
|
-
*/
|
|
77
|
-
vivify?: Vivify;
|
|
78
|
-
noUnionLeaves?: boolean;
|
|
79
|
-
}): Fork<T>;
|
|
68
|
+
};
|
|
69
|
+
export declare function forkStore<T extends Record<string, any>>(base: WritableSignalStore<T>, opt?: ForkStoreOptions<T>): Fork<T>;
|
package/lib/store/internals.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { type Signal } from '@angular/core';
|
|
1
|
+
import { InjectionToken, type Signal } from '@angular/core';
|
|
2
2
|
import { type SignalStore } from './types';
|
|
3
3
|
export declare const IS_STORE: unique symbol;
|
|
4
4
|
export declare const SCOPE_PARENT: unique symbol;
|
|
5
|
+
export declare const STORE_SHARED_GLOBALS: unique symbol;
|
|
6
|
+
export declare const STORE_SHARED_OPTIONS: unique symbol;
|
|
5
7
|
/**
|
|
6
8
|
* @internal Brand carrying a store's writability ('mutable' | 'writable' | 'readonly'), stamped
|
|
7
9
|
* on every store proxy. Read by `extendStore` instead of re-deriving via `isWritableSignal`,
|
|
@@ -9,27 +11,22 @@ export declare const SCOPE_PARENT: unique symbol;
|
|
|
9
11
|
*/
|
|
10
12
|
export declare const STORE_KIND: unique symbol;
|
|
11
13
|
export type StoreKind = 'mutable' | 'writable' | 'readonly';
|
|
12
|
-
/**
|
|
13
|
-
* @internal Brand exposing the injector a store was built with, so `extendStore` inherits it the
|
|
14
|
-
* same way `store.extend(...)` does (via closure) — no injection context needed at the call site.
|
|
15
|
-
*/
|
|
16
|
-
export declare const STORE_INJECTOR: unique symbol;
|
|
17
14
|
export declare const SIGNAL_FN_PROP: Set<string>;
|
|
18
15
|
/**
|
|
19
16
|
* @internal
|
|
20
|
-
* Test-only handle on the proxy cache (deliberately NOT re-exported from the public barrel).
|
|
21
17
|
* Maps a store's backing signal to its lazily-built child proxies, each held via a `WeakRef`.
|
|
22
18
|
*/
|
|
23
|
-
export
|
|
19
|
+
export type ProxyCache = WeakMap<object, Map<PropertyKey, WeakRef<Signal<any>>>>;
|
|
24
20
|
/**
|
|
25
21
|
* @internal
|
|
26
|
-
*
|
|
27
|
-
* barrel). Prunes a cache entry once its proxy is reclaimed by the GC.
|
|
22
|
+
* Prunes a cache entry once its proxy is reclaimed by the GC.
|
|
28
23
|
*/
|
|
29
|
-
export
|
|
24
|
+
export type ProxyCleanupRegistry = FinalizationRegistry<{
|
|
30
25
|
target: object;
|
|
31
26
|
prop: PropertyKey;
|
|
32
27
|
}>;
|
|
28
|
+
export declare const PROXY_CACHE_TOKEN: InjectionToken<ProxyCache>;
|
|
29
|
+
export declare const PROXY_CLEANUP_TOKEN: InjectionToken<ProxyCleanupRegistry>;
|
|
33
30
|
/**
|
|
34
31
|
* @internal
|
|
35
32
|
* Validates whether a value is a Signal Store.
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
export * from './fork-store';
|
|
2
|
-
export {
|
|
2
|
+
export { isStore } from './internals';
|
|
3
|
+
export { isLeaf } from './leaf';
|
|
4
|
+
export { isOpaque, opaque, type Opaque } from './opaque';
|
|
5
|
+
export { extendStore, mutableStore, store, toStore, type ExtendStoreOptions, type StoreOptions, type toStoreOptions, } from './store';
|
|
6
|
+
export type { MutableSignalStore, SignalStore, WritableSignalStore, } from './types';
|
package/lib/store/store.d.ts
CHANGED
|
@@ -1,17 +1,46 @@
|
|
|
1
1
|
import { Injector, type CreateSignalOptions, type Signal, type WritableSignal } from '@angular/core';
|
|
2
2
|
import { type MutableSignal } from '../mutable';
|
|
3
3
|
import { type Vivify } from '../util';
|
|
4
|
+
import { STORE_SHARED_GLOBALS, type ProxyCache, type ProxyCleanupRegistry } from './internals';
|
|
4
5
|
import { type AnyRecord, type MutableSignalStore, type SignalStore, type Simplify, type WritableSignalStore } from './types';
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
export type toStoreOptions = {
|
|
7
|
+
injector?: Injector;
|
|
8
|
+
/**
|
|
9
|
+
* Opt-in autovivification: when writing through a `null`/`undefined` path, create the
|
|
10
|
+
* missing intermediate containers instead of dropping the write. Off by default.
|
|
11
|
+
*
|
|
12
|
+
* Levels whose current value is a known object/array re-vivify as that same shape — the
|
|
13
|
+
* knowledge is captured when the path is first accessed and cached, so it holds even after
|
|
14
|
+
* the value is later nulled. This option governs only genuinely-unknown (currently
|
|
15
|
+
* `null`/`undefined`) levels: `'auto'` (an array for index keys, an object otherwise), an
|
|
16
|
+
* explicit `'object'`/`'array'`, or a `() => container` factory. See {@link Vivify}.
|
|
17
|
+
*/
|
|
18
|
+
vivify?: Vivify;
|
|
19
|
+
/**
|
|
20
|
+
* Performance opt-in: promise that no node ever switches between leaf and substore (i.e. no
|
|
21
|
+
* unions mixing a primitive with an object/array). With this on, each node's leaf-ness is
|
|
22
|
+
* resolved once on the first {@link isLeaf} probe and cached as a constant, skipping the
|
|
23
|
+
* reactive `computed`. If a node's shape does change anyway, {@link isLeaf} keeps its first
|
|
24
|
+
* answer. Off by default.
|
|
25
|
+
*/
|
|
26
|
+
noUnionLeaves?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* @internal
|
|
29
|
+
* Shared cleanup singletons, they get injected/passed automatically
|
|
30
|
+
*/
|
|
31
|
+
[STORE_SHARED_GLOBALS]?: {
|
|
32
|
+
cache: ProxyCache;
|
|
33
|
+
registry: ProxyCleanupRegistry;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export type StoreOptions<T> = CreateSignalOptions<T> & toStoreOptions;
|
|
37
|
+
export declare function toStore<T extends AnyRecord>(source: MutableSignal<T>, options?: toStoreOptions): MutableSignalStore<T>;
|
|
38
|
+
export declare function toStore<T extends AnyRecord>(source: WritableSignal<T>, options?: toStoreOptions): WritableSignalStore<T>;
|
|
39
|
+
export declare function toStore<T extends AnyRecord>(source: Signal<T>, options?: toStoreOptions): SignalStore<T>;
|
|
40
|
+
export type ExtendStoreOptions = Omit<toStoreOptions, 'vivify' | 'noUnionLeaves' | typeof STORE_SHARED_GLOBALS>;
|
|
41
|
+
export declare function extendStore<T extends AnyRecord, L extends AnyRecord>(store: MutableSignalStore<T>, source: MutableSignal<L> | L, options?: ExtendStoreOptions): MutableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
42
|
+
export declare function extendStore<T extends AnyRecord, L extends AnyRecord>(store: WritableSignalStore<T>, source: WritableSignal<L> | L, options?: ExtendStoreOptions): WritableSignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
43
|
+
export declare function extendStore<T extends AnyRecord, L extends AnyRecord>(store: SignalStore<T>, source: Signal<L> | L, options?: ExtendStoreOptions): SignalStore<Simplify<Omit<NonNullable<T>, keyof L> & L>>;
|
|
15
44
|
/**
|
|
16
45
|
* Creates a WritableSignalStore from a value.
|
|
17
46
|
* @see {@link toStore}
|