@rlabs-inc/signals 0.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 +307 -0
- package/dist/index.d.ts +268 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +707 -0
- package/dist/index.mjs +677 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# @rlabs-inc/signals
|
|
2
|
+
|
|
3
|
+
**Ultra-lightweight fine-grained reactivity for TypeScript**
|
|
4
|
+
|
|
5
|
+
A standalone reactive primitives library inspired by Svelte 5 runes, Solid.js, and Vue reactivity. Zero dependencies. ~700 lines of pure TypeScript.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Fine-grained reactivity** - Only effects that read a signal re-run when it changes
|
|
10
|
+
- **Deep reactivity** - Objects and arrays are automatically deeply reactive
|
|
11
|
+
- **Lazy deriveds** - Computed values only recompute when read
|
|
12
|
+
- **Batching** - Group updates to prevent multiple re-runs
|
|
13
|
+
- **Reactive collections** - ReactiveMap, ReactiveSet, and reactiveArray
|
|
14
|
+
- **Zero dependencies** - Pure TypeScript, works everywhere
|
|
15
|
+
- **Tiny** - ~5KB minified
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun add @rlabs-inc/signals
|
|
21
|
+
# or
|
|
22
|
+
npm install @rlabs-inc/signals
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { signal, effect, derived, state } from '@rlabs-inc/signals'
|
|
29
|
+
|
|
30
|
+
// Simple signal
|
|
31
|
+
const count = signal(0)
|
|
32
|
+
|
|
33
|
+
// Effect runs when dependencies change
|
|
34
|
+
effect(() => {
|
|
35
|
+
console.log('Count:', count.value)
|
|
36
|
+
})
|
|
37
|
+
// Logs: "Count: 0"
|
|
38
|
+
|
|
39
|
+
count.value = 1
|
|
40
|
+
// Logs: "Count: 1"
|
|
41
|
+
|
|
42
|
+
// Derived values
|
|
43
|
+
const doubled = derived(() => count.value * 2)
|
|
44
|
+
console.log(doubled.value) // 2
|
|
45
|
+
|
|
46
|
+
// Deep reactivity with state()
|
|
47
|
+
const user = state({
|
|
48
|
+
name: 'John',
|
|
49
|
+
address: {
|
|
50
|
+
city: 'NYC'
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
effect(() => {
|
|
55
|
+
console.log('City:', user.address.city)
|
|
56
|
+
})
|
|
57
|
+
// Logs: "City: NYC"
|
|
58
|
+
|
|
59
|
+
user.address.city = 'LA'
|
|
60
|
+
// Logs: "City: LA"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API Reference
|
|
64
|
+
|
|
65
|
+
### signal(initial, options?)
|
|
66
|
+
|
|
67
|
+
Create a reactive signal that holds a value.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const count = signal(0)
|
|
71
|
+
console.log(count.value) // 0
|
|
72
|
+
|
|
73
|
+
count.value = 5
|
|
74
|
+
console.log(count.value) // 5
|
|
75
|
+
|
|
76
|
+
// With custom equality
|
|
77
|
+
const obj = signal({ x: 1 }, {
|
|
78
|
+
equals: (a, b) => a.x === b.x
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### effect(fn)
|
|
83
|
+
|
|
84
|
+
Create a reactive effect that re-runs when dependencies change.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const name = signal('John')
|
|
88
|
+
|
|
89
|
+
const dispose = effect(() => {
|
|
90
|
+
console.log('Hello,', name.value)
|
|
91
|
+
|
|
92
|
+
// Optional cleanup function
|
|
93
|
+
return () => {
|
|
94
|
+
console.log('Cleaning up...')
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
name.value = 'Jane' // Effect re-runs
|
|
99
|
+
|
|
100
|
+
dispose() // Stop the effect
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### derived(fn, options?)
|
|
104
|
+
|
|
105
|
+
Create a computed/derived value that updates automatically.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const count = signal(5)
|
|
109
|
+
const doubled = derived(() => count.value * 2)
|
|
110
|
+
|
|
111
|
+
console.log(doubled.value) // 10
|
|
112
|
+
|
|
113
|
+
count.value = 10
|
|
114
|
+
console.log(doubled.value) // 20
|
|
115
|
+
|
|
116
|
+
// Alias: derived.by() (Svelte compatibility)
|
|
117
|
+
const tripled = derived.by(() => count.value * 3)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### state(initial)
|
|
121
|
+
|
|
122
|
+
Create a deeply reactive state object. All nested properties are automatically reactive.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
const app = state({
|
|
126
|
+
user: {
|
|
127
|
+
name: 'John',
|
|
128
|
+
preferences: {
|
|
129
|
+
theme: 'dark'
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
items: [1, 2, 3]
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
effect(() => {
|
|
136
|
+
console.log(app.user.preferences.theme)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
app.user.preferences.theme = 'light' // Triggers effect
|
|
140
|
+
app.items.push(4) // Arrays are reactive too
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### batch(fn)
|
|
144
|
+
|
|
145
|
+
Batch multiple updates into a single reaction cycle.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const a = signal(1)
|
|
149
|
+
const b = signal(2)
|
|
150
|
+
|
|
151
|
+
effect(() => {
|
|
152
|
+
console.log('Sum:', a.value + b.value)
|
|
153
|
+
})
|
|
154
|
+
// Logs: "Sum: 3"
|
|
155
|
+
|
|
156
|
+
batch(() => {
|
|
157
|
+
a.value = 10
|
|
158
|
+
b.value = 20
|
|
159
|
+
})
|
|
160
|
+
// Logs: "Sum: 30" (only once, not twice)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### untrack(fn)
|
|
164
|
+
|
|
165
|
+
Read signals without creating dependencies.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const a = signal(1)
|
|
169
|
+
const b = signal(2)
|
|
170
|
+
|
|
171
|
+
effect(() => {
|
|
172
|
+
console.log('a:', a.value) // Creates dependency
|
|
173
|
+
untrack(() => {
|
|
174
|
+
console.log('b:', b.value) // Does NOT create dependency
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
b.value = 100 // Effect does NOT re-run
|
|
179
|
+
a.value = 100 // Effect re-runs
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### watch(source, callback, options?)
|
|
183
|
+
|
|
184
|
+
Watch a signal and call callback when it changes.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const count = signal(0)
|
|
188
|
+
|
|
189
|
+
const dispose = watch(
|
|
190
|
+
() => count.value,
|
|
191
|
+
(newValue, oldValue) => {
|
|
192
|
+
console.log(`Changed from ${oldValue} to ${newValue}`)
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
count.value = 1 // Logs: "Changed from 0 to 1"
|
|
197
|
+
|
|
198
|
+
// With immediate option
|
|
199
|
+
watch(
|
|
200
|
+
() => count.value,
|
|
201
|
+
(value) => console.log('Value:', value),
|
|
202
|
+
{ immediate: true }
|
|
203
|
+
)
|
|
204
|
+
// Logs immediately: "Value: 1"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### ReactiveMap
|
|
208
|
+
|
|
209
|
+
A reactive Map that triggers updates on modifications.
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const map = new ReactiveMap<string, number>()
|
|
213
|
+
|
|
214
|
+
effect(() => {
|
|
215
|
+
console.log('Value:', map.get('key'))
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
map.set('key', 42) // Triggers effect
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### ReactiveSet
|
|
222
|
+
|
|
223
|
+
A reactive Set that triggers updates on modifications.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const set = new ReactiveSet<string>()
|
|
227
|
+
|
|
228
|
+
effect(() => {
|
|
229
|
+
console.log('Has item:', set.has('item'))
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
set.add('item') // Triggers effect
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### reactiveArray(initial?)
|
|
236
|
+
|
|
237
|
+
Create a reactive array with fine-grained reactivity.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
const items = reactiveArray([1, 2, 3])
|
|
241
|
+
|
|
242
|
+
effect(() => {
|
|
243
|
+
console.log('First:', items[0])
|
|
244
|
+
console.log('Length:', items.length)
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
items[0] = 10 // Triggers effect
|
|
248
|
+
items.push(4) // Triggers effect
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Utilities
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Create read-only view
|
|
255
|
+
const count = signal(0)
|
|
256
|
+
const ro = readonly(count)
|
|
257
|
+
// ro.value = 5 // TypeScript error
|
|
258
|
+
|
|
259
|
+
// Read without tracking (alias for untrack)
|
|
260
|
+
const value = peek(() => count.value)
|
|
261
|
+
|
|
262
|
+
// Check if value is reactive
|
|
263
|
+
isReactive(someObject)
|
|
264
|
+
|
|
265
|
+
// Get raw object from reactive proxy
|
|
266
|
+
const raw = toRaw(reactiveObject)
|
|
267
|
+
|
|
268
|
+
// Create effect scope
|
|
269
|
+
const scope = effectScope()
|
|
270
|
+
scope.run(() => {
|
|
271
|
+
effect(() => { /* ... */ })
|
|
272
|
+
effect(() => { /* ... */ })
|
|
273
|
+
})
|
|
274
|
+
scope.stop() // Disposes all effects
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Comparison with Svelte 5
|
|
278
|
+
|
|
279
|
+
| Svelte 5 | @rlabs-inc/signals |
|
|
280
|
+
|----------|-------------------|
|
|
281
|
+
| `$state(value)` | `signal(value)` or `state(obj)` |
|
|
282
|
+
| `$derived(expr)` | `derived(() => expr)` |
|
|
283
|
+
| `$derived.by(fn)` | `derived.by(fn)` or `derived(fn)` |
|
|
284
|
+
| `$effect(fn)` | `effect(fn)` |
|
|
285
|
+
| `SvelteMap` | `ReactiveMap` |
|
|
286
|
+
| `SvelteSet` | `ReactiveSet` |
|
|
287
|
+
|
|
288
|
+
**Key differences:**
|
|
289
|
+
- No compiler needed - works with plain TypeScript
|
|
290
|
+
- Use `.value` to read/write signals (like Vue/Solid)
|
|
291
|
+
- No Happy DOM or browser environment required
|
|
292
|
+
|
|
293
|
+
## Why?
|
|
294
|
+
|
|
295
|
+
We built this because:
|
|
296
|
+
1. We love Svelte 5's reactivity model
|
|
297
|
+
2. We wanted to use it outside Svelte components
|
|
298
|
+
3. We didn't want the overhead of Happy DOM for server-side usage
|
|
299
|
+
4. We needed a lightweight solution for libraries like [FatherStateDB](https://github.com/rlabs-inc/fatherstatedb)
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
MIT
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
Built with ❤️ by RLabs Inc.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/** Cleanup function returned by effects */
|
|
2
|
+
export type CleanupFn = () => void;
|
|
3
|
+
/** Effect function that may return a cleanup */
|
|
4
|
+
export type EffectFn = () => void | CleanupFn;
|
|
5
|
+
/** Equality function for comparing values */
|
|
6
|
+
export type EqualityFn<T> = (a: T, b: T) => boolean;
|
|
7
|
+
/** A reactive signal that holds a value */
|
|
8
|
+
export interface Signal<T> {
|
|
9
|
+
readonly value: T;
|
|
10
|
+
}
|
|
11
|
+
/** A writable reactive signal */
|
|
12
|
+
export interface WritableSignal<T> extends Signal<T> {
|
|
13
|
+
value: T;
|
|
14
|
+
}
|
|
15
|
+
/** A derived/computed signal (read-only) */
|
|
16
|
+
export interface Derived<T> extends Signal<T> {
|
|
17
|
+
readonly value: T;
|
|
18
|
+
}
|
|
19
|
+
/** Options for creating a signal */
|
|
20
|
+
export interface SignalOptions<T> {
|
|
21
|
+
equals?: EqualityFn<T>;
|
|
22
|
+
}
|
|
23
|
+
/** Default equality check using Object.is */
|
|
24
|
+
export declare const defaultEquals: <T>(a: T, b: T) => boolean;
|
|
25
|
+
/** Shallow equality for objects/arrays */
|
|
26
|
+
export declare const shallowEquals: <T>(a: T, b: T) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Create a reactive signal
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const count = signal(0)
|
|
33
|
+
* console.log(count.value) // 0
|
|
34
|
+
* count.value = 1
|
|
35
|
+
* console.log(count.value) // 1
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function signal<T>(initial: T, options?: SignalOptions<T>): WritableSignal<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Create a reactive effect that re-runs when dependencies change
|
|
41
|
+
*
|
|
42
|
+
* @returns Dispose function to stop the effect
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* const count = signal(0)
|
|
47
|
+
* const dispose = effect(() => {
|
|
48
|
+
* console.log('Count:', count.value)
|
|
49
|
+
* })
|
|
50
|
+
* // Logs: "Count: 0"
|
|
51
|
+
*
|
|
52
|
+
* count.value = 1
|
|
53
|
+
* // Logs: "Count: 1"
|
|
54
|
+
*
|
|
55
|
+
* dispose() // Stop the effect
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function effect(fn: EffectFn): CleanupFn;
|
|
59
|
+
/**
|
|
60
|
+
* Create a derived/computed value that automatically updates
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const count = signal(0)
|
|
65
|
+
* const doubled = derived(() => count.value * 2)
|
|
66
|
+
* console.log(doubled.value) // 0
|
|
67
|
+
*
|
|
68
|
+
* count.value = 5
|
|
69
|
+
* console.log(doubled.value) // 10
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function derived<T>(fn: () => T, options?: SignalOptions<T>): Derived<T>;
|
|
73
|
+
export declare namespace derived {
|
|
74
|
+
var by: typeof derived;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Batch multiple updates into a single reaction cycle
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* const a = signal(1)
|
|
82
|
+
* const b = signal(2)
|
|
83
|
+
*
|
|
84
|
+
* effect(() => console.log(a.value + b.value))
|
|
85
|
+
* // Logs: 3
|
|
86
|
+
*
|
|
87
|
+
* batch(() => {
|
|
88
|
+
* a.value = 10
|
|
89
|
+
* b.value = 20
|
|
90
|
+
* })
|
|
91
|
+
* // Logs: 30 (only once, not twice)
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function batch<T>(fn: () => T): T;
|
|
95
|
+
/**
|
|
96
|
+
* Read signals without creating dependencies
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* const a = signal(1)
|
|
101
|
+
* const b = signal(2)
|
|
102
|
+
*
|
|
103
|
+
* effect(() => {
|
|
104
|
+
* console.log(a.value) // Creates dependency
|
|
105
|
+
* untrack(() => {
|
|
106
|
+
* console.log(b.value) // Does NOT create dependency
|
|
107
|
+
* })
|
|
108
|
+
* })
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function untrack<T>(fn: () => T): T;
|
|
112
|
+
/**
|
|
113
|
+
* Create a deeply reactive state object
|
|
114
|
+
* All nested properties are automatically reactive
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const user = state({
|
|
119
|
+
* name: 'John',
|
|
120
|
+
* address: {
|
|
121
|
+
* city: 'NYC'
|
|
122
|
+
* }
|
|
123
|
+
* })
|
|
124
|
+
*
|
|
125
|
+
* effect(() => {
|
|
126
|
+
* console.log(user.address.city)
|
|
127
|
+
* })
|
|
128
|
+
* // Logs: "NYC"
|
|
129
|
+
*
|
|
130
|
+
* user.address.city = 'LA'
|
|
131
|
+
* // Logs: "LA"
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export declare function state<T extends object>(initial: T): T;
|
|
135
|
+
/**
|
|
136
|
+
* Get the raw (non-reactive) version of a reactive object
|
|
137
|
+
*/
|
|
138
|
+
export declare function toRaw<T>(proxy: T): T;
|
|
139
|
+
/**
|
|
140
|
+
* Check if a value is a reactive proxy
|
|
141
|
+
*/
|
|
142
|
+
export declare function isReactive(value: unknown): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* A reactive Map that triggers updates on modifications
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const map = new ReactiveMap<string, number>()
|
|
149
|
+
*
|
|
150
|
+
* effect(() => {
|
|
151
|
+
* console.log('Size:', map.size)
|
|
152
|
+
* console.log('Has foo:', map.has('foo'))
|
|
153
|
+
* })
|
|
154
|
+
*
|
|
155
|
+
* map.set('foo', 42) // Triggers effect
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare class ReactiveMap<K, V> extends Map<K, V> {
|
|
159
|
+
#private;
|
|
160
|
+
constructor(entries?: Iterable<readonly [K, V]> | null);
|
|
161
|
+
get size(): number;
|
|
162
|
+
has(key: K): boolean;
|
|
163
|
+
get(key: K): V | undefined;
|
|
164
|
+
set(key: K, value: V): this;
|
|
165
|
+
delete(key: K): boolean;
|
|
166
|
+
clear(): void;
|
|
167
|
+
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
|
|
168
|
+
keys(): MapIterator<K>;
|
|
169
|
+
values(): MapIterator<V>;
|
|
170
|
+
entries(): MapIterator<[K, V]>;
|
|
171
|
+
[Symbol.iterator](): MapIterator<[K, V]>;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A reactive Set that triggers updates on modifications
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* const set = new ReactiveSet<string>()
|
|
179
|
+
*
|
|
180
|
+
* effect(() => {
|
|
181
|
+
* console.log('Size:', set.size)
|
|
182
|
+
* console.log('Has foo:', set.has('foo'))
|
|
183
|
+
* })
|
|
184
|
+
*
|
|
185
|
+
* set.add('foo') // Triggers effect
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
export declare class ReactiveSet<T> extends Set<T> {
|
|
189
|
+
#private;
|
|
190
|
+
constructor(values?: Iterable<T> | null);
|
|
191
|
+
get size(): number;
|
|
192
|
+
has(value: T): boolean;
|
|
193
|
+
add(value: T): this;
|
|
194
|
+
delete(value: T): boolean;
|
|
195
|
+
clear(): void;
|
|
196
|
+
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
|
|
197
|
+
keys(): SetIterator<T>;
|
|
198
|
+
values(): SetIterator<T>;
|
|
199
|
+
entries(): SetIterator<[T, T]>;
|
|
200
|
+
[Symbol.iterator](): SetIterator<T>;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Create a reactive array with fine-grained reactivity
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* const items = reactiveArray([1, 2, 3])
|
|
208
|
+
*
|
|
209
|
+
* effect(() => {
|
|
210
|
+
* console.log('Length:', items.length)
|
|
211
|
+
* console.log('First:', items[0])
|
|
212
|
+
* })
|
|
213
|
+
*
|
|
214
|
+
* items.push(4) // Triggers effect
|
|
215
|
+
* items[0] = 10 // Triggers effect
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export declare function reactiveArray<T>(initial?: T[]): T[];
|
|
219
|
+
/**
|
|
220
|
+
* Create an effect scope for grouping and disposing multiple effects
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* const scope = effectScope()
|
|
225
|
+
*
|
|
226
|
+
* scope.run(() => {
|
|
227
|
+
* effect(() => console.log('Effect 1'))
|
|
228
|
+
* effect(() => console.log('Effect 2'))
|
|
229
|
+
* })
|
|
230
|
+
*
|
|
231
|
+
* scope.stop() // Disposes all effects in the scope
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
export declare function effectScope(): {
|
|
235
|
+
run<T>(fn: () => T): T | undefined;
|
|
236
|
+
stop(): void;
|
|
237
|
+
readonly active: boolean;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Watch a signal or derived and call callback when it changes
|
|
241
|
+
* Like effect but only runs the callback, not for initial subscription
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const count = signal(0)
|
|
246
|
+
*
|
|
247
|
+
* watch(
|
|
248
|
+
* () => count.value,
|
|
249
|
+
* (newValue, oldValue) => {
|
|
250
|
+
* console.log(`Changed from ${oldValue} to ${newValue}`)
|
|
251
|
+
* }
|
|
252
|
+
* )
|
|
253
|
+
*
|
|
254
|
+
* count.value = 1 // Logs: "Changed from 0 to 1"
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export declare function watch<T>(source: () => T, callback: (newValue: T, oldValue: T | undefined) => void | CleanupFn, options?: {
|
|
258
|
+
immediate?: boolean;
|
|
259
|
+
}): CleanupFn;
|
|
260
|
+
/**
|
|
261
|
+
* Create a readonly signal from a writable signal
|
|
262
|
+
*/
|
|
263
|
+
export declare function readonly<T>(sig: WritableSignal<T>): Signal<T>;
|
|
264
|
+
/**
|
|
265
|
+
* Compute a value once without reactivity
|
|
266
|
+
*/
|
|
267
|
+
export declare function peek<T>(fn: () => T): T;
|
|
268
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|