@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.
Files changed (36) hide show
  1. package/README.md +238 -198
  2. package/dist/collections/date.d.ts +67 -0
  3. package/dist/collections/date.d.ts.map +1 -0
  4. package/dist/collections/map.d.ts +37 -0
  5. package/dist/collections/map.d.ts.map +1 -0
  6. package/dist/collections/set.d.ts +36 -0
  7. package/dist/collections/set.d.ts.map +1 -0
  8. package/dist/core/constants.d.ts +47 -0
  9. package/dist/core/constants.d.ts.map +1 -0
  10. package/dist/core/globals.d.ts +45 -0
  11. package/dist/core/globals.d.ts.map +1 -0
  12. package/dist/core/types.d.ts +76 -0
  13. package/dist/core/types.d.ts.map +1 -0
  14. package/dist/deep/proxy.d.ts +19 -0
  15. package/dist/deep/proxy.d.ts.map +1 -0
  16. package/dist/index.d.ts +16 -277
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1268 -607
  19. package/dist/index.mjs +1267 -608
  20. package/dist/primitives/bind.d.ts +95 -0
  21. package/dist/primitives/bind.d.ts.map +1 -0
  22. package/dist/primitives/derived.d.ts +45 -0
  23. package/dist/primitives/derived.d.ts.map +1 -0
  24. package/dist/primitives/effect.d.ts +41 -0
  25. package/dist/primitives/effect.d.ts.map +1 -0
  26. package/dist/primitives/signal.d.ts +54 -0
  27. package/dist/primitives/signal.d.ts.map +1 -0
  28. package/dist/reactivity/batching.d.ts +56 -0
  29. package/dist/reactivity/batching.d.ts.map +1 -0
  30. package/dist/reactivity/equality.d.ts +36 -0
  31. package/dist/reactivity/equality.d.ts.map +1 -0
  32. package/dist/reactivity/scheduling.d.ts +26 -0
  33. package/dist/reactivity/scheduling.d.ts.map +1 -0
  34. package/dist/reactivity/tracking.d.ts +47 -0
  35. package/dist/reactivity/tracking.d.ts.map +1 -0
  36. 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": "0.2.0",
4
- "description": "Ultra-lightweight fine-grained reactivity for TypeScript. Signals, effects, derived values, and reactive collections with deep reactivity support.",
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.",