@vielzeug/stateit 2.0.0 → 3.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/README.md +60 -290
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/stateit.cjs +1 -1
- package/dist/stateit.cjs.map +1 -1
- package/dist/stateit.d.ts +68 -0
- package/dist/stateit.d.ts.map +1 -0
- package/dist/stateit.js +294 -228
- package/dist/stateit.js.map +1 -1
- package/package.json +6 -5
- package/dist/batch.cjs +0 -2
- package/dist/batch.cjs.map +0 -1
- package/dist/batch.d.ts +0 -5
- package/dist/batch.d.ts.map +0 -1
- package/dist/batch.js +0 -28
- package/dist/batch.js.map +0 -1
- package/dist/computed.cjs +0 -2
- package/dist/computed.cjs.map +0 -1
- package/dist/computed.d.ts +0 -58
- package/dist/computed.d.ts.map +0 -1
- package/dist/computed.js +0 -65
- package/dist/computed.js.map +0 -1
- package/dist/effect.cjs +0 -2
- package/dist/effect.cjs.map +0 -1
- package/dist/effect.d.ts +0 -31
- package/dist/effect.d.ts.map +0 -1
- package/dist/effect.js +0 -53
- package/dist/effect.js.map +0 -1
- package/dist/runtime.cjs +0 -2
- package/dist/runtime.cjs.map +0 -1
- package/dist/runtime.d.ts +0 -40
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js +0 -47
- package/dist/runtime.js.map +0 -1
- package/dist/signal.cjs +0 -2
- package/dist/signal.cjs.map +0 -1
- package/dist/signal.d.ts +0 -26
- package/dist/signal.d.ts.map +0 -1
- package/dist/signal.js +0 -40
- package/dist/signal.js.map +0 -1
- package/dist/store.cjs +0 -2
- package/dist/store.cjs.map +0 -1
- package/dist/store.d.ts +0 -32
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -51
- package/dist/store.js.map +0 -1
- package/dist/types.cjs +0 -2
- package/dist/types.cjs.map +0 -1
- package/dist/types.d.ts +0 -39
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/watch.cjs +0 -2
- package/dist/watch.cjs.map +0 -1
- package/dist/watch.d.ts +0 -36
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js +0 -32
- package/dist/watch.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,337 +1,107 @@
|
|
|
1
1
|
# @vielzeug/stateit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@vielzeug/stateit) [](https://opensource.org/licenses/MIT)
|
|
6
|
-
|
|
7
|
-
**Stateit** is a tiny, zero-dependency reactive library with two complementary primitives:
|
|
8
|
-
|
|
9
|
-
- **Signals** — fine-grained reactive atoms with `signal()`, `computed()`, `effect()`, `watch()`, `batch()`, and more
|
|
10
|
-
- **Stores** — typed reactive object containers with partial patching, updater functions, selectors, and freeze
|
|
11
|
-
|
|
12
|
-
A `Store<T>` extends `Signal<T>`, so every signal primitive — `effect`, `watch`, `computed`, `batch` — works seamlessly on stores.
|
|
3
|
+
Tiny reactive state with direct singleton primitives.
|
|
13
4
|
|
|
14
5
|
## Installation
|
|
15
6
|
|
|
16
7
|
```sh
|
|
17
8
|
pnpm add @vielzeug/stateit
|
|
18
|
-
# npm install @vielzeug/stateit
|
|
19
|
-
# yarn add @vielzeug/stateit
|
|
20
9
|
```
|
|
21
10
|
|
|
22
|
-
##
|
|
11
|
+
## Usage
|
|
23
12
|
|
|
24
|
-
|
|
13
|
+
Stateit exports singleton primitives directly.
|
|
25
14
|
|
|
26
|
-
```
|
|
27
|
-
import {
|
|
15
|
+
```ts
|
|
16
|
+
import { batch, computed, effect, signal } from '@vielzeug/stateit';
|
|
28
17
|
|
|
29
18
|
const count = signal(0);
|
|
30
19
|
const doubled = computed(() => count.value * 2);
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
console.log(`count=${count.value}, doubled=${doubled.value}`);
|
|
21
|
+
const stop = effect(() => {
|
|
22
|
+
console.log(count.value, doubled.value);
|
|
35
23
|
});
|
|
36
|
-
// → count=0, doubled=0
|
|
37
24
|
|
|
38
|
-
count.value = 3;
|
|
39
|
-
// → count=3, doubled=6
|
|
40
|
-
|
|
41
|
-
// Update via function — shorthand for count.value = count.value + n
|
|
42
|
-
count.update((n) => n + 1);
|
|
43
|
-
// → count=4, doubled=8
|
|
44
|
-
|
|
45
|
-
// Watch explicitly (does not fire immediately by default)
|
|
46
|
-
const stopWatch = watch(count, (next, prev) => console.log(prev, '→', next));
|
|
47
|
-
count.value = 5; // → 4 → 5
|
|
48
|
-
|
|
49
|
-
// Batch coalesces notifications into one flush
|
|
50
25
|
batch(() => {
|
|
51
|
-
count.value =
|
|
52
|
-
count.value =
|
|
26
|
+
count.value = 1;
|
|
27
|
+
count.value = 2;
|
|
53
28
|
});
|
|
54
|
-
// One notification: → 5 → 20
|
|
55
29
|
|
|
56
|
-
|
|
30
|
+
stop();
|
|
57
31
|
doubled.dispose();
|
|
58
|
-
stopWatch.dispose();
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Stores
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
import { store, watch, batch } from '@vielzeug/stateit';
|
|
65
|
-
|
|
66
|
-
const counter = store({ count: 0, user: null as User | null });
|
|
67
|
-
|
|
68
|
-
// Read
|
|
69
|
-
console.log(counter.value); // { count: 0, user: null }
|
|
70
|
-
|
|
71
|
-
// Partial patch
|
|
72
|
-
counter.patch({ count: 1 });
|
|
73
|
-
|
|
74
|
-
// Updater function
|
|
75
|
-
counter.update((s) => ({ ...s, count: s.count + 1 }));
|
|
76
|
-
|
|
77
|
-
// Watch a slice — compose store.select() with watch()
|
|
78
|
-
const countSignal = counter.select((s) => s.count);
|
|
79
|
-
const stopWatch = watch(countSignal, (count, prev) => {
|
|
80
|
-
console.log('count:', prev, '→', count);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Batch updates into one notification
|
|
84
|
-
batch(() => {
|
|
85
|
-
counter.patch({ count: 10 });
|
|
86
|
-
counter.patch({ user: currentUser });
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Reset to initial state
|
|
90
|
-
counter.reset();
|
|
91
|
-
|
|
92
|
-
stopWatch.dispose();
|
|
93
|
-
counter.freeze();
|
|
94
32
|
```
|
|
95
33
|
|
|
96
|
-
##
|
|
97
|
-
|
|
98
|
-
- ✅ **Signals** — reactive atoms with `.value` getter/setter, `.update(fn)`, and `.peek()` for untracked reads
|
|
99
|
-
- ✅ **Computed** — lazy derived signals; call `.dispose()` to stop tracking dependencies
|
|
100
|
-
- ✅ **Effects** — run immediately and re-run when dependencies change; support cleanup returns; return a `Subscription`
|
|
101
|
-
- ✅ **Watch** — explicit subscriptions with `{ immediate?, once?, equals? }` options; returns a `Subscription`
|
|
102
|
-
- ✅ **Batch** — coalesce multiple writes into a single downstream notification
|
|
103
|
-
- ✅ **Untrack** — read signals without registering reactive dependencies
|
|
104
|
-
- ✅ **derived** — multi-source computed from an array of signals
|
|
105
|
-
- ✅ **nextValue** — `Promise` that resolves on the next matching signal emission
|
|
106
|
-
- ✅ **Custom equality** — `signal/computed/watch/store` all accept a custom `equals` function
|
|
107
|
-
- ✅ **Stores** — object state with `patch(partial)`, `update(fn)`, `reset()`, `select()`, and `freeze()`
|
|
108
|
-
- ✅ **Writable computed** — bidirectional computed with `writable(get, set)`
|
|
109
|
-
- ✅ **Symbol.dispose** — all dispose handles support `using` declarations (TC39 explicit resource management)
|
|
110
|
-
- ✅ **Type guards** — `isSignal(v)` and `isStore(v)`
|
|
111
|
-
- ✅ **Zero dependencies** — no supply-chain risk, minimal bundle size
|
|
112
|
-
- ✅ **Framework agnostic** — works in React, Vue, Svelte, or plain TypeScript
|
|
113
|
-
|
|
114
|
-
## Usage
|
|
34
|
+
## Store As Small Recipe
|
|
115
35
|
|
|
116
|
-
|
|
36
|
+
`store()` is a thin object helper over `signal()` with immutable-style updates. Stores expose the readable signal contract (`value`, `peek`, `subscribe`) plus object-focused mutation helpers.
|
|
117
37
|
|
|
118
|
-
```
|
|
119
|
-
import {
|
|
38
|
+
```ts
|
|
39
|
+
import { store } from '@vielzeug/stateit';
|
|
120
40
|
|
|
121
|
-
const
|
|
122
|
-
count.value = 5;
|
|
123
|
-
count.peek(); // read without tracking
|
|
124
|
-
count.update((n) => n + 1); // derive next value in place
|
|
41
|
+
const user = store({ profile: { name: 'Ada' }, count: 0 });
|
|
125
42
|
|
|
126
|
-
|
|
127
|
-
|
|
43
|
+
user.patch({ count: 1 });
|
|
44
|
+
user.update((state) => ({ ...state, count: state.count + 1 }));
|
|
45
|
+
user.reset();
|
|
128
46
|
```
|
|
129
47
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import { signal, computed } from '@vielzeug/stateit';
|
|
48
|
+
## Watching Derived Values
|
|
134
49
|
|
|
135
|
-
|
|
136
|
-
const last = signal('Lovelace');
|
|
137
|
-
const full = computed(() => `${first.value} ${last.value}`);
|
|
50
|
+
Use `watch` with a getter function to watch any derived value directly:
|
|
138
51
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
first.value = 'Grace';
|
|
142
|
-
full.stale; // true — deps changed, not yet re-read
|
|
143
|
-
|
|
144
|
-
// Dispose (stop tracking dependencies)
|
|
145
|
-
full.dispose();
|
|
146
|
-
// or: using full = computed(...) — TC39 using declaration
|
|
147
|
-
```
|
|
52
|
+
```ts
|
|
53
|
+
import { store, watch } from '@vielzeug/stateit';
|
|
148
54
|
|
|
149
|
-
|
|
55
|
+
const cart = store({ count: 0, label: 'x' });
|
|
150
56
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const name = signal('Ada');
|
|
155
|
-
|
|
156
|
-
const sub = effect(() => {
|
|
157
|
-
console.log('Hello,', name.value);
|
|
158
|
-
return () => console.log('cleanup'); // optional teardown
|
|
57
|
+
const stop = watch(() => cart.value.count, (next, prev) => {
|
|
58
|
+
console.log(prev, '->', next);
|
|
159
59
|
});
|
|
160
60
|
|
|
161
|
-
|
|
162
|
-
sub.dispose(); // logs 'cleanup', effect is removed
|
|
61
|
+
stop();
|
|
163
62
|
```
|
|
164
63
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
import { signal, store, watch } from '@vielzeug/stateit';
|
|
169
|
-
|
|
170
|
-
const count = signal(0);
|
|
64
|
+
## Interop Helpers
|
|
171
65
|
|
|
172
|
-
|
|
173
|
-
const sub = watch(count, (next, prev) => console.log(prev, '→', next));
|
|
174
|
-
|
|
175
|
-
// Slice watch — compose with store.select()
|
|
176
|
-
const user = store({ name: 'Ada', age: 30 });
|
|
177
|
-
const nameSig = user.select((s) => s.name);
|
|
178
|
-
watch(nameSig, (name) => console.log('name:', name));
|
|
179
|
-
|
|
180
|
-
// Options
|
|
181
|
-
watch(count, (v) => console.log(v), { immediate: true, once: true });
|
|
182
|
-
|
|
183
|
-
sub.dispose();
|
|
184
|
-
```
|
|
66
|
+
Stateit stays framework-agnostic, but the core exports are designed to plug directly into common reactive contracts.
|
|
185
67
|
|
|
186
|
-
|
|
68
|
+
```ts
|
|
69
|
+
import { computed, readonly, signal, toObservable, toStore } from '@vielzeug/stateit';
|
|
187
70
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const cart = store({ items: [] as string[], total: 0 });
|
|
192
|
-
|
|
193
|
-
// Partial patch
|
|
194
|
-
cart.patch({ total: 42 });
|
|
195
|
-
|
|
196
|
-
// Updater function
|
|
197
|
-
cart.update((s) => ({ ...s, items: [...s.items, 'apple'] }));
|
|
198
|
-
|
|
199
|
-
// Derived slice
|
|
200
|
-
const totalSignal = cart.select((s) => s.total);
|
|
201
|
-
|
|
202
|
-
// Watch slice
|
|
203
|
-
watch(totalSignal, (total) => console.log('total:', total));
|
|
204
|
-
|
|
205
|
-
// Batch
|
|
206
|
-
batch(() => {
|
|
207
|
-
cart.patch({ total: 0 });
|
|
208
|
-
cart.update((s) => ({ ...s, items: [] }));
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
cart.reset();
|
|
212
|
-
cart.freeze();
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Writable Computed
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
import { signal, writable } from '@vielzeug/stateit';
|
|
219
|
-
|
|
220
|
-
const celsius = signal(0);
|
|
221
|
-
const fahrenheit = writable(
|
|
222
|
-
() => (celsius.value * 9) / 5 + 32,
|
|
223
|
-
(f) => {
|
|
224
|
-
celsius.value = ((f - 32) * 5) / 9;
|
|
225
|
-
},
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
fahrenheit.value = 212;
|
|
229
|
-
console.log(celsius.value); // 100
|
|
230
|
-
|
|
231
|
-
fahrenheit.update((f) => f + 10); // increment via fn
|
|
232
|
-
fahrenheit.dispose();
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### `nextValue` — Async Watch
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
import { signal, nextValue } from '@vielzeug/stateit';
|
|
239
|
-
|
|
240
|
-
const status = signal<'idle' | 'loading' | 'done'>('idle');
|
|
241
|
-
|
|
242
|
-
// Wait for the next change (any value)
|
|
243
|
-
const next = await nextValue(status);
|
|
244
|
-
|
|
245
|
-
// Wait for a specific condition
|
|
246
|
-
const done = await nextValue(status, (v) => v === 'done');
|
|
71
|
+
const count = signal(0);
|
|
72
|
+
const doubled = computed(() => count.value * 2);
|
|
247
73
|
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
controller.abort(new Error('cancelled'));
|
|
74
|
+
const publicCount = readonly(count);
|
|
75
|
+
const svelteStore = toStore(doubled);
|
|
76
|
+
const observable = toObservable(publicCount);
|
|
252
77
|
```
|
|
253
78
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
import { signal, computed } from '@vielzeug/stateit';
|
|
79
|
+
## Strict Runtime Rules
|
|
258
80
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// Computed suppresses downstream when result is structurally unchanged
|
|
263
|
-
const sorted = computed(() => [...tags.value].sort(), { equals: (a, b) => a.join() === b.join() });
|
|
264
|
-
```
|
|
81
|
+
- `onCleanup()` throws when called outside an active effect.
|
|
82
|
+
- Reading a disposed computed signal throws.
|
|
83
|
+
- Store constructor/patch misuse (non-object values) throws.
|
|
265
84
|
|
|
266
85
|
## API
|
|
267
86
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
| `_resetContextForTesting` | `_resetContextForTesting()` | `void` |
|
|
290
|
-
|
|
291
|
-
### Store Functions
|
|
292
|
-
|
|
293
|
-
| Export | Signature | Returns |
|
|
294
|
-
| ------- | -------------------------- | ---------- |
|
|
295
|
-
| `store` | `store(initial, options?)` | `Store<T>` |
|
|
296
|
-
|
|
297
|
-
### `Store<T>` Methods
|
|
298
|
-
|
|
299
|
-
| Member | Description |
|
|
300
|
-
| ----------------------------- | ----------------------------------------------------------------------- |
|
|
301
|
-
| `.value` | Read the current state (tracked) |
|
|
302
|
-
| `.peek()` | Read the current state (untracked) |
|
|
303
|
-
| `.update(fn)` | Derive next state via `fn(copy) => next` |
|
|
304
|
-
| `.patch(partial)` | Shallow-merge a `Partial<T>` into state |
|
|
305
|
-
| `.reset()` | Restore the original initial state |
|
|
306
|
-
| `.select(selector, options?)` | Lazily derived `ComputedSignal<U>` from a slice; compose with `watch()` |
|
|
307
|
-
| `.frozen` | `true` after `freeze()` has been called |
|
|
308
|
-
| `.freeze()` | Freeze the store; further writes are silently ignored |
|
|
309
|
-
|
|
310
|
-
### Types
|
|
311
|
-
|
|
312
|
-
| Type | Description |
|
|
313
|
-
| -------------------- | ------------------------------------------------------------------------------------ |
|
|
314
|
-
| `Signal<T>` | Readable/writable reactive atom with `.update(fn)` |
|
|
315
|
-
| `ReadonlySignal<T>` | Read-only signal (no setter) |
|
|
316
|
-
| `ComputedSignal<T>` | `ReadonlySignal<T> & Disposable` — has `.stale`, `.dispose()` |
|
|
317
|
-
| `WritableSignal<T>` | `Signal<T> & Disposable` — has `.stale`, `.update(fn)`, `.dispose()` |
|
|
318
|
-
| `Store<T>` | Object store extending `Signal<T>` |
|
|
319
|
-
| `Subscription` | Callable + `.dispose()` + `[Symbol.dispose]` — returned by `effect`/`watch` |
|
|
320
|
-
| `Disposable` | `.dispose()` + `[Symbol.dispose]` — implemented by `ComputedSignal`/`WritableSignal` |
|
|
321
|
-
| `CleanupFn` | `() => void` |
|
|
322
|
-
| `EffectCallback` | `() => CleanupFn \| void` |
|
|
323
|
-
| `EffectOptions` | `{ maxIterations?, onError? }` |
|
|
324
|
-
| `EqualityFn<T>` | `(a: T, b: T) => boolean` |
|
|
325
|
-
| `ReactiveOptions<T>` | `{ equals?: EqualityFn<T> }` |
|
|
326
|
-
| `WatchOptions<T>` | `{ immediate?, once?, equals? }` |
|
|
327
|
-
| `StoreOptions<T>` | `{ equals?: EqualityFn<T> }` |
|
|
328
|
-
|
|
329
|
-
## Documentation
|
|
330
|
-
|
|
331
|
-
Full docs at **[vielzeug.dev/stateit](https://vielzeug.dev/stateit)**
|
|
332
|
-
|
|
333
|
-
| | |
|
|
334
|
-
| ------------------------------------------------- | -------------------------------------- |
|
|
335
|
-
| [Usage Guide](https://vielzeug.dev/stateit/usage) | Concepts, patterns, and best practices |
|
|
336
|
-
| [API Reference](https://vielzeug.dev/stateit/api) | Complete type signatures |
|
|
337
|
-
| [Examples](https://vielzeug.dev/stateit/examples) | Framework integrations and recipes |
|
|
87
|
+
```ts
|
|
88
|
+
type ObservableObserver<T> = { next(value: T): void };
|
|
89
|
+
type ObservableLike<T> = {
|
|
90
|
+
subscribe(observer: ObservableObserver<T> | ((value: T) => void)): { unsubscribe(): void };
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
signal<T>(initial: T, options?: { equals?: (a: T, b: T) => boolean }): Signal<T>;
|
|
94
|
+
computed<T>(compute: () => T, options?: { equals?: (a: T, b: T) => boolean }): ComputedSignal<T>;
|
|
95
|
+
effect(fn: () => void | (() => void)): Subscription;
|
|
96
|
+
watch<T>(source: ReadonlySignal<T>, cb: (value: T, prev: T) => void, options?: WatchOptions<T>): Subscription;
|
|
97
|
+
watch<T>(source: () => T, cb: (value: T, prev: T) => void, options?: WatchOptions<T>): Subscription;
|
|
98
|
+
batch<T>(fn: () => T): T;
|
|
99
|
+
untrack<T>(fn: () => T): T;
|
|
100
|
+
readonly<T>(source: ReadonlySignal<T>): ReadonlySignal<T>;
|
|
101
|
+
toStore<T>(source: ReadonlySignal<T>): { subscribe(run: (value: T) => void): Subscription };
|
|
102
|
+
toObservable<T>(source: ReadonlySignal<T>): ObservableLike<T>;
|
|
103
|
+
onCleanup(fn: () => void): void;
|
|
104
|
+
scope(setup?: () => void): Scope;
|
|
105
|
+
store<T extends object>(initial: T): Store<T>;
|
|
106
|
+
isSignal<T>(value: unknown): value is ReadonlySignal<T>;
|
|
107
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./stateit.cjs`);exports.batch=e.batch,exports.computed=e.computed,exports.effect=e.effect,exports.isSignal=e.isSignal,exports.observableSymbol=e.observableSymbol,exports.onCleanup=e.onCleanup,exports.readonly=e.readonly,exports.scope=e.scope,exports.signal=e.signal,exports.store=e.store,exports.toObservable=e.toObservable,exports.toStore=e.toStore,exports.toSubscription=e.toSubscription,exports.untrack=e.untrack,exports.watch=e.watch;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* Reactive primitives:
|
|
4
|
-
* Signal<T> -- synchronous, fine-grained reactive atom
|
|
5
|
-
* ReadonlySignal<T> -- read-only view of a signal
|
|
6
|
-
* Store<T> -- object-state store with set/freeze/reset/select
|
|
7
|
-
*
|
|
8
|
-
* All primitives interoperate: computed, derived, effect, watch, batch,
|
|
9
|
-
* untrack, onCleanup, toValue, configureStateit work uniformly
|
|
10
|
-
* on Signal<T> and Store<T>.
|
|
11
|
-
*/
|
|
12
|
-
export * from './batch';
|
|
13
|
-
export * from './computed';
|
|
14
|
-
export * from './effect';
|
|
15
|
-
export { _resetContextForTesting, configureStateit } from './runtime';
|
|
16
|
-
export * from './signal';
|
|
17
|
-
export * from './store';
|
|
18
|
-
export * from './types';
|
|
19
|
-
export * from './watch';
|
|
1
|
+
export * from './stateit';
|
|
20
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { _SIGNAL_BRAND as i, _STORE_BRAND as a } from "./types.js";
|
|
4
|
-
import { ComputedNode as o, WritableNode as s, computed as c, derived as l, writable as u } from "./computed.js";
|
|
5
|
-
import { effect as d, onCleanup as f, untrack as p } from "./effect.js";
|
|
6
|
-
import { SignalImpl as m, isSignal as h, peekValue as g, readonly as _, signal as v, toValue as y } from "./signal.js";
|
|
7
|
-
import { isStore as b, shallowEqual as x, store as S } from "./store.js";
|
|
8
|
-
import { nextValue as C, watch as w } from "./watch.js";
|
|
9
|
-
export { o as ComputedNode, m as SignalImpl, s as WritableNode, i as _SIGNAL_BRAND, a as _STORE_BRAND, n as _flushPending, e as _resetContextForTesting, r as batch, c as computed, t as configureStateit, l as derived, d as effect, h as isSignal, b as isStore, C as nextValue, f as onCleanup, g as peekValue, _ as readonly, x as shallowEqual, v as signal, S as store, y as toValue, p as untrack, w as watch, u as writable };
|
|
1
|
+
import { batch as e, computed as t, effect as n, isSignal as r, observableSymbol as i, onCleanup as a, readonly as o, scope as s, signal as c, store as l, toObservable as u, toStore as d, toSubscription as f, untrack as p, watch as m } from "./stateit.js";
|
|
2
|
+
export { e as batch, t as computed, n as effect, r as isSignal, i as observableSymbol, a as onCleanup, o as readonly, s as scope, c as signal, l as store, u as toObservable, d as toStore, f as toSubscription, p as untrack, m as watch };
|
package/dist/stateit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Symbol(`stateit.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=100,t=Symbol(`stateit.is-signal`),n=Symbol.observable??Symbol.for(`observable`),r=n,i=e=>Object.assign(e,{dispose:e,[Symbol.dispose]:e}),a=new WeakMap,o=e=>e instanceof Error?e:Error(String(e)),s=(e,t)=>{if(typeof e!=`object`||!e||Array.isArray(e))throw TypeError(t)},c=(e,t)=>{let n=[];for(let t of e)try{t()}catch(e){n.push(e)}if(n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,`[stateit] ${t}`)},l=(e,t,n)=>{let r=o(e);throw t.length===0?r:AggregateError([r,...t.map(o)],`[stateit] ${n}`,{cause:r})},u=e=>{try{return c(e,`cleanup errors`),[]}catch(e){return e instanceof AggregateError?e.errors:[e]}},d=null,f=null,p=null,m=null,h=(e,t,n,r,i)=>{let a=d,o=f,s=p,c=m;d=e,f=t,p=n,m=r;try{return i()}finally{d=a,f=o,p=s,m=c}},g=0,_=new Set,v=new Set,y=e=>{let t=new Set(e),n=new Map;for(let t of e)n.set(t,0);for(let r of e)for(let e of r.computedSubscribers())t.has(e)&&n.set(e,(n.get(e)??0)+1);let r=[];for(let t of e)(n.get(t)??0)===0&&r.push(t);let i=[];for(;r.length>0;){let e=r.shift();i.push(e);for(let i of e.computedSubscribers()){if(!t.has(i))continue;let e=(n.get(i)??0)-1;n.set(i,e),e===0&&r.push(i)}}if(i.length<e.length)for(let t of e)i.includes(t)||i.push(t);return i},b=e=>{let t=[...e.computedSubscribers()],n=new Set;for(let t of e.subscribers())_.add(t);for(;t.length>0;){let e=t.pop();if(!n.has(e)&&(n.add(e),e.markDirty())){v.add(e);for(let n of e.computedSubscribers())t.push(n)}}},x=()=>{for(;v.size>0;){let e=y([...v]);v.clear();for(let t of e)if(t.hasAnySubscribers()&&t.refreshIfDirty()){for(let e of t.subscribers())_.add(e);for(let e of t.computedSubscribers())e.markDirty()&&v.add(e)}}},S=()=>{let t=0;for(;_.size>0||v.size>0;){if(++t>e)throw Error(`[stateit] infinite flush loop (> ${e} iterations)`);if(v.size>0&&x(),_.size===0)continue;let n=[..._];_.clear(),c(n,`subscriber errors`)}},C=e=>{e.hasAnySubscribers()&&(b(e),g===0&&S())},w=class{computedSubs_=new Set;subscribers_=new Set;track(){if(p){if(f!==null){let e=f;this.computedSubs_.add(e),p.add(()=>this.computedSubs_.delete(e));return}if(d!==null){let e=d;this.subscribers_.add(e),p.add(()=>this.subscribers_.delete(e))}}}notify(){C(this)}hasAnySubscribers(){return this.computedSubs_.size>0||this.subscribers_.size>0}computedSubscribers(){return this.computedSubs_}subscribers(){return this.subscribers_}subscribe(e){return this.subscribers_.add(e),i(()=>{this.subscribers_.delete(e)})}},T=class extends w{value_;equals_;[t]=!0;constructor(e,t){super(),this.value_=e,this.equals_=t??Object.is}get value(){return this.track(),this.value_}peek(){return this.value_}subscribe=e=>super.subscribe(e);update(e){this.value=e(this.value_)}set value(e){this.equals_(this.value_,e)||(this.value_=e,this.notify())}},E=class extends w{hasValue_=!1;value_;dirty_=!0;computing_=!1;disposed_=!1;deps_=new Set;compute_;equals_;[t]=!0;constructor(e,t){super(),this.compute_=e,this.equals_=t??Object.is}markDirty(){return this.disposed_||this.dirty_?!1:(this.dirty_=!0,!0)}refreshIfDirty(){return this.dirty_?this.recompute():!1}recompute(){if(this.computing_)throw Error(`[stateit] computed cycle detected`);for(let e of this.deps_)e();this.deps_.clear(),this.computing_=!0;try{let e=h(null,this,this.deps_,null,this.compute_);return this.dirty_=!1,!this.hasValue_||!this.equals_(this.value_,e)?(this.hasValue_=!0,this.value_=e,!0):!1}catch(e){let t=u(this.deps_);return this.deps_.clear(),l(e,t,`computed failed dependency cleanup errors`)}finally{this.computing_=!1}}get value(){if(this.disposed_)throw Error(`[stateit] Cannot read disposed computed signal`);return this.refreshIfDirty(),this.track(),this.value_}peek(){if(this.disposed_)throw Error(`[stateit] Cannot read disposed computed signal`);return this.refreshIfDirty(),this.value_}subscribe=e=>{if(this.disposed_)throw Error(`[stateit] Cannot subscribe to a disposed computed signal`);return this.refreshIfDirty(),super.subscribe(e)};dispose(){if(!this.disposed_){this.disposed_=!0;for(let e of this.deps_)e();this.deps_.clear()}}[Symbol.dispose](){this.dispose()}},D=(e,t)=>new T(e,t?.equals),O=(e,t)=>{let n=new E(e,t?.equals);return m!==null&&F(()=>n.dispose()),n},k=e=>{g++;let t,n;try{t=e()}catch(e){n=e}if(g--,g===0)try{S()}catch(e){throw n===void 0?o(e):AggregateError([n,e],`[stateit] batch error with flush errors`,{cause:e})}if(n!==void 0)throw o(n);return t},A=t=>{let n,r=new Set,a=!1,o=!1,s=!1,d=()=>{if(!n&&r.size===0)return;let e=n?[n,...r]:[...r];n=void 0,r.clear(),c(e,`effect teardown errors`)},f=()=>{if(!s){if(a){o=!0;return}a=!0;try{let i=0;do{if(++i>e)throw Error(`[stateit] infinite effect loop (> ${e} iterations)`);o=!1,d();let a=[],s;try{s=h(f,null,r,a,t)}catch(e){let t=[...u(r),...u(a)];r.clear(),l(e,t,`effect failure with cleanup errors`)}typeof s==`function`&&a.push(s),n=a.length>0?()=>{c(a,`effect cleanup errors`)}:void 0}while(o&&!s)}finally{a=!1}}};return f(),i(()=>{s||(s=!0,d())})},j=e=>h(null,null,null,null,e),M=e=>{let t=e,n=a.get(t);if(n)return n;let r={peek(){return e.peek()},subscribe(t){return e.subscribe(t)},get value(){return e.value}};return a.set(t,r),r},N=e=>({subscribe(t){return t(e.value),e.subscribe(()=>t(e.value))}}),P=e=>{let t=t=>{let n=typeof t==`function`?{next:t}:t;n.next?.(e.value);let r=e.subscribe(()=>n.next?.(e.value));return{unsubscribe(){r()}}},r={[n](){return r},subscribe:t};return r},F=e=>{if(m===null)throw Error(`[stateit] onCleanup() must be called from within an active effect or scope.`);m.push(e)},I=e=>{let t=[],n=!1,r=e=>{if(n)throw Error(`[stateit] Cannot run inside a disposed scope.`);return h(null,null,null,t,e)},i=()=>{n||(n=!0,c([...t].reverse(),`scope cleanup errors`),t.length=0)},a={dispose:i,run:r,[Symbol.dispose]:i};return e&&r(e),a};function L(e,t,n){let r=typeof e==`function`?e:()=>e.value,i=n?.equals??Object.is,a=!1,o;return n?.immediate&&(o=j(r),a=!0,t(o,o)),A(()=>{let e=r();if(!a){a=!0,o=e;return}if(i(o,e))return;let n=o;o=e,t(e,n)})}var R=e=>{s(e,`[stateit] store() requires a plain object initial state.`);let n=structuredClone(e),r=D(structuredClone(e));return{[t]:!0,patch(e){s(e,`[stateit] store.patch() requires a plain object partial.`);let t=j(()=>r.value);Object.keys(e).some(n=>!Object.is(t[n],e[n]))&&(r.value={...t,...e})},peek(){return r.peek()},reset(){r.value=structuredClone(n)},subscribe(e){return r.subscribe(e)},update(e){r.update(e)},get value(){return r.value}}},z=e=>typeof e==`object`&&!!e&&!!e[t];exports.batch=k,exports.computed=O,exports.effect=A,exports.isSignal=z,exports.observableSymbol=r,exports.onCleanup=F,exports.readonly=M,exports.scope=I,exports.signal=D,exports.store=R,exports.toObservable=P,exports.toStore=N,exports.toSubscription=i,exports.untrack=j,exports.watch=L;
|
|
2
2
|
//# sourceMappingURL=stateit.cjs.map
|