@mmstack/primitives 22.1.2 → 22.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -418,6 +418,8 @@ export class UserProfile {
|
|
|
418
418
|
|
|
419
419
|
This is also the pattern for coordinating resources registered _above_ a boundary (e.g. an app-builder page whose connectors register at a higher injector): the outer `provideTransitionScope()` is the shared scope, and any number of `<mm-unscoped-suspense>` boundaries observe it.
|
|
420
420
|
|
|
421
|
+
**Forwarding scope (advanced).** `provideForwardingTransitionScope()` provides a scope that can be **re-pointed at a different target at runtime** via `setTarget(scope | null)` — reads follow the current target, while `add`/`remove` pin to the target a resource was registered under (so re-pointing never strands a registration). It's the building block for a coordinator that hosts several independent sub-scopes and switches which one it observes — e.g. a router outlet that, per navigation, points at the incoming route's own scope (read it from any injector with `getTransitionScope(injector)`). Most apps reach for `provideTransitionScope()`; this is for that one extra level of control.
|
|
422
|
+
|
|
421
423
|
### `injectStartTransition`
|
|
422
424
|
|
|
423
425
|
The analog of React's `useTransition`. `startTransition(fn)` runs your state mutations (which commit immediately); any resource that reloads as a result **holds its value and reveals together once everything settles** — so a multi-resource update lands as one consistent frame instead of a torn mix of new and stale. The returned handle gives you a unified `pending` signal and a `done` promise for imperative coordination (disable a button, await completion).
|
|
@@ -80,7 +80,7 @@ function popFrame() {
|
|
|
80
80
|
* ]);
|
|
81
81
|
*
|
|
82
82
|
* // The fine-grained mapped list
|
|
83
|
-
* const mappedUsers =
|
|
83
|
+
* const mappedUsers = indexArray(
|
|
84
84
|
* users,
|
|
85
85
|
* (userSignal, index) => {
|
|
86
86
|
* // 1. Create a fine-grained SIDE EFFECT for *this item*
|
|
@@ -101,7 +101,7 @@ function popFrame() {
|
|
|
101
101
|
* };
|
|
102
102
|
* },
|
|
103
103
|
* {
|
|
104
|
-
* // 3. Tell
|
|
104
|
+
* // 3. Tell indexArray HOW to clean up when an item is removed, this needs to be manual as it's not a nestedEffect itself
|
|
105
105
|
* onDestroy: (mappedItem) => {
|
|
106
106
|
* mappedItem.destroyEffect();
|
|
107
107
|
* }
|
|
@@ -280,10 +280,10 @@ class MmActivity {
|
|
|
280
280
|
else
|
|
281
281
|
this.view.detach();
|
|
282
282
|
}
|
|
283
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
284
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
283
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: MmActivity, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
284
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: MmActivity, isStandalone: true, selector: "[mmActivity]", inputs: { visible: { classPropertyName: "visible", publicName: "mmActivity", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
285
285
|
}
|
|
286
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: MmActivity, decorators: [{
|
|
287
287
|
type: Directive,
|
|
288
288
|
args: [{
|
|
289
289
|
selector: '[mmActivity]',
|
|
@@ -565,6 +565,48 @@ function injectTransitionScope() {
|
|
|
565
565
|
}
|
|
566
566
|
return scope;
|
|
567
567
|
}
|
|
568
|
+
function createForwardingScope() {
|
|
569
|
+
const own = createTransitionScope();
|
|
570
|
+
const target = signal(null, /* @ts-ignore */
|
|
571
|
+
...(ngDevMode ? [{ debugName: "target" }] : /* istanbul ignore next */ []));
|
|
572
|
+
const eff = () => target() ?? own;
|
|
573
|
+
const owners = new Map();
|
|
574
|
+
return {
|
|
575
|
+
setTarget: (t) => target.set(t),
|
|
576
|
+
resources: computed(() => eff().resources()),
|
|
577
|
+
pending: computed(() => eff().pending()),
|
|
578
|
+
suspended: (type) => eff().suspended(type),
|
|
579
|
+
add: (ref, opt) => {
|
|
580
|
+
const t = untracked(target) ?? own;
|
|
581
|
+
owners.set(ref, t);
|
|
582
|
+
t.add(ref, opt);
|
|
583
|
+
},
|
|
584
|
+
remove: (ref) => {
|
|
585
|
+
const t = owners.get(ref) ?? untracked(target) ?? own;
|
|
586
|
+
t.remove(ref);
|
|
587
|
+
owners.delete(ref);
|
|
588
|
+
},
|
|
589
|
+
commit: (value) => linkedSignal({
|
|
590
|
+
source: () => ({ v: value(), settled: !eff().pending() }),
|
|
591
|
+
computation: (curr, prev) => curr.settled || prev === undefined ? curr.v : prev.value,
|
|
592
|
+
}),
|
|
593
|
+
holding: computed(() => eff().holding()),
|
|
594
|
+
beginHold: () => (untracked(target) ?? own).beginHold(),
|
|
595
|
+
endHold: () => (untracked(target) ?? own).endHold(),
|
|
596
|
+
hold: (value) => linkedSignal({
|
|
597
|
+
source: () => ({ v: value(), held: eff().holding() }),
|
|
598
|
+
computation: (curr, prev) => prev !== undefined && curr.held ? prev.value : curr.v,
|
|
599
|
+
}),
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
/** Provide a forwarding transition scope at a boundary (used by the transition outlet). */
|
|
603
|
+
function provideForwardingTransitionScope() {
|
|
604
|
+
return { provide: TRANSITION_SCOPE, useFactory: createForwardingScope };
|
|
605
|
+
}
|
|
606
|
+
/** Read the transition scope reachable from `injector`, or null if none is provided there. */
|
|
607
|
+
function getTransitionScope(injector) {
|
|
608
|
+
return injector.get(TRANSITION_SCOPE, null);
|
|
609
|
+
}
|
|
568
610
|
/**
|
|
569
611
|
* Returns a register function bound to the nearest transition scope: it adds a resource
|
|
570
612
|
* to the scope and removes it when the caller's injection context is destroyed. Pass any
|
|
@@ -652,10 +694,10 @@ class SuspenseBoundaryBase {
|
|
|
652
694
|
pending = this.scope.pending;
|
|
653
695
|
suspended = computed(() => this.scope.suspended(this.type()), /* @ts-ignore */
|
|
654
696
|
...(ngDevMode ? [{ debugName: "suspended" }] : /* istanbul ignore next */ []));
|
|
655
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
656
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
697
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: SuspenseBoundaryBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
698
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: SuspenseBoundaryBase, isStandalone: true, inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
657
699
|
}
|
|
658
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
700
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: SuspenseBoundaryBase, decorators: [{
|
|
659
701
|
type: Directive
|
|
660
702
|
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }] } });
|
|
661
703
|
const SUSPENSE_TEMPLATE = `
|
|
@@ -683,10 +725,10 @@ const SUSPENSE_HOST = {
|
|
|
683
725
|
* `provideTransitionScope()`. The common case.
|
|
684
726
|
*/
|
|
685
727
|
class SuspenseBoundary extends SuspenseBoundaryBase {
|
|
686
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
687
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.
|
|
728
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: SuspenseBoundary, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
729
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: SuspenseBoundary, isStandalone: true, selector: "mm-suspense", host: { properties: { "attr.aria-busy": "pending() ? true : null" } }, providers: [provideTransitionScope()], usesInheritance: true, ngImport: i0, template: "\n @if (suspended()) {\n <ng-content select=\"[placeholder]\"><span>Loading\u2026</span></ng-content>\n } @else {\n @if (pending()) {\n <ng-content select=\"[busy]\" />\n }\n <ng-content />\n }\n", isInline: true, styles: [":host{display:contents}\n"] });
|
|
688
730
|
}
|
|
689
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
731
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: SuspenseBoundary, decorators: [{
|
|
690
732
|
type: Component,
|
|
691
733
|
args: [{ selector: 'mm-suspense', template: SUSPENSE_TEMPLATE, host: SUSPENSE_HOST, providers: [provideTransitionScope()], styles: [":host{display:contents}\n"] }]
|
|
692
734
|
}] });
|
|
@@ -698,10 +740,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
|
|
|
698
740
|
* ancestor.
|
|
699
741
|
*/
|
|
700
742
|
class UnscopedSuspenseBoundary extends SuspenseBoundaryBase {
|
|
701
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
702
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.
|
|
743
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: UnscopedSuspenseBoundary, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
744
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: UnscopedSuspenseBoundary, isStandalone: true, selector: "mm-unscoped-suspense", host: { properties: { "attr.aria-busy": "pending() ? true : null" } }, usesInheritance: true, ngImport: i0, template: "\n @if (suspended()) {\n <ng-content select=\"[placeholder]\"><span>Loading\u2026</span></ng-content>\n } @else {\n @if (pending()) {\n <ng-content select=\"[busy]\" />\n }\n <ng-content />\n }\n", isInline: true, styles: [":host{display:contents}\n"] });
|
|
703
745
|
}
|
|
704
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
746
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: UnscopedSuspenseBoundary, decorators: [{
|
|
705
747
|
type: Component,
|
|
706
748
|
args: [{ selector: 'mm-unscoped-suspense', template: SUSPENSE_TEMPLATE, host: SUSPENSE_HOST, styles: [":host{display:contents}\n"] }]
|
|
707
749
|
}] });
|
|
@@ -3970,10 +4012,10 @@ class MessageBus {
|
|
|
3970
4012
|
this.channel.close();
|
|
3971
4013
|
this.listeners.clear();
|
|
3972
4014
|
}
|
|
3973
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
3974
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.
|
|
4015
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: MessageBus, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4016
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: MessageBus, providedIn: 'root' });
|
|
3975
4017
|
}
|
|
3976
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
4018
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: MessageBus, decorators: [{
|
|
3977
4019
|
type: Injectable,
|
|
3978
4020
|
args: [{
|
|
3979
4021
|
providedIn: 'root',
|
|
@@ -4278,5 +4320,5 @@ function withHistory(sourceOrValue, opt) {
|
|
|
4278
4320
|
* Generated bundle index. Do not edit.
|
|
4279
4321
|
*/
|
|
4280
4322
|
|
|
4281
|
-
export { MmActivity, SuspenseBoundary, SuspenseBoundaryBase, UnscopedSuspenseBoundary, activeTransaction, batteryStatus, chunked, clipboard, combineWith, createTransaction, createTransitionScope, debounce, debounced, derived, distinct, elementSize, elementVisibility, filter, filterWith, focusWithin, forkStore, geolocation, holdUntilReady, idle, indexArray, injectPaused, injectRegisterResource, injectStartTransaction, injectStartTransition, injectTransitionScope, isDerivation, isLeaf, isMutable, isOpaque, isStore, keepPrevious, keyArray, map, mapArray, mapObject, mediaQuery, merge3, mousePosition, mutable, mutableStore, nestedEffect, networkStatus, opaque, orientation, pageVisibility, pairwise, pausableComputed, pausableEffect, pausableSignal, pipeable, piped, pooled, pooledArray, pooledMap, pooledSet, prefersDarkMode, prefersReducedMotion, providePaused, provideTransitionScope, registerResource, resolvePause, scan, scrollPosition, select, sensor, sensors, signalFromEvent, startWith, store, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toStore, toWritable, until, windowSize, withHistory };
|
|
4323
|
+
export { MmActivity, SuspenseBoundary, SuspenseBoundaryBase, UnscopedSuspenseBoundary, activeTransaction, batteryStatus, chunked, clipboard, combineWith, createForwardingScope, createTransaction, createTransitionScope, debounce, debounced, derived, distinct, elementSize, elementVisibility, filter, filterWith, focusWithin, forkStore, geolocation, getTransitionScope, holdUntilReady, idle, indexArray, injectPaused, injectRegisterResource, injectStartTransaction, injectStartTransition, injectTransitionScope, isDerivation, isLeaf, isMutable, isOpaque, isStore, keepPrevious, keyArray, map, mapArray, mapObject, mediaQuery, merge3, mousePosition, mutable, mutableStore, nestedEffect, networkStatus, opaque, orientation, pageVisibility, pairwise, pausableComputed, pausableEffect, pausableSignal, pipeable, piped, pooled, pooledArray, pooledMap, pooledSet, prefersDarkMode, prefersReducedMotion, provideForwardingTransitionScope, providePaused, provideTransitionScope, registerResource, resolvePause, scan, scrollPosition, select, sensor, sensors, signalFromEvent, startWith, store, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toStore, toWritable, until, windowSize, withHistory };
|
|
4282
4324
|
//# sourceMappingURL=mmstack-primitives.mjs.map
|