@mmstack/primitives 20.4.7 → 21.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/primitives",
3
- "version": "20.4.7",
3
+ "version": "21.0.1",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "signals",
@@ -15,18 +15,18 @@
15
15
  },
16
16
  "homepage": "https://github.com/mihajm/mmstack/blob/master/packages/primitives",
17
17
  "peerDependencies": {
18
- "@angular/core": ">=20 <21",
19
- "@angular/common": ">=20 <21"
18
+ "@angular/core": ">=21 <22",
19
+ "@angular/common": ">=21 <22"
20
20
  },
21
21
  "sideEffects": false,
22
22
  "module": "fesm2022/mmstack-primitives.mjs",
23
- "typings": "index.d.ts",
23
+ "typings": "types/mmstack-primitives.d.ts",
24
24
  "exports": {
25
25
  "./package.json": {
26
26
  "default": "./package.json"
27
27
  },
28
28
  ".": {
29
- "types": "./index.d.ts",
29
+ "types": "./types/mmstack-primitives.d.ts",
30
30
  "default": "./fesm2022/mmstack-primitives.mjs"
31
31
  }
32
32
  },
@@ -1,4 +1,4 @@
1
- import { CreateSignalOptions, DestroyRef, WritableSignal, Signal, ElementRef, EffectCleanupRegisterFn, CreateEffectOptions, Injector, ValueEqualityFn } from '@angular/core';
1
+ import { CreateSignalOptions, DestroyRef, WritableSignal, Signal, EffectCleanupRegisterFn, CreateEffectOptions, ElementRef, Injector, ValueEqualityFn } from '@angular/core';
2
2
 
3
3
  /**
4
4
  * Options for creating a debounced writable signal.
@@ -353,72 +353,6 @@ declare function toFakeSignalDerivation<T, U>(initial: WritableSignal<U>): Deriv
353
353
  */
354
354
  declare function isDerivation<T, U>(sig: WritableSignal<U>): sig is DerivedSignal<T, U>;
355
355
 
356
- /**
357
- * Options for configuring the `elementVisibility` sensor, extending
358
- * standard `IntersectionObserverInit` options.
359
- */
360
- type ElementVisibilityOptions = IntersectionObserverInit & {
361
- /** Optional debug name for the internal signal. */
362
- debugName?: string;
363
- };
364
- type ElementVisibilitySignal = Signal<IntersectionObserverEntry | undefined> & {
365
- readonly visible: Signal<boolean>;
366
- };
367
- /**
368
- * Creates a read-only signal that tracks the intersection status of a target DOM element
369
- * with the viewport or a specified root element, using the `IntersectionObserver` API.
370
- *
371
- * It can observe a static `ElementRef`/`Element` or a `Signal` that resolves to one,
372
- * allowing for dynamic targets.
373
- *
374
- * @param target The DOM element (or `ElementRef`, or a `Signal` resolving to one) to observe.
375
- * If the signal resolves to `null`, observation stops.
376
- * @param options Optional `IntersectionObserverInit` options (e.g., `root`, `rootMargin`, `threshold`)
377
- * and an optional `debugName`.
378
- * @returns A `Signal<IntersectionObserverEntry | undefined>`. It emits `undefined` initially,
379
- * on the server, or if the target is `null`. Otherwise, it emits the latest
380
- * `IntersectionObserverEntry`. Consumers can derive a boolean `isVisible` from
381
- * this entry's `isIntersecting` property.
382
- *
383
- * @example
384
- * ```ts
385
- * import { Component, effect, ElementRef, viewChild } from '@angular/core';
386
- * import { elementVisibility } from '@mmstack/primitives';
387
- * import { computed } from '@angular/core'; // For derived boolean
388
- *
389
- * @Component({
390
- * selector: 'app-lazy-image',
391
- * template: `
392
- * <div #imageContainer style="height: 200px; border: 1px dashed grey;">
393
- * @if (isVisible()) {
394
- * <img src="your-image-url.jpg" alt="Lazy loaded image" />
395
- * <p>Image is VISIBLE!</p>
396
- * } @else {
397
- * <p>Scroll down to see the image...</p>
398
- * }
399
- * </div>
400
- * `
401
- * })
402
- * export class LazyImageComponent {
403
- * readonly imageContainer = viewChild.required<ElementRef<HTMLDivElement>>('imageContainer');
404
- *
405
- * // Observe the element, get the full IntersectionObserverEntry
406
- * readonly intersectionEntry = elementVisibility(this.imageContainer);
407
- *
408
- * // Derive a simple boolean for visibility
409
- * readonly isVisible = computed(() => this.intersectionEntry()?.isIntersecting ?? false);
410
- *
411
- * constructor() {
412
- * effect(() => {
413
- * console.log('Intersection Entry:', this.intersectionEntry());
414
- * console.log('Is Visible:', this.isVisible());
415
- * });
416
- * }
417
- * }
418
- * ```
419
- */
420
- declare function elementVisibility(target?: ElementRef<Element> | Element | Signal<ElementRef<Element> | Element | null>, opt?: ElementVisibilityOptions): ElementVisibilitySignal;
421
-
422
356
  /**
423
357
  * Reactively maps items from a source array to a new array, creating stable signals for each item.
424
358
  *
@@ -449,7 +383,7 @@ declare function elementVisibility(target?: ElementRef<Element> | Element | Sign
449
383
  * ]);
450
384
  *
451
385
  * // The `itemSignal` is writable because `sourceItems` is a WritableSignal.
452
- * const mappedItems = mapArray(sourceItems, (itemSignal, index) => ({
386
+ * const mappedItems = indexArray(sourceItems, (itemSignal, index) => ({
453
387
  * label: computed(() => `${index}: ${itemSignal().name.toUpperCase()}`),
454
388
  * setName: (newName: string) => itemSignal.update(item => ({ ...item, name: newName }))
455
389
  * }));
@@ -458,13 +392,43 @@ declare function elementVisibility(target?: ElementRef<Element> | Element | Sign
458
392
  * mappedItems()[0].setName('Avocado');
459
393
  * // sourceItems() is now: [{ id: 1, name: 'Avocado' }, { id: 2, name: 'Banana' }]
460
394
  */
461
- declare function mapArray<T, U>(source: MutableSignal<T[]>, map: (value: MutableSignal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
395
+ declare function indexArray<T, U>(source: MutableSignal<T[]>, map: (value: MutableSignal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
396
+ onDestroy?: (value: U) => void;
397
+ }): Signal<U[]>;
398
+ declare function indexArray<T, U>(source: WritableSignal<T[]>, map: (value: WritableSignal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
399
+ onDestroy?: (value: U) => void;
400
+ }): Signal<U[]>;
401
+ declare function indexArray<T, U>(source: Signal<T[]> | (() => T[]), map: (value: Signal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
402
+ onDestroy?: (value: U) => void;
403
+ }): Signal<U[]>;
404
+ /**
405
+ * @deprecated use indexArray instead
406
+ */
407
+ declare const mapArray: typeof indexArray;
408
+
409
+ /**
410
+ * Reactively maps items from a source array to a new array using a key function to maintain stability.
411
+ *
412
+ * This function preserves the `mapped` signals for items even if they move within the array,
413
+ * as long as their key remains the same. This is equivalent to SolidJS's `mapArray` or Angular's `@for (item of items; track item.id)`.
414
+ *
415
+ * @template T The type of items in the source array.
416
+ * @template U The type of items in the resulting mapped array.
417
+ * @template K The type of the key.
418
+ *
419
+ * @param source A `Signal<T[]>` or a function returning `T[]`.
420
+ * @param keyFn A function to extract a unique key for each item.
421
+ * @param map The mapping function. It receives a stable signal for the item and a signal for its index.
422
+ * @param options Optional configuration, including `CreateSignalOptions` and an `onDestroy` callback.
423
+ * @returns A `Signal<U[]>` containing the mapped array.
424
+ */
425
+ declare function keyArray<T, U>(source: MutableSignal<T[]>, keyFn: (item: T) => string | number, map: (value: MutableSignal<T>, index: Signal<number>) => U, options?: CreateSignalOptions<T> & {
462
426
  onDestroy?: (value: U) => void;
463
427
  }): Signal<U[]>;
464
- declare function mapArray<T, U>(source: WritableSignal<T[]>, map: (value: WritableSignal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
428
+ declare function keyArray<T, U>(source: WritableSignal<T[]>, keyFn: (item: T) => string | number, map: (value: WritableSignal<T>, index: Signal<number>) => U, options?: CreateSignalOptions<T> & {
465
429
  onDestroy?: (value: U) => void;
466
430
  }): Signal<U[]>;
467
- declare function mapArray<T, U>(source: Signal<T[]> | (() => T[]), map: (value: Signal<T>, index: number) => U, options?: CreateSignalOptions<T> & {
431
+ declare function keyArray<T, U>(source: Signal<T[]> | (() => T[]), keyFn: (item: T) => string | number, map: (value: Signal<T>, index: Signal<number>) => U, options?: CreateSignalOptions<T> & {
468
432
  onDestroy?: (value: U) => void;
469
433
  }): Signal<U[]>;
470
434
 
@@ -640,6 +604,107 @@ declare function pipeable<TSig extends Signal<any>>(signal: TSig): PipeableSigna
640
604
  */
641
605
  declare function piped<T>(initial: T, opt?: CreateSignalOptions<T>): PipeableSignal<T, WritableSignal<T>>;
642
606
 
607
+ /**
608
+ * Represents the size of an element.
609
+ */
610
+ interface ElementSize {
611
+ width: number;
612
+ height: number;
613
+ }
614
+ /**
615
+ * Options for configuring the `elementSize` sensor.
616
+ */
617
+ type ElementSizeOptions = ResizeObserverOptions & {
618
+ /** Optional debug name for the internal signal. */
619
+ debugName?: string;
620
+ };
621
+ type ElementSizeSignal = Signal<ElementSize | undefined>;
622
+ /**
623
+ * Creates a read-only signal that tracks the size of a target DOM element.
624
+ *
625
+ * By default, it observes the `border-box` size to align with `getBoundingClientRect()`,
626
+ * which is used to provide a synchronous initial value if possible.
627
+ *
628
+ * @param target The DOM element (or `ElementRef`, or a `Signal` resolving to one) to observe.
629
+ * @param options Optional configuration including `box` (defaults to 'border-box') and `debugName`.
630
+ * @returns A `Signal<ElementSize | undefined>`.
631
+ *
632
+ * @example
633
+ * ```ts
634
+ * const size = elementSize(elementRef);
635
+ * effect(() => {
636
+ * console.log('Size:', size()?.width, size()?.height);
637
+ * });
638
+ * ```
639
+ */
640
+ declare function elementSize(target?: ElementRef<Element> | Element | Signal<ElementRef<Element> | Element | null>, opt?: ElementSizeOptions): ElementSizeSignal;
641
+
642
+ /**
643
+ * Options for configuring the `elementVisibility` sensor, extending
644
+ * standard `IntersectionObserverInit` options.
645
+ */
646
+ type ElementVisibilityOptions = IntersectionObserverInit & {
647
+ /** Optional debug name for the internal signal. */
648
+ debugName?: string;
649
+ };
650
+ type ElementVisibilitySignal = Signal<IntersectionObserverEntry | undefined> & {
651
+ readonly visible: Signal<boolean>;
652
+ };
653
+ /**
654
+ * Creates a read-only signal that tracks the intersection status of a target DOM element
655
+ * with the viewport or a specified root element, using the `IntersectionObserver` API.
656
+ *
657
+ * It can observe a static `ElementRef`/`Element` or a `Signal` that resolves to one,
658
+ * allowing for dynamic targets.
659
+ *
660
+ * @param target The DOM element (or `ElementRef`, or a `Signal` resolving to one) to observe.
661
+ * If the signal resolves to `null`, observation stops.
662
+ * @param options Optional `IntersectionObserverInit` options (e.g., `root`, `rootMargin`, `threshold`)
663
+ * and an optional `debugName`.
664
+ * @returns A `Signal<IntersectionObserverEntry | undefined>`. It emits `undefined` initially,
665
+ * on the server, or if the target is `null`. Otherwise, it emits the latest
666
+ * `IntersectionObserverEntry`. Consumers can derive a boolean `isVisible` from
667
+ * this entry's `isIntersecting` property.
668
+ *
669
+ * @example
670
+ * ```ts
671
+ * import { Component, effect, ElementRef, viewChild } from '@angular/core';
672
+ * import { elementVisibility } from '@mmstack/primitives';
673
+ * import { computed } from '@angular/core'; // For derived boolean
674
+ *
675
+ * @Component({
676
+ * selector: 'app-lazy-image',
677
+ * template: `
678
+ * <div #imageContainer style="height: 200px; border: 1px dashed grey;">
679
+ * @if (isVisible()) {
680
+ * <img src="your-image-url.jpg" alt="Lazy loaded image" />
681
+ * <p>Image is VISIBLE!</p>
682
+ * } @else {
683
+ * <p>Scroll down to see the image...</p>
684
+ * }
685
+ * </div>
686
+ * `
687
+ * })
688
+ * export class LazyImageComponent {
689
+ * readonly imageContainer = viewChild.required<ElementRef<HTMLDivElement>>('imageContainer');
690
+ *
691
+ * // Observe the element, get the full IntersectionObserverEntry
692
+ * readonly intersectionEntry = elementVisibility(this.imageContainer);
693
+ *
694
+ * // Derive a simple boolean for visibility
695
+ * readonly isVisible = computed(() => this.intersectionEntry()?.isIntersecting ?? false);
696
+ *
697
+ * constructor() {
698
+ * effect(() => {
699
+ * console.log('Intersection Entry:', this.intersectionEntry());
700
+ * console.log('Is Visible:', this.isVisible());
701
+ * });
702
+ * }
703
+ * }
704
+ * ```
705
+ */
706
+ declare function elementVisibility(target?: ElementRef<Element> | Element | Signal<ElementRef<Element> | Element | null>, opt?: ElementVisibilityOptions): ElementVisibilitySignal;
707
+
643
708
  /**
644
709
  * Creates a read-only signal that reactively tracks whether a CSS media query
645
710
  * string currently matches.
@@ -1029,6 +1094,81 @@ type WindowSizeSignal = Signal<WindowSize> & {
1029
1094
  */
1030
1095
  declare function windowSize(opt?: WindowSizeOptions): WindowSizeSignal;
1031
1096
 
1097
+ type SensorTypedOptions = {
1098
+ elementVisibility: {
1099
+ opt: ElementVisibilityOptions & {
1100
+ target?: ElementRef<Element> | Element | Signal<ElementRef<Element> | Element | null>;
1101
+ };
1102
+ returnType: ElementVisibilitySignal;
1103
+ };
1104
+ elementSize: {
1105
+ opt: ElementSizeOptions & {
1106
+ target?: ElementRef<Element> | Element | Signal<ElementRef<Element> | Element | null>;
1107
+ };
1108
+ returnType: ElementSizeSignal;
1109
+ };
1110
+ mousePosition: {
1111
+ opt: MousePositionOptions;
1112
+ returnType: MousePositionSignal;
1113
+ };
1114
+ networkStatus: {
1115
+ opt: {
1116
+ debugName?: string;
1117
+ };
1118
+ returnType: NetworkStatusSignal;
1119
+ };
1120
+ pageVisibility: {
1121
+ opt: {
1122
+ debugName?: string;
1123
+ };
1124
+ returnType: Signal<DocumentVisibilityState>;
1125
+ };
1126
+ darkMode: {
1127
+ opt: {
1128
+ debugName?: string;
1129
+ };
1130
+ returnType: Signal<boolean>;
1131
+ };
1132
+ reducedMotion: {
1133
+ opt: {
1134
+ debugName?: string;
1135
+ };
1136
+ returnType: Signal<boolean>;
1137
+ };
1138
+ scrollPosition: {
1139
+ opt: ScrollPositionOptions;
1140
+ returnType: ScrollPositionSignal;
1141
+ };
1142
+ windowSize: {
1143
+ opt: WindowSizeOptions;
1144
+ returnType: WindowSizeSignal;
1145
+ };
1146
+ mediaQuery: {
1147
+ opt: {
1148
+ query: string;
1149
+ debugName?: string;
1150
+ };
1151
+ returnType: Signal<boolean>;
1152
+ };
1153
+ };
1154
+ /**
1155
+ * Creates a sensor signal that the elements visiblity within the viewport
1156
+ * @param type Must be `'elementVisibility'`.
1157
+ * @param options Optional configuration IntersectionObserver & target.
1158
+ * @returns A `ElementVisibilitySignal` that tracks whether the Element is intersected.
1159
+ * @see {elementVisibility} for detailed documentation and examples.
1160
+ * @example const pos = sensor('elementVisibility');
1161
+ */
1162
+ declare function sensor(type: 'elementVisibility', options?: SensorTypedOptions['elementVisibility']['opt']): ElementVisibilitySignal;
1163
+ /**
1164
+ * Creates a sensor signal that tracks the element's size dimensions.
1165
+ * @param type Must be `'elementSize'`.
1166
+ * @param options Optional configuration ResizeObserver & target.
1167
+ * @returns A `ElementSizeSignal` that tracks the element's size ({ width, height }).
1168
+ * @see {elementSize} for detailed documentation and examples.
1169
+ * @example const size = sensor('elementSize');
1170
+ */
1171
+ declare function sensor(type: 'elementSize', options?: SensorTypedOptions['elementSize']['opt']): ElementSizeSignal;
1032
1172
  /**
1033
1173
  * Creates a sensor signal that tracks the mouse cursor's position.
1034
1174
  * @param type Must be `'mousePosition'`.
@@ -1037,7 +1177,7 @@ declare function windowSize(opt?: WindowSizeOptions): WindowSizeSignal;
1037
1177
  * @see {mousePosition} for detailed documentation and examples.
1038
1178
  * @example const pos = sensor('mousePosition', { coordinateSpace: 'page', throttle: 50 });
1039
1179
  */
1040
- declare function sensor(type: 'mousePosition', options?: MousePositionOptions): MousePositionSignal;
1180
+ declare function sensor(type: 'mousePosition', options?: SensorTypedOptions['mousePosition']['opt']): MousePositionSignal;
1041
1181
  /**
1042
1182
  * Creates a sensor signal that tracks the browser's online/offline status.
1043
1183
  * @param type Must be `'networkStatus'`.
@@ -1046,9 +1186,7 @@ declare function sensor(type: 'mousePosition', options?: MousePositionOptions):
1046
1186
  * @see {networkStatus} for detailed documentation and examples.
1047
1187
  * @example const onlineStatus = sensor('networkStatus');
1048
1188
  */
1049
- declare function sensor(type: 'networkStatus', options?: {
1050
- debugName?: string;
1051
- }): NetworkStatusSignal;
1189
+ declare function sensor(type: 'networkStatus', options?: SensorTypedOptions['networkStatus']['opt']): NetworkStatusSignal;
1052
1190
  /**
1053
1191
  * Creates a sensor signal that tracks the page's visibility state (e.g., 'visible', 'hidden').
1054
1192
  * @param type Must be `'pageVisibility'`.
@@ -1057,31 +1195,34 @@ declare function sensor(type: 'networkStatus', options?: {
1057
1195
  * @see {pageVisibility} for detailed documentation and examples.
1058
1196
  * @example const visibility = sensor('pageVisibility');
1059
1197
  */
1060
- declare function sensor(type: 'pageVisibility', options?: {
1061
- debugName?: string;
1062
- }): Signal<DocumentVisibilityState>;
1198
+ declare function sensor(type: 'pageVisibility', options?: SensorTypedOptions['pageVisibility']['opt']): Signal<DocumentVisibilityState>;
1063
1199
  /**
1064
1200
  * Creates a sensor signal that tracks the user's OS/browser preference for a dark color scheme.
1065
- * @param type Must be `'dark-mode'`.
1201
+ * @param type Must be `'darkMode'`.
1066
1202
  * @param options Optional configuration, currently only `debugName`.
1067
1203
  * @returns A `Signal<boolean>` which is `true` if a dark theme is preferred.
1068
1204
  * @see {prefersDarkMode} for detailed documentation and examples.
1069
1205
  * @example const isDarkMode = sensor('dark-mode');
1070
1206
  */
1071
- declare function sensor(type: 'dark-mode', options?: {
1072
- debugName?: string;
1073
- }): Signal<boolean>;
1207
+ declare function sensor(type: 'darkMode' | 'dark-mode', options?: SensorTypedOptions['darkMode']['opt']): Signal<boolean>;
1074
1208
  /**
1075
1209
  * Creates a sensor signal that tracks the user's OS/browser preference for reduced motion.
1076
- * @param type Must be `'reduced-motion'`.
1210
+ * @param type Must be `'reducedMotion'`.
1077
1211
  * @param options Optional configuration, currently only `debugName`.
1078
1212
  * @returns A `Signal<boolean>` which is `true` if reduced motion is preferred.
1079
1213
  * @see {prefersReducedMotion} for detailed documentation and examples.
1080
1214
  * @example const wantsReducedMotion = sensor('reduced-motion');
1081
1215
  */
1082
- declare function sensor(type: 'reduced-motion', options?: {
1083
- debugName?: string;
1084
- }): Signal<boolean>;
1216
+ declare function sensor(type: 'reducedMotion' | 'reduced-motion', options?: SensorTypedOptions['reducedMotion']['opt']): Signal<boolean>;
1217
+ /**
1218
+ * Creates a sensor signal that tracks the provided media query.
1219
+ * @param type Must be `'mediaQuery'`.
1220
+ * @param options Optional configuration for the media query sensor, including `query` and `debugName`.
1221
+ * @returns A `Signal<boolean>` which is `true` if the media query currently matches.
1222
+ * @see {mediaQuery} for detailed documentation and examples.
1223
+ * @example const isDesktop = sensor('mediaQuery', { query: '(min-width: 1024px)' });
1224
+ */
1225
+ declare function sensor(type: 'mediaQuery', options?: SensorTypedOptions['mediaQuery']['opt']): Signal<boolean>;
1085
1226
  /**
1086
1227
  * Creates a sensor signal that tracks the browser window's inner dimensions (width and height).
1087
1228
  * @param type Must be `'windowSize'`.
@@ -1090,7 +1231,7 @@ declare function sensor(type: 'reduced-motion', options?: {
1090
1231
  * @see {windowSize} for detailed documentation and examples.
1091
1232
  * @example const size = sensor('windowSize', { throttle: 200 });
1092
1233
  */
1093
- declare function sensor(type: 'windowSize', options?: WindowSizeOptions): WindowSizeSignal;
1234
+ declare function sensor(type: 'windowSize', options?: SensorTypedOptions['windowSize']['opt']): WindowSizeSignal;
1094
1235
  /**
1095
1236
  * Creates a sensor signal that tracks the scroll position (x, y) of the window or a specified element.
1096
1237
  * @param type Must be `'scrollPosition'`.
@@ -1099,7 +1240,14 @@ declare function sensor(type: 'windowSize', options?: WindowSizeOptions): Window
1099
1240
  * @see {scrollPosition} for detailed documentation and examples.
1100
1241
  * @example const pageScroll = sensor('scrollPosition', { throttle: 150 });
1101
1242
  */
1102
- declare function sensor(type: 'scrollPosition', options?: ScrollPositionOptions): ScrollPositionSignal;
1243
+ declare function sensor(type: 'scrollPosition', options?: SensorTypedOptions['scrollPosition']['opt']): ScrollPositionSignal;
1244
+ type SensorsOptions<TKey extends keyof SensorTypedOptions> = {
1245
+ [K in TKey]: SensorTypedOptions[K]['opt'];
1246
+ };
1247
+ type Sensors<TKey extends keyof SensorTypedOptions> = {
1248
+ [K in TKey]: SensorTypedOptions[K]['returnType'];
1249
+ };
1250
+ declare function sensors<const TType extends keyof SensorTypedOptions>(track: TType[], opt?: SensorsOptions<TType>): Sensors<TType>;
1103
1251
 
1104
1252
  /**
1105
1253
  * Interface for storage mechanisms compatible with the `stored` signal.
@@ -1380,7 +1528,9 @@ declare function throttle<T>(source: WritableSignal<T>, opt?: CreateThrottledOpt
1380
1528
  *
1381
1529
  * writableSignal.set(5); // sets value of originalValue.a to 5 & triggers all signals
1382
1530
  */
1383
- declare function toWritable<T>(signal: Signal<T>, set: (value: T) => void, update?: (updater: (value: T) => T) => void): WritableSignal<T>;
1531
+ declare function toWritable<T>(source: Signal<T>, set: (value: T) => void, update?: (updater: (value: T) => T) => void, opt?: CreateSignalOptions<T> & {
1532
+ pure?: boolean;
1533
+ }): WritableSignal<T>;
1384
1534
 
1385
1535
  type UntilOptions = {
1386
1536
  /**
@@ -1532,5 +1682,5 @@ type CreateHistoryOptions<T> = Omit<CreateSignalOptions<T[]>, 'equal'> & {
1532
1682
  */
1533
1683
  declare function withHistory<T>(source: WritableSignal<T>, opt?: CreateHistoryOptions<T>): SignalWithHistory<T>;
1534
1684
 
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 };
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 };
1685
+ export { combineWith, debounce, debounced, derived, distinct, elementSize, elementVisibility, filter, indexArray, isDerivation, isMutable, keyArray, map, mapArray, mediaQuery, mousePosition, mutable, nestedEffect, networkStatus, pageVisibility, pipeable, piped, prefersDarkMode, prefersReducedMotion, scrollPosition, select, sensor, sensors, stored, tabSync, tap, throttle, throttled, toFakeDerivation, toFakeSignalDerivation, toWritable, until, windowSize, withHistory };
1686
+ export type { CreateDebouncedOptions, CreateHistoryOptions, CreateStoredOptions, CreateThrottledOptions, DebouncedSignal, DerivedSignal, ElementSize, ElementSizeOptions, ElementSizeSignal, ElementVisibilityOptions, ElementVisibilitySignal, MousePositionOptions, MousePositionSignal, MutableSignal, NetworkStatusSignal, PipeableSignal, ScrollPosition, ScrollPositionOptions, ScrollPositionSignal, SignalWithHistory, StoredSignal, ThrottledSignal, UntilOptions, WindowSize, WindowSizeOptions, WindowSizeSignal };