flint-reactivity 4.0.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 +107 -0
- package/dist/compat.d.ts +120 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +229 -0
- package/dist/compat.js.map +1 -0
- package/dist/debug.d.ts +130 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +257 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/signals.d.ts +163 -0
- package/dist/signals.d.ts.map +1 -0
- package/dist/signals.js +757 -0
- package/dist/signals.js.map +1 -0
- package/dist/types-helpers.d.ts +238 -0
- package/dist/types-helpers.d.ts.map +1 -0
- package/dist/types-helpers.js +4 -0
- package/dist/types-helpers.js.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @flint/reactivity
|
|
2
|
+
|
|
3
|
+
> Fine-grained signals system for Flint — the fastest reactive primitives
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @flint/reactivity
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { state, computed, effect } from '@flint/reactivity'
|
|
15
|
+
|
|
16
|
+
const count = state(0)
|
|
17
|
+
const doubled = computed(() => count() * 2)
|
|
18
|
+
|
|
19
|
+
effect(() => {
|
|
20
|
+
console.log(`Count: ${count()}, Doubled: ${doubled()}`)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
count.set(5) // Logs: Count: 5, Doubled: 10
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## API
|
|
27
|
+
|
|
28
|
+
### `state(initial)`
|
|
29
|
+
|
|
30
|
+
Create a reactive signal.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const count = state(0)
|
|
34
|
+
count() // read: 0
|
|
35
|
+
count.set(5) // write: 5
|
|
36
|
+
count.set(c => c + 1) // write: 6
|
|
37
|
+
count.peek() // read without tracking
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `computed(fn)`
|
|
41
|
+
|
|
42
|
+
Create a derived value (lazy, cached).
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const doubled = computed(() => count() * 2)
|
|
46
|
+
doubled() // recomputes only when count() changes
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `computedSet({ get, set })`
|
|
50
|
+
|
|
51
|
+
Create a writable computed value.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const count = state(0)
|
|
55
|
+
const doubled = computedSet({
|
|
56
|
+
get: () => count() * 2,
|
|
57
|
+
set: (value) => count.set(value / 2)
|
|
58
|
+
})
|
|
59
|
+
doubled() // read: 0
|
|
60
|
+
doubled.set(10) // write: sets count to 5
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `effect(fn)`
|
|
64
|
+
|
|
65
|
+
Run side effects when dependencies change.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
effect(() => {
|
|
69
|
+
console.log(count())
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `batch(fn)`
|
|
74
|
+
|
|
75
|
+
Group multiple updates into one.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
batch(() => {
|
|
79
|
+
count.set(1)
|
|
80
|
+
name.set('hello')
|
|
81
|
+
}) // Only one re-render
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `reactive(obj)`
|
|
85
|
+
|
|
86
|
+
Proxy-based reactivity (like Vue).
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const user = reactive({ name: 'John', age: 30 })
|
|
90
|
+
user.age++ // triggers updates
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `model(config)`
|
|
94
|
+
|
|
95
|
+
State + computed + actions in one object.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const counter = model({
|
|
99
|
+
state: { count: 0 },
|
|
100
|
+
computed: { doubled: (s) => s.count * 2 },
|
|
101
|
+
actions: { increment(s) { s.count++ } }
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
package/dist/compat.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { batch, createRoot } from './signals.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a reactive signal (Solid.js-compatible alias for `state()`).
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // Solid style:
|
|
7
|
+
* const [count, setCount] = createSignal(0)
|
|
8
|
+
* count() // read
|
|
9
|
+
* setCount(1) // set
|
|
10
|
+
* setCount(prev => prev + 1) // update from previous
|
|
11
|
+
*
|
|
12
|
+
* // Flint style (equivalent):
|
|
13
|
+
* const count = state(0)
|
|
14
|
+
* count() // read
|
|
15
|
+
* count.set(1) // set
|
|
16
|
+
*/
|
|
17
|
+
export declare function createSignal<T>(initialValue: T): [() => T, (value: T | ((prev: T) => T)) => void];
|
|
18
|
+
/**
|
|
19
|
+
* Create a side effect (Solid.js-compatible alias for `effect()`).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* createEffect(() => {
|
|
23
|
+
* console.log('Count changed:', count())
|
|
24
|
+
* })
|
|
25
|
+
*/
|
|
26
|
+
export declare function createEffect(fn: () => void): void;
|
|
27
|
+
/**
|
|
28
|
+
* Create a memoized derived value (Solid.js-compatible alias for `computed()`).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const doubled = createMemo(() => count() * 2)
|
|
32
|
+
*/
|
|
33
|
+
export declare function createMemo<T>(fn: () => T): () => T;
|
|
34
|
+
/**
|
|
35
|
+
* Create a reactive store (Solid.js-compatible).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const [store, setStore] = createStore({
|
|
39
|
+
* user: { name: 'John', age: 30 },
|
|
40
|
+
* todos: []
|
|
41
|
+
* })
|
|
42
|
+
*
|
|
43
|
+
* // Read
|
|
44
|
+
* store.user.name // 'John'
|
|
45
|
+
*
|
|
46
|
+
* // Shallow set (replaces property)
|
|
47
|
+
* setStore('user', 'name', 'Jane')
|
|
48
|
+
*
|
|
49
|
+
* // Functional update
|
|
50
|
+
* setStore('todos', todos => [...todos, { text: 'New', done: false }])
|
|
51
|
+
*/
|
|
52
|
+
export declare function createStore<T extends Record<string, any>>(initialValue: T): [T, (path: string, value: any) => void];
|
|
53
|
+
/**
|
|
54
|
+
* Create a reactive root (Solid.js-compatible alias for `createRoot()`).
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* createRoot((dispose) => {
|
|
58
|
+
* effect(() => console.log(count()))
|
|
59
|
+
* // cleanup when disposed
|
|
60
|
+
* return () => cleanup()
|
|
61
|
+
* })
|
|
62
|
+
*/
|
|
63
|
+
export { createRoot };
|
|
64
|
+
/**
|
|
65
|
+
* Batch multiple updates into a single re-render (Solid.js-compatible).
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* batch(() => {
|
|
69
|
+
* setCount(1)
|
|
70
|
+
* setName('John')
|
|
71
|
+
* // Only one re-render happens
|
|
72
|
+
* })
|
|
73
|
+
*/
|
|
74
|
+
export { batch };
|
|
75
|
+
/**
|
|
76
|
+
* Create an async resource (Solid.js-compatible).
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* const [data, { mutate, refetch }] = createResource(
|
|
80
|
+
* () => userId(),
|
|
81
|
+
* async (id) => {
|
|
82
|
+
* const res = await fetch(`/api/users/${id}`)
|
|
83
|
+
* return res.json()
|
|
84
|
+
* }
|
|
85
|
+
* )
|
|
86
|
+
*
|
|
87
|
+
* // In JSX:
|
|
88
|
+
* <Suspense fallback={<Loading />}>
|
|
89
|
+
* <div>{data()?.name}</div>
|
|
90
|
+
* </Suspense>
|
|
91
|
+
*/
|
|
92
|
+
export declare function createResource<T, S = void>(source: (() => S) | S, fetcher: (source: S) => Promise<T>): [
|
|
93
|
+
() => T | undefined,
|
|
94
|
+
{
|
|
95
|
+
mutate: (fn: T | ((prev: T | undefined) => T)) => void;
|
|
96
|
+
refetch: () => void;
|
|
97
|
+
state: () => 'unresolved' | 'pending' | 'ready' | 'error' | 'refreshing';
|
|
98
|
+
error: () => any | undefined;
|
|
99
|
+
}
|
|
100
|
+
];
|
|
101
|
+
/**
|
|
102
|
+
* Create a reactive value from a non-reactive source.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* const mouseX = from(document, 'mousemove', (e) => e.clientX)
|
|
106
|
+
*/
|
|
107
|
+
export declare function from<T>(source: EventTarget | {
|
|
108
|
+
subscribe: (fn: (value: T) => void) => () => void;
|
|
109
|
+
}, eventOrSelector: string | ((event: any) => T)): () => T | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* Create an immutable update helper.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* produce(store, draft => {
|
|
115
|
+
* draft.user.name = 'Jane'
|
|
116
|
+
* draft.todos.push({ text: 'New', done: false })
|
|
117
|
+
* })
|
|
118
|
+
*/
|
|
119
|
+
export declare function produce<T>(store: T, recipe: (draft: T) => void): void;
|
|
120
|
+
//# sourceMappingURL=compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,EACL,UAAU,EAEX,MAAM,cAAc,CAAA;AAIrB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,YAAY,EAAE,CAAC,GACd,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAWlD;AAID;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,IAAI,GACb,IAAI,CAEN;AAID;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,EAAE,EAAE,MAAM,CAAC,GACV,MAAM,CAAC,CAET;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACvD,YAAY,EAAE,CAAC,GACd,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,CAgBzC;AAID;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,CAAA;AAQrB;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,EAAE,CAAA;AAIhB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EACxC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EACrB,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACjC;IACD,MAAM,CAAC,GAAG,SAAS;IACnB;QACE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,KAAK,CAAC,CAAC,KAAK,IAAI,CAAA;QACtD,OAAO,EAAE,MAAM,IAAI,CAAA;QACnB,KAAK,EAAE,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,CAAA;QACxE,KAAK,EAAE,MAAM,GAAG,GAAG,SAAS,CAAA;KAC7B;CACF,CAqDA;AAID;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,WAAW,GAAG;IAAE,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;CAAE,EAC3E,eAAe,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,GAC5C,MAAM,CAAC,GAAG,SAAS,CAgBrB;AAID;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,IAAI,CAKrE"}
|
package/dist/compat.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// Flint Reactivity — Solid/React-compatible Aliases
|
|
2
|
+
// For developers coming from React/Solid.js backgrounds
|
|
3
|
+
import { state, computed, effect, batch, createRoot, reactive, } from './signals.js';
|
|
4
|
+
// ─── createSignal ───────────────────────────────────────────────
|
|
5
|
+
/**
|
|
6
|
+
* Create a reactive signal (Solid.js-compatible alias for `state()`).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Solid style:
|
|
10
|
+
* const [count, setCount] = createSignal(0)
|
|
11
|
+
* count() // read
|
|
12
|
+
* setCount(1) // set
|
|
13
|
+
* setCount(prev => prev + 1) // update from previous
|
|
14
|
+
*
|
|
15
|
+
* // Flint style (equivalent):
|
|
16
|
+
* const count = state(0)
|
|
17
|
+
* count() // read
|
|
18
|
+
* count.set(1) // set
|
|
19
|
+
*/
|
|
20
|
+
export function createSignal(initialValue) {
|
|
21
|
+
const s = state(initialValue);
|
|
22
|
+
const getter = () => s();
|
|
23
|
+
const setter = (value) => {
|
|
24
|
+
if (typeof value === 'function') {
|
|
25
|
+
s.set(value(s()));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
s.set(value);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return [getter, setter];
|
|
32
|
+
}
|
|
33
|
+
// ─── createEffect ───────────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Create a side effect (Solid.js-compatible alias for `effect()`).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* createEffect(() => {
|
|
39
|
+
* console.log('Count changed:', count())
|
|
40
|
+
* })
|
|
41
|
+
*/
|
|
42
|
+
export function createEffect(fn) {
|
|
43
|
+
effect(fn);
|
|
44
|
+
}
|
|
45
|
+
// ─── createMemo ─────────────────────────────────────────────────
|
|
46
|
+
/**
|
|
47
|
+
* Create a memoized derived value (Solid.js-compatible alias for `computed()`).
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const doubled = createMemo(() => count() * 2)
|
|
51
|
+
*/
|
|
52
|
+
export function createMemo(fn) {
|
|
53
|
+
return computed(fn);
|
|
54
|
+
}
|
|
55
|
+
// ─── createStore ────────────────────────────────────────────────
|
|
56
|
+
/**
|
|
57
|
+
* Create a reactive store (Solid.js-compatible).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const [store, setStore] = createStore({
|
|
61
|
+
* user: { name: 'John', age: 30 },
|
|
62
|
+
* todos: []
|
|
63
|
+
* })
|
|
64
|
+
*
|
|
65
|
+
* // Read
|
|
66
|
+
* store.user.name // 'John'
|
|
67
|
+
*
|
|
68
|
+
* // Shallow set (replaces property)
|
|
69
|
+
* setStore('user', 'name', 'Jane')
|
|
70
|
+
*
|
|
71
|
+
* // Functional update
|
|
72
|
+
* setStore('todos', todos => [...todos, { text: 'New', done: false }])
|
|
73
|
+
*/
|
|
74
|
+
export function createStore(initialValue) {
|
|
75
|
+
const store = reactive(initialValue);
|
|
76
|
+
const setStore = (path, value) => {
|
|
77
|
+
const keys = path.split('.');
|
|
78
|
+
let current = store;
|
|
79
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
80
|
+
current = current[keys[i]];
|
|
81
|
+
}
|
|
82
|
+
const lastKey = keys[keys.length - 1];
|
|
83
|
+
if (typeof value === 'function') {
|
|
84
|
+
current[lastKey] = value(current[lastKey]);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
current[lastKey] = value;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
return [store, setStore];
|
|
91
|
+
}
|
|
92
|
+
// ─── createRoot (Solid-compatible) ──────────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Create a reactive root (Solid.js-compatible alias for `createRoot()`).
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* createRoot((dispose) => {
|
|
98
|
+
* effect(() => console.log(count()))
|
|
99
|
+
* // cleanup when disposed
|
|
100
|
+
* return () => cleanup()
|
|
101
|
+
* })
|
|
102
|
+
*/
|
|
103
|
+
export { createRoot };
|
|
104
|
+
// ─── createSelector ─────────────────────────────────────────────
|
|
105
|
+
// Note: createSelector is already exported from signals.ts with the full API
|
|
106
|
+
// (setSelected, getSelected, dispose). We re-export it here for compatibility.
|
|
107
|
+
// ─── batch (Solid-compatible) ───────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* Batch multiple updates into a single re-render (Solid.js-compatible).
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* batch(() => {
|
|
113
|
+
* setCount(1)
|
|
114
|
+
* setName('John')
|
|
115
|
+
* // Only one re-render happens
|
|
116
|
+
* })
|
|
117
|
+
*/
|
|
118
|
+
export { batch };
|
|
119
|
+
// ─── createResource ─────────────────────────────────────────────
|
|
120
|
+
/**
|
|
121
|
+
* Create an async resource (Solid.js-compatible).
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const [data, { mutate, refetch }] = createResource(
|
|
125
|
+
* () => userId(),
|
|
126
|
+
* async (id) => {
|
|
127
|
+
* const res = await fetch(`/api/users/${id}`)
|
|
128
|
+
* return res.json()
|
|
129
|
+
* }
|
|
130
|
+
* )
|
|
131
|
+
*
|
|
132
|
+
* // In JSX:
|
|
133
|
+
* <Suspense fallback={<Loading />}>
|
|
134
|
+
* <div>{data()?.name}</div>
|
|
135
|
+
* </Suspense>
|
|
136
|
+
*/
|
|
137
|
+
export function createResource(source, fetcher) {
|
|
138
|
+
const dataSignal = state(undefined);
|
|
139
|
+
const errorSignal = state(undefined);
|
|
140
|
+
const stateSignal = state('unresolved');
|
|
141
|
+
let fetchCount = 0;
|
|
142
|
+
const refetch = () => {
|
|
143
|
+
fetchCount++;
|
|
144
|
+
const currentFetch = fetchCount;
|
|
145
|
+
const src = typeof source === 'function' ? source() : source;
|
|
146
|
+
stateSignal.set('pending');
|
|
147
|
+
fetcher(src)
|
|
148
|
+
.then((result) => {
|
|
149
|
+
if (currentFetch === fetchCount) {
|
|
150
|
+
dataSignal.set(result);
|
|
151
|
+
stateSignal.set('ready');
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
.catch((err) => {
|
|
155
|
+
if (currentFetch === fetchCount) {
|
|
156
|
+
errorSignal.set(err);
|
|
157
|
+
stateSignal.set('error');
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
// Start fetching immediately if source is available
|
|
162
|
+
if (typeof source === 'function') {
|
|
163
|
+
effect(() => {
|
|
164
|
+
const src = source();
|
|
165
|
+
if (src !== undefined && src !== null) {
|
|
166
|
+
refetch();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
refetch();
|
|
172
|
+
}
|
|
173
|
+
return [
|
|
174
|
+
() => dataSignal(),
|
|
175
|
+
{
|
|
176
|
+
mutate: (fn) => {
|
|
177
|
+
if (typeof fn === 'function') {
|
|
178
|
+
dataSignal.set(fn);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
dataSignal.set(fn);
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
refetch,
|
|
185
|
+
state: () => stateSignal(),
|
|
186
|
+
error: () => errorSignal(),
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
}
|
|
190
|
+
// ─── from (reactive from) ───────────────────────────────────────
|
|
191
|
+
/**
|
|
192
|
+
* Create a reactive value from a non-reactive source.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* const mouseX = from(document, 'mousemove', (e) => e.clientX)
|
|
196
|
+
*/
|
|
197
|
+
export function from(source, eventOrSelector) {
|
|
198
|
+
const signal = state(undefined);
|
|
199
|
+
if ('addEventListener' in source) {
|
|
200
|
+
const eventName = eventOrSelector;
|
|
201
|
+
const selector = typeof eventOrSelector === 'function' ? eventOrSelector : (e) => e;
|
|
202
|
+
source.addEventListener(eventName, (e) => {
|
|
203
|
+
signal.set(selector(e));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
source.subscribe((value) => {
|
|
208
|
+
signal.set(value);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return () => signal();
|
|
212
|
+
}
|
|
213
|
+
// ─── produce (immutable helper) ─────────────────────────────────
|
|
214
|
+
/**
|
|
215
|
+
* Create an immutable update helper.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* produce(store, draft => {
|
|
219
|
+
* draft.user.name = 'Jane'
|
|
220
|
+
* draft.todos.push({ text: 'New', done: false })
|
|
221
|
+
* })
|
|
222
|
+
*/
|
|
223
|
+
export function produce(store, recipe) {
|
|
224
|
+
// Simple immutable update pattern
|
|
225
|
+
if (typeof store === 'object' && store !== null) {
|
|
226
|
+
recipe(store);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
|
package/dist/debug.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { Signal, Computed } from './types.js';
|
|
2
|
+
export interface DebugOptions {
|
|
3
|
+
/** Enable debug mode */
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** Log signal changes */
|
|
6
|
+
logChanges: boolean;
|
|
7
|
+
/** Log computed recalculations */
|
|
8
|
+
logComputed: boolean;
|
|
9
|
+
/** Log effect executions */
|
|
10
|
+
logEffects: boolean;
|
|
11
|
+
/** Log batch operations */
|
|
12
|
+
logBatch: boolean;
|
|
13
|
+
/** Maximum history entries per signal */
|
|
14
|
+
maxHistory: number;
|
|
15
|
+
/** Enable performance tracking */
|
|
16
|
+
trackPerformance: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface SignalDebugInfo {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
value: any;
|
|
22
|
+
previousValue: any;
|
|
23
|
+
changeCount: number;
|
|
24
|
+
lastChange: number;
|
|
25
|
+
history: SignalHistoryEntry[];
|
|
26
|
+
subscribers: string[];
|
|
27
|
+
computedFrom: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface SignalHistoryEntry {
|
|
30
|
+
value: any;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
stackTrace?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ComputedDebugInfo {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
value: any;
|
|
38
|
+
recalculationCount: number;
|
|
39
|
+
lastRecalculation: number;
|
|
40
|
+
dependencies: string[];
|
|
41
|
+
isDirty: boolean;
|
|
42
|
+
computationTime: number;
|
|
43
|
+
}
|
|
44
|
+
export interface EffectDebugInfo {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
executionCount: number;
|
|
48
|
+
lastExecution: number;
|
|
49
|
+
dependencies: string[];
|
|
50
|
+
executionTime: number;
|
|
51
|
+
}
|
|
52
|
+
export declare class DebugManager {
|
|
53
|
+
private options;
|
|
54
|
+
private signalRegistry;
|
|
55
|
+
private computedRegistry;
|
|
56
|
+
private effectRegistry;
|
|
57
|
+
private idCounter;
|
|
58
|
+
private enabled;
|
|
59
|
+
constructor(options?: Partial<DebugOptions>);
|
|
60
|
+
/**
|
|
61
|
+
* Enable debug mode
|
|
62
|
+
*/
|
|
63
|
+
enable(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Disable debug mode
|
|
66
|
+
*/
|
|
67
|
+
disable(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Track a signal
|
|
70
|
+
*/
|
|
71
|
+
trackSignal<T>(name: string, signal: Signal<T>): Signal<T>;
|
|
72
|
+
/**
|
|
73
|
+
* Track a computed value
|
|
74
|
+
*/
|
|
75
|
+
trackComputed<T>(name: string, computed$: Computed<T>): Computed<T>;
|
|
76
|
+
/**
|
|
77
|
+
* Get debug info for a signal
|
|
78
|
+
*/
|
|
79
|
+
getSignalDebugInfo(id: string): SignalDebugInfo | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Get debug info for a computed
|
|
82
|
+
*/
|
|
83
|
+
getComputedDebugInfo(id: string): ComputedDebugInfo | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Get all tracked signals
|
|
86
|
+
*/
|
|
87
|
+
getAllSignals(): SignalDebugInfo[];
|
|
88
|
+
/**
|
|
89
|
+
* Get all tracked computed values
|
|
90
|
+
*/
|
|
91
|
+
getAllComputed(): ComputedDebugInfo[];
|
|
92
|
+
/**
|
|
93
|
+
* Clear all tracking data
|
|
94
|
+
*/
|
|
95
|
+
clear(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Get performance summary
|
|
98
|
+
*/
|
|
99
|
+
getPerformanceSummary(): {
|
|
100
|
+
totalSignals: number;
|
|
101
|
+
totalComputed: number;
|
|
102
|
+
totalEffects: number;
|
|
103
|
+
averageComputationTime: number;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export declare function createDebugManager(options?: Partial<DebugOptions>): DebugManager;
|
|
107
|
+
export declare function getDebugManager(): DebugManager | null;
|
|
108
|
+
export declare function enableDebug(): DebugManager;
|
|
109
|
+
export declare function disableDebug(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Track a signal in debug mode
|
|
112
|
+
*/
|
|
113
|
+
export declare function trackSignal<T>(name: string, signal: Signal<T>): Signal<T>;
|
|
114
|
+
/**
|
|
115
|
+
* Track a computed in debug mode
|
|
116
|
+
*/
|
|
117
|
+
export declare function trackComputed<T>(name: string, computed$: Computed<T>): Computed<T>;
|
|
118
|
+
/**
|
|
119
|
+
* Print signal history
|
|
120
|
+
*/
|
|
121
|
+
export declare function printSignalHistory(signalId: string): void;
|
|
122
|
+
/**
|
|
123
|
+
* Print computed stats
|
|
124
|
+
*/
|
|
125
|
+
export declare function printComputedStats(computedId: string): void;
|
|
126
|
+
/**
|
|
127
|
+
* Print performance summary
|
|
128
|
+
*/
|
|
129
|
+
export declare function printPerformanceSummary(): void;
|
|
130
|
+
//# sourceMappingURL=debug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"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"}
|