@rlabs-inc/signals 0.2.0 → 1.1.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 +238 -198
- package/dist/collections/date.d.ts +67 -0
- package/dist/collections/date.d.ts.map +1 -0
- package/dist/collections/map.d.ts +37 -0
- package/dist/collections/map.d.ts.map +1 -0
- package/dist/collections/set.d.ts +36 -0
- package/dist/collections/set.d.ts.map +1 -0
- package/dist/core/constants.d.ts +47 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/globals.d.ts +45 -0
- package/dist/core/globals.d.ts.map +1 -0
- package/dist/core/types.d.ts +76 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/deep/proxy.d.ts +19 -0
- package/dist/deep/proxy.d.ts.map +1 -0
- package/dist/index.d.ts +16 -277
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1268 -607
- package/dist/index.mjs +1267 -608
- package/dist/primitives/bind.d.ts +95 -0
- package/dist/primitives/bind.d.ts.map +1 -0
- package/dist/primitives/derived.d.ts +45 -0
- package/dist/primitives/derived.d.ts.map +1 -0
- package/dist/primitives/effect.d.ts +41 -0
- package/dist/primitives/effect.d.ts.map +1 -0
- package/dist/primitives/signal.d.ts +54 -0
- package/dist/primitives/signal.d.ts.map +1 -0
- package/dist/reactivity/batching.d.ts +56 -0
- package/dist/reactivity/batching.d.ts.map +1 -0
- package/dist/reactivity/equality.d.ts +36 -0
- package/dist/reactivity/equality.d.ts.map +1 -0
- package/dist/reactivity/scheduling.d.ts +26 -0
- package/dist/reactivity/scheduling.d.ts.map +1 -0
- package/dist/reactivity/tracking.d.ts +47 -0
- package/dist/reactivity/tracking.d.ts.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { WritableSignal, ReadableSignal } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A writable binding that forwards reads and writes to a source.
|
|
4
|
+
* Reading creates dependency on source, writing triggers source's reactions.
|
|
5
|
+
*/
|
|
6
|
+
export interface Binding<T> {
|
|
7
|
+
get value(): T;
|
|
8
|
+
set value(v: T);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A read-only binding that forwards reads to a source.
|
|
12
|
+
* Reading creates dependency on source, writing throws an error.
|
|
13
|
+
*/
|
|
14
|
+
export interface ReadonlyBinding<T> {
|
|
15
|
+
readonly value: T;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if a value is a binding created by bind()
|
|
19
|
+
*/
|
|
20
|
+
export declare function isBinding(value: unknown): value is Binding<unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Create a reactive binding to a signal or another binding.
|
|
23
|
+
*
|
|
24
|
+
* A binding is a "reactive pointer" - it forwards reads and writes to the source.
|
|
25
|
+
* This enables connecting user's reactive state to internal component state.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const source = signal(0)
|
|
30
|
+
* const binding = bind(source)
|
|
31
|
+
*
|
|
32
|
+
* // Reading through binding reads from source (creates dependency)
|
|
33
|
+
* console.log(binding.value) // → 0
|
|
34
|
+
*
|
|
35
|
+
* // Writing through binding writes to source (triggers reactivity)
|
|
36
|
+
* binding.value = 42
|
|
37
|
+
* console.log(source.value) // → 42
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example Two-way binding for inputs
|
|
41
|
+
* ```ts
|
|
42
|
+
* const username = signal('')
|
|
43
|
+
* const inputBinding = bind(username)
|
|
44
|
+
*
|
|
45
|
+
* // When user types:
|
|
46
|
+
* inputBinding.value = 'alice' // Updates username signal!
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example Chaining bindings
|
|
50
|
+
* ```ts
|
|
51
|
+
* const source = signal(0)
|
|
52
|
+
* const b1 = bind(source)
|
|
53
|
+
* const b2 = bind(b1) // Points to same source
|
|
54
|
+
*
|
|
55
|
+
* b2.value = 99
|
|
56
|
+
* console.log(source.value) // → 99
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function bind<T>(source: WritableSignal<T>): Binding<T>;
|
|
60
|
+
export declare function bind<T>(source: ReadableSignal<T>): ReadonlyBinding<T>;
|
|
61
|
+
export declare function bind<T>(source: Binding<T>): Binding<T>;
|
|
62
|
+
export declare function bind<T>(source: ReadonlyBinding<T>): ReadonlyBinding<T>;
|
|
63
|
+
/**
|
|
64
|
+
* Create an explicitly read-only binding.
|
|
65
|
+
* Attempting to write will throw an error at runtime.
|
|
66
|
+
*
|
|
67
|
+
* Use this when you want to ensure a binding is never written to,
|
|
68
|
+
* even if the source is writable.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* const source = signal(0)
|
|
73
|
+
* const readonly = bindReadonly(source)
|
|
74
|
+
*
|
|
75
|
+
* console.log(readonly.value) // → 0
|
|
76
|
+
* readonly.value = 42 // Throws: Cannot write to a read-only binding
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function bindReadonly<T>(source: ReadableSignal<T> | Binding<T>): ReadonlyBinding<T>;
|
|
80
|
+
/**
|
|
81
|
+
* Get the value from a binding or return the value directly if not a binding.
|
|
82
|
+
* Useful for reading values that may or may not be bound.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const arr: (string | Binding<string>)[] = [
|
|
87
|
+
* 'static',
|
|
88
|
+
* bind(signal('dynamic'))
|
|
89
|
+
* ]
|
|
90
|
+
*
|
|
91
|
+
* arr.map(unwrap) // → ['static', 'dynamic']
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function unwrap<T>(value: T | Binding<T> | ReadonlyBinding<T>): T;
|
|
95
|
+
//# sourceMappingURL=bind.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../src/primitives/bind.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAMtE;;;GAGG;AACH,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,IAAI,CAAC,CAAA;IACd,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAClB;AAQD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAEnE;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAC9D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AACtE,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AACvD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;AA6BvE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAQ1F;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAKvE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Derived, Effect, DerivedSignal, Equals } from '../core/types.js';
|
|
2
|
+
export interface DerivedOptions<T> {
|
|
3
|
+
equals?: Equals<T>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Create a derived signal (internal)
|
|
7
|
+
* This is the low-level primitive
|
|
8
|
+
*/
|
|
9
|
+
export declare function createDerived<T>(fn: () => T, options?: DerivedOptions<T>): Derived<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Execute a derived's computation function
|
|
12
|
+
* Cleans up old effects and tracks new dependencies
|
|
13
|
+
*/
|
|
14
|
+
export declare function executeDerived<T>(derived: Derived<T>): T;
|
|
15
|
+
/**
|
|
16
|
+
* Update a derived signal's value
|
|
17
|
+
* Only called when the derived is dirty and being read
|
|
18
|
+
*/
|
|
19
|
+
export declare function updateDerived<T>(derived: Derived<T>): void;
|
|
20
|
+
export declare function setDestroyEffectImpl(impl: (effect: Effect) => void): void;
|
|
21
|
+
/**
|
|
22
|
+
* Create a derived signal
|
|
23
|
+
*
|
|
24
|
+
* Derived signals are lazy - they only compute when read.
|
|
25
|
+
* They cache their value and only recompute when dependencies change.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const count = signal(1)
|
|
30
|
+
* const doubled = derived(() => count.value * 2)
|
|
31
|
+
* console.log(doubled.value) // 2
|
|
32
|
+
* count.value = 5
|
|
33
|
+
* console.log(doubled.value) // 10
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function derived<T>(fn: () => T, options?: DerivedOptions<T>): DerivedSignal<T>;
|
|
37
|
+
export declare namespace derived {
|
|
38
|
+
var by: typeof derived;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Disconnect a derived from its dependencies
|
|
42
|
+
* Used when a derived is no longer needed
|
|
43
|
+
*/
|
|
44
|
+
export declare function disconnectDerived(derived: Derived): void;
|
|
45
|
+
//# sourceMappingURL=derived.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derived.d.ts","sourceRoot":"","sources":["../../src/primitives/derived.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAuB9E,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CACnB;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BrF;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAQxD;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAc1D;AAYD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAEzE;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAQrF;yBARe,OAAO;;;AAoBvB;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAKxD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Effect, EffectFn, DisposeFn } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create an effect (internal)
|
|
4
|
+
*
|
|
5
|
+
* @param type - Effect type flags
|
|
6
|
+
* @param fn - Effect function
|
|
7
|
+
* @param sync - Whether to run synchronously
|
|
8
|
+
* @param push - Whether to add to parent's child list
|
|
9
|
+
*/
|
|
10
|
+
export declare function createEffect(type: number, fn: EffectFn | null, sync: boolean, push?: boolean): Effect;
|
|
11
|
+
/**
|
|
12
|
+
* Run an effect and track its dependencies
|
|
13
|
+
*/
|
|
14
|
+
export declare function updateEffect(effect: Effect): void;
|
|
15
|
+
/**
|
|
16
|
+
* Destroy an effect and all its children
|
|
17
|
+
*/
|
|
18
|
+
export declare function destroyEffect(effect: Effect, removeFromParent?: boolean): void;
|
|
19
|
+
/**
|
|
20
|
+
* Create an effect that runs when dependencies change
|
|
21
|
+
*
|
|
22
|
+
* Effects are scheduled asynchronously (microtask).
|
|
23
|
+
* The function can return a cleanup function that runs before the next execution.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const count = signal(0)
|
|
28
|
+
*
|
|
29
|
+
* effect(() => {
|
|
30
|
+
* console.log('Count:', count.value)
|
|
31
|
+
* return () => console.log('Cleanup')
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function effect(fn: EffectFn): DisposeFn;
|
|
36
|
+
export declare namespace effect {
|
|
37
|
+
var pre: (fn: EffectFn) => DisposeFn;
|
|
38
|
+
var root: (fn: () => void) => DisposeFn;
|
|
39
|
+
var tracking: () => boolean;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=effect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/primitives/effect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAa,SAAS,EAAE,MAAM,kBAAkB,CAAA;AA8B9E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,QAAQ,GAAG,IAAI,EACnB,IAAI,EAAE,OAAO,EACb,IAAI,UAAO,GACV,MAAM,CA8BR;AAyBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA4BjD;AASD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,UAAO,GAAG,IAAI,CA0B3E;AA8ED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,SAAS,CAI9C;yBAJe,MAAM;kBAUc,QAAQ,KAAG,SAAS;mBAqBlB,MAAM,IAAI,KAAG,SAAS;wBAUf,OAAO"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Source, WritableSignal, Equals } from '../core/types.js';
|
|
2
|
+
export interface SourceOptions<T> {
|
|
3
|
+
equals?: Equals<T>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Create a source (internal signal)
|
|
7
|
+
* This is the low-level primitive - use signal() for the public API
|
|
8
|
+
*/
|
|
9
|
+
export declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Create a mutable source with safe equality
|
|
12
|
+
* Used for values that may contain NaN or need object reference tracking
|
|
13
|
+
*/
|
|
14
|
+
export declare function mutableSource<T>(initialValue: T): Source<T>;
|
|
15
|
+
export interface SignalOptions<T> {
|
|
16
|
+
equals?: Equals<T>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a writable signal
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const count = signal(0)
|
|
24
|
+
* console.log(count.value) // 0
|
|
25
|
+
* count.value = 1
|
|
26
|
+
* console.log(count.value) // 1
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function signal<T>(initialValue: T, options?: SignalOptions<T>): WritableSignal<T>;
|
|
30
|
+
export declare function setProxyFn(fn: <T extends object>(value: T) => T): void;
|
|
31
|
+
/**
|
|
32
|
+
* Create a deeply reactive state object
|
|
33
|
+
* Unlike signal(), state() returns the proxy directly (no .value needed)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const user = state({ name: 'John', age: 30 })
|
|
38
|
+
* user.name = 'Jane' // No .value needed
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function state<T extends object>(initialValue: T): T;
|
|
42
|
+
/**
|
|
43
|
+
* Create a signal that holds an object reference without deep reactivity
|
|
44
|
+
* Useful for DOM elements, class instances, or large objects where
|
|
45
|
+
* you only want to track reference changes
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const canvas = stateRaw(document.createElement('canvas'))
|
|
50
|
+
* // Only triggers when canvas.value is reassigned, not on canvas mutations
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function stateRaw<T>(initialValue: T): WritableSignal<T>;
|
|
54
|
+
//# sourceMappingURL=signal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/primitives/signal.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAQtE,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAShF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAE3D;AAMD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAWxF;AASD,wBAAgB,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAEtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAK1D;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAE9D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch multiple signal updates into a single reaction cycle
|
|
3
|
+
*
|
|
4
|
+
* Without batching, each signal update triggers effects immediately.
|
|
5
|
+
* With batching, effects only run once after all updates complete.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const a = signal(1)
|
|
10
|
+
* const b = signal(2)
|
|
11
|
+
*
|
|
12
|
+
* effect(() => {
|
|
13
|
+
* console.log(a.value + b.value)
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // Without batch: logs twice (during each update)
|
|
17
|
+
* // With batch: logs once (after both updates)
|
|
18
|
+
* batch(() => {
|
|
19
|
+
* a.value = 10
|
|
20
|
+
* b.value = 20
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function batch<T>(fn: () => T): T;
|
|
25
|
+
/**
|
|
26
|
+
* Read signals without creating dependencies
|
|
27
|
+
*
|
|
28
|
+
* Useful when you need to read a value but don't want
|
|
29
|
+
* the effect to re-run when it changes.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const a = signal(1)
|
|
34
|
+
* const b = signal(2)
|
|
35
|
+
*
|
|
36
|
+
* effect(() => {
|
|
37
|
+
* // This creates a dependency on 'a'
|
|
38
|
+
* console.log(a.value)
|
|
39
|
+
*
|
|
40
|
+
* // This does NOT create a dependency on 'b'
|
|
41
|
+
* untrack(() => {
|
|
42
|
+
* console.log(b.value)
|
|
43
|
+
* })
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* a.value = 10 // Effect re-runs
|
|
47
|
+
* b.value = 20 // Effect does NOT re-run
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function untrack<T>(fn: () => T): T;
|
|
51
|
+
/**
|
|
52
|
+
* Alias for untrack()
|
|
53
|
+
* Some prefer this name as it's more explicit about "peeking" at a value
|
|
54
|
+
*/
|
|
55
|
+
export declare const peek: typeof untrack;
|
|
56
|
+
//# sourceMappingURL=batching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batching.d.ts","sourceRoot":"","sources":["../../src/reactivity/batching.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAavC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAQzC;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,gBAAU,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Equals } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default strict equality function using Object.is
|
|
4
|
+
* This is the default for source() signals
|
|
5
|
+
*/
|
|
6
|
+
export declare const equals: Equals;
|
|
7
|
+
/**
|
|
8
|
+
* Safe not-equal check
|
|
9
|
+
* Handles NaN correctly and considers objects/functions as not equal
|
|
10
|
+
*/
|
|
11
|
+
export declare function safeNotEqual<T>(a: T, b: T): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Safe equality function
|
|
14
|
+
* Used for mutable sources where NaN and objects need special handling
|
|
15
|
+
*/
|
|
16
|
+
export declare const safeEquals: Equals;
|
|
17
|
+
/**
|
|
18
|
+
* Shallow equality for objects/arrays
|
|
19
|
+
* Compares own enumerable properties one level deep
|
|
20
|
+
*/
|
|
21
|
+
export declare const shallowEquals: Equals;
|
|
22
|
+
/**
|
|
23
|
+
* Create a custom equality function
|
|
24
|
+
*/
|
|
25
|
+
export declare function createEquals<T>(fn: (a: T, b: T) => boolean): Equals<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Never equal - always triggers updates
|
|
28
|
+
* Useful for forcing reactivity
|
|
29
|
+
*/
|
|
30
|
+
export declare const neverEquals: Equals;
|
|
31
|
+
/**
|
|
32
|
+
* Always equal - never triggers updates
|
|
33
|
+
* Useful for static values
|
|
34
|
+
*/
|
|
35
|
+
export declare const alwaysEquals: Equals;
|
|
36
|
+
//# sourceMappingURL=equality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equality.d.ts","sourceRoot":"","sources":["../../src/reactivity/equality.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAM9C;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,MAA8D,CAAA;AAMnF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,OAAO,CAQnD;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAkE,CAAA;AAM3F;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAkD3B,CAAA;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAEtE;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAoB,CAAA;AAE9C;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAmB,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Reaction, Effect } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Schedule an effect for execution
|
|
4
|
+
* Walks up the effect tree to find the root and queues it
|
|
5
|
+
*/
|
|
6
|
+
export declare function scheduleEffect(reaction: Reaction): void;
|
|
7
|
+
export declare function setUpdateEffectImpl(impl: (effect: Effect) => void): void;
|
|
8
|
+
/**
|
|
9
|
+
* Flush all queued effects
|
|
10
|
+
*/
|
|
11
|
+
export declare function flushEffects(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Flush pending reactions from a batch
|
|
14
|
+
*/
|
|
15
|
+
export declare function flushPendingReactions(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Synchronously flush all pending updates
|
|
18
|
+
* Runs all effects immediately instead of waiting for microtask
|
|
19
|
+
*/
|
|
20
|
+
export declare function flushSync<T>(fn?: () => T): T | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Wait for the next update cycle
|
|
23
|
+
* Returns a promise that resolves after all pending effects have run
|
|
24
|
+
*/
|
|
25
|
+
export declare function tick(): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=scheduling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../src/reactivity/scheduling.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAkBxD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAmCvD;AAWD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAExE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAYnC;AAwBD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAc5C;AASD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CA6CxD;AAMD;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Source, Reaction, Derived } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read a signal's value and track it as a dependency
|
|
4
|
+
* This is the core of Svelte 5's fine-grained reactivity
|
|
5
|
+
*
|
|
6
|
+
* Key optimizations:
|
|
7
|
+
* 1. Version-based deduplication (rv) prevents duplicate dependencies
|
|
8
|
+
* 2. skippedDeps optimization reuses existing dependency arrays
|
|
9
|
+
*/
|
|
10
|
+
export declare function get<T>(signal: Source<T>): T;
|
|
11
|
+
/**
|
|
12
|
+
* Write a signal's value and trigger dependent reactions
|
|
13
|
+
*/
|
|
14
|
+
export declare function set<T>(signal: Source<T>, value: T): T;
|
|
15
|
+
/**
|
|
16
|
+
* Mark all reactions of a signal with the given status
|
|
17
|
+
* For effects: schedule them for execution
|
|
18
|
+
* For deriveds: cascade MAYBE_DIRTY to their reactions
|
|
19
|
+
*/
|
|
20
|
+
export declare function markReactions(signal: Source, status: number): void;
|
|
21
|
+
/**
|
|
22
|
+
* Set the status flags of a signal (CLEAN, DIRTY, MAYBE_DIRTY)
|
|
23
|
+
*/
|
|
24
|
+
export declare function setSignalStatus(signal: {
|
|
25
|
+
f: number;
|
|
26
|
+
}, status: number): void;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a reaction is dirty and needs to be updated
|
|
29
|
+
*
|
|
30
|
+
* DIRTY: definitely needs update
|
|
31
|
+
* MAYBE_DIRTY: check dependencies to see if any actually changed
|
|
32
|
+
* CLEAN: no update needed
|
|
33
|
+
*/
|
|
34
|
+
export declare function isDirty(reaction: Reaction): boolean;
|
|
35
|
+
export declare function updateDerived(derived: Derived): void;
|
|
36
|
+
export declare function setUpdateDerivedImpl(impl: (derived: Derived) => void): void;
|
|
37
|
+
/**
|
|
38
|
+
* Remove a reaction from its dependencies, starting at the given index
|
|
39
|
+
* Uses swap-and-pop for O(1) removal
|
|
40
|
+
*/
|
|
41
|
+
export declare function removeReactions(reaction: Reaction, start: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Run a reaction function and track its dependencies
|
|
44
|
+
* This is the core algorithm for dynamic dependency tracking
|
|
45
|
+
*/
|
|
46
|
+
export declare function updateReaction(reaction: Reaction): unknown;
|
|
47
|
+
//# sourceMappingURL=tracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking.d.ts","sourceRoot":"","sources":["../../src/reactivity/tracking.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAkCjE;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAmD3C;AAQD;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CA8BrD;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuBlE;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAE3E;AAMD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAiCnD;AAWD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEpD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAE3E;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOvE;AA8BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAmG1D"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rlabs-inc/signals",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Production-grade fine-grained reactivity for TypeScript. A complete standalone mirror of Svelte 5's reactivity system - signals, effects, derived values, deep reactivity, reactive collections, and reactive bindings.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"build": "bun build src/index.ts --outfile dist/index.mjs --target node --format esm && bun build src/index.ts --outfile dist/index.js --target node --format cjs && bun run build:types",
|
|
22
22
|
"build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
23
23
|
"test": "bun test",
|
|
24
|
+
"test:unit": "bun test test/unit",
|
|
25
|
+
"test:integration": "bun test test/integration",
|
|
26
|
+
"test:perf": "bun test test/performance",
|
|
24
27
|
"prepublishOnly": "bun run build"
|
|
25
28
|
},
|
|
26
29
|
"keywords": [
|
|
@@ -34,6 +37,7 @@
|
|
|
34
37
|
"derived",
|
|
35
38
|
"computed",
|
|
36
39
|
"observable",
|
|
40
|
+
"svelte",
|
|
37
41
|
"typescript"
|
|
38
42
|
],
|
|
39
43
|
"author": "RLabs Inc.",
|