@mmstack/primitives 20.4.4 → 20.4.6
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/fesm2022/mmstack-primitives.mjs +254 -2
- package/fesm2022/mmstack-primitives.mjs.map +1 -1
- package/index.d.ts +120 -2
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateSignalOptions, DestroyRef, WritableSignal, Signal, ElementRef, Injector, ValueEqualityFn } from '@angular/core';
|
|
1
|
+
import { CreateSignalOptions, DestroyRef, WritableSignal, Signal, ElementRef, EffectCleanupRegisterFn, CreateEffectOptions, Injector, ValueEqualityFn } from '@angular/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Options for creating a debounced writable signal.
|
|
@@ -468,6 +468,82 @@ declare function mapArray<T, U>(source: Signal<T[]> | (() => T[]), map: (value:
|
|
|
468
468
|
onDestroy?: (value: U) => void;
|
|
469
469
|
}): Signal<U[]>;
|
|
470
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Creates an effect that can be nested, similar to SolidJS's `createEffect`.
|
|
473
|
+
*
|
|
474
|
+
* This primitive enables true hierarchical reactivity. A `nestedEffect` created
|
|
475
|
+
* within another `nestedEffect` is automatically destroyed and recreated when
|
|
476
|
+
* the parent re-runs.
|
|
477
|
+
*
|
|
478
|
+
* It automatically handles injector propagation and lifetime management, allowing
|
|
479
|
+
* you to create fine-grained, conditional side-effects that only track
|
|
480
|
+
* dependencies when they are "live".
|
|
481
|
+
*
|
|
482
|
+
* @param effectFn The side-effect function, which receives a cleanup register function.
|
|
483
|
+
* @param options (Optional) Angular's `CreateEffectOptions`.
|
|
484
|
+
* @returns An `EffectRef` for the created effect.
|
|
485
|
+
*
|
|
486
|
+
* @example
|
|
487
|
+
* ```ts
|
|
488
|
+
* // Assume `coldGuard` changes rarely, but `hotSignal` changes often.
|
|
489
|
+
* const coldGuard = signal(false);
|
|
490
|
+
* const hotSignal = signal(0);
|
|
491
|
+
*
|
|
492
|
+
* nestedEffect(() => {
|
|
493
|
+
* // This outer effect only tracks `coldGuard`.
|
|
494
|
+
* if (coldGuard()) {
|
|
495
|
+
*
|
|
496
|
+
* // This inner effect is CREATED when coldGuard is true
|
|
497
|
+
* // and DESTROYED when it becomes false.
|
|
498
|
+
* nestedEffect(() => {
|
|
499
|
+
* // It only tracks `hotSignal` while it exists.
|
|
500
|
+
* console.log('Hot signal is:', hotSignal());
|
|
501
|
+
* });
|
|
502
|
+
* }
|
|
503
|
+
* // If `coldGuard` is false, this outer effect does not track `hotSignal`.
|
|
504
|
+
* });
|
|
505
|
+
* ```
|
|
506
|
+
* @example
|
|
507
|
+
* ```ts
|
|
508
|
+
* const users = signal([
|
|
509
|
+
{ id: 1, name: 'Alice' },
|
|
510
|
+
{ id: 2, name: 'Bob' }
|
|
511
|
+
]);
|
|
512
|
+
|
|
513
|
+
// The fine-grained mapped list
|
|
514
|
+
const mappedUsers = mapArray(
|
|
515
|
+
users,
|
|
516
|
+
(userSignal, index) => {
|
|
517
|
+
// 1. Create a fine-grained SIDE EFFECT for *this item*
|
|
518
|
+
// This effect's lifetime is now tied to this specific item. created once on init of this index.
|
|
519
|
+
const effectRef = nestedEffect(() => {
|
|
520
|
+
// This only runs if *this* userSignal changes,
|
|
521
|
+
// not if the whole list changes.
|
|
522
|
+
console.log(`User ${index} updated:`, userSignal().name);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// 2. Return the data AND the cleanup logic
|
|
526
|
+
return {
|
|
527
|
+
// The mapped data
|
|
528
|
+
label: computed(() => `User: ${userSignal().name}`),
|
|
529
|
+
|
|
530
|
+
// The cleanup function
|
|
531
|
+
destroyEffect: () => effectRef.destroy()
|
|
532
|
+
};
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
// 3. Tell mapArray HOW to clean up when an item is removed, this needs to be manual as it's not a nestedEffect itself
|
|
536
|
+
onDestroy: (mappedItem) => {
|
|
537
|
+
mappedItem.destroyEffect();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
);
|
|
541
|
+
* ```
|
|
542
|
+
*/
|
|
543
|
+
declare function nestedEffect(effectFn: (registerCleanup: EffectCleanupRegisterFn) => void, options?: CreateEffectOptions): {
|
|
544
|
+
destroy: () => void;
|
|
545
|
+
};
|
|
546
|
+
|
|
471
547
|
/**
|
|
472
548
|
* A pure, synchronous transform from I -> O.
|
|
473
549
|
* Prefer transforms without side effects to keep derivations predictable.
|
|
@@ -1160,6 +1236,48 @@ type StoredSignal<T> = WritableSignal<T> & {
|
|
|
1160
1236
|
*/
|
|
1161
1237
|
declare function stored<T>(fallback: T, { key, store: providedStore, serialize, deserialize, syncTabs, equal, onKeyChange, cleanupOldKey, ...rest }: CreateStoredOptions<T>): StoredSignal<T>;
|
|
1162
1238
|
|
|
1239
|
+
type SyncSignalOptions = {
|
|
1240
|
+
id?: string;
|
|
1241
|
+
};
|
|
1242
|
+
/**
|
|
1243
|
+
* Synchronizes a WritableSignal across browser tabs using BroadcastChannel API.
|
|
1244
|
+
*
|
|
1245
|
+
* Creates a shared signal that automatically syncs its value between all tabs
|
|
1246
|
+
* of the same application. When the signal is updated in one tab, all other
|
|
1247
|
+
* tabs will receive the new value automatically.
|
|
1248
|
+
*
|
|
1249
|
+
* @template T - The type of the WritableSignal
|
|
1250
|
+
* @param sig - The WritableSignal to synchronize across tabs
|
|
1251
|
+
* @param opt - Optional configuration object
|
|
1252
|
+
* @param opt.id - Explicit channel ID for synchronization. If not provided,
|
|
1253
|
+
* a deterministic ID is generated based on the call site.
|
|
1254
|
+
* Use explicit IDs in production for reliability.
|
|
1255
|
+
*
|
|
1256
|
+
* @returns The same WritableSignal instance, now synchronized across tabs
|
|
1257
|
+
*
|
|
1258
|
+
* @throws {Error} When deterministic ID generation fails and no explicit ID is provided
|
|
1259
|
+
*
|
|
1260
|
+
* @example
|
|
1261
|
+
* ```typescript
|
|
1262
|
+
* // Basic usage - auto-generates channel ID from call site
|
|
1263
|
+
* const theme = tabSync(signal('dark'));
|
|
1264
|
+
*
|
|
1265
|
+
* // With explicit ID (recommended for production)
|
|
1266
|
+
* const userPrefs = tabSync(signal({ lang: 'en' }), { id: 'user-preferences' });
|
|
1267
|
+
*
|
|
1268
|
+
* // Changes in one tab will sync to all other tabs
|
|
1269
|
+
* theme.set('light'); // All tabs will update to 'light'
|
|
1270
|
+
* ```
|
|
1271
|
+
*
|
|
1272
|
+
* @remarks
|
|
1273
|
+
* - Only works in browser environments (returns original signal on server)
|
|
1274
|
+
* - Uses a single BroadcastChannel for all synchronized signals
|
|
1275
|
+
* - Automatically cleans up listeners when the injection context is destroyed
|
|
1276
|
+
* - Initial signal value after sync setup is not broadcasted to prevent loops
|
|
1277
|
+
*
|
|
1278
|
+
*/
|
|
1279
|
+
declare function tabSync<T extends WritableSignal<any>>(sig: T, opt?: SyncSignalOptions): T;
|
|
1280
|
+
|
|
1163
1281
|
/**
|
|
1164
1282
|
* Options for creating a throttled writable signal.
|
|
1165
1283
|
* Extends Angular's `CreateSignalOptions` with a throttle time setting.
|
|
@@ -1414,5 +1532,5 @@ type CreateHistoryOptions<T> = Omit<CreateSignalOptions<T[]>, 'equal'> & {
|
|
|
1414
1532
|
*/
|
|
1415
1533
|
declare function withHistory<T>(source: WritableSignal<T>, opt?: CreateHistoryOptions<T>): SignalWithHistory<T>;
|
|
1416
1534
|
|
|
1417
|
-
export { combineWith, debounce, debounced, derived, distinct, elementVisibility, filter, isDerivation, isMutable, map, mapArray, mediaQuery, mousePosition, mutable, networkStatus, pageVisibility, pipeable, piped, prefersDarkMode, prefersReducedMotion, scrollPosition, select, sensor, stored, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toWritable, until, windowSize, withHistory };
|
|
1535
|
+
export { combineWith, debounce, debounced, derived, distinct, elementVisibility, filter, isDerivation, isMutable, map, mapArray, mediaQuery, mousePosition, mutable, nestedEffect, networkStatus, pageVisibility, pipeable, piped, prefersDarkMode, prefersReducedMotion, scrollPosition, select, sensor, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toWritable, until, windowSize, withHistory };
|
|
1418
1536
|
export type { CreateDebouncedOptions, CreateHistoryOptions, CreateStoredOptions, CreateThrottledOptions, DebouncedSignal, DerivedSignal, ElementVisibilityOptions, ElementVisibilitySignal, MousePositionOptions, MousePositionSignal, MutableSignal, NetworkStatusSignal, PipeableSignal, ScrollPosition, ScrollPositionOptions, ScrollPositionSignal, SignalWithHistory, StoredSignal, ThrottledSignal, UntilOptions, WindowSize, WindowSizeOptions, WindowSizeSignal };
|