lume-js 1.0.0 → 2.0.0-alpha.2
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 +10 -4
- package/package.json +7 -3
- package/src/addons/debug.js +330 -0
- package/src/addons/index.d.ts +98 -4
- package/src/addons/index.js +2 -1
- package/src/addons/repeat.js +75 -59
- package/src/core/bindDom.js +23 -11
- package/src/core/effect.js +91 -51
- package/src/core/state.js +104 -10
- package/src/index.d.ts +143 -2
package/src/index.d.ts
CHANGED
|
@@ -14,6 +14,94 @@ export type Unsubscribe = () => void;
|
|
|
14
14
|
*/
|
|
15
15
|
export type Subscriber<T> = (value: T) => void;
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Plugin interface for extending state behavior
|
|
19
|
+
*
|
|
20
|
+
* All hooks are optional. Hooks execute in the order plugins are registered.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const debugPlugin: Plugin = {
|
|
25
|
+
* name: 'debug',
|
|
26
|
+
* onGet: (key, value) => {
|
|
27
|
+
* console.log(`GET ${key}:`, value);
|
|
28
|
+
* return value; // Return value to pass to next plugin
|
|
29
|
+
* },
|
|
30
|
+
* onSet: (key, newValue, oldValue) => {
|
|
31
|
+
* console.log(`SET ${key}:`, oldValue, '→', newValue);
|
|
32
|
+
* return newValue; // Return value to pass to next plugin
|
|
33
|
+
* }
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* const store = state({ count: 0 }, { plugins: [debugPlugin] });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export interface Plugin {
|
|
40
|
+
/**
|
|
41
|
+
* Plugin name (for debugging)
|
|
42
|
+
*/
|
|
43
|
+
name: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Called when state object is created
|
|
47
|
+
* Runs synchronously before Proxy is returned
|
|
48
|
+
*/
|
|
49
|
+
onInit?(): void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Called when a property is accessed (before value returned)
|
|
53
|
+
* Can transform the value by returning a new value
|
|
54
|
+
*
|
|
55
|
+
* Chain pattern: Each plugin receives the output of the previous plugin
|
|
56
|
+
*
|
|
57
|
+
* @param key - Property key being accessed
|
|
58
|
+
* @param value - Current value (possibly transformed by previous plugins)
|
|
59
|
+
* @returns Transformed value, or undefined to keep current value
|
|
60
|
+
*/
|
|
61
|
+
onGet?(key: string, value: any): any;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Called when a property is updated (before subscribers notified)
|
|
65
|
+
* Can transform or validate the new value
|
|
66
|
+
*
|
|
67
|
+
* Chain pattern: Each plugin receives the output of the previous plugin
|
|
68
|
+
*
|
|
69
|
+
* @param key - Property key being updated
|
|
70
|
+
* @param newValue - New value being set (possibly transformed by previous plugins)
|
|
71
|
+
* @param oldValue - Previous value
|
|
72
|
+
* @returns Transformed value, or undefined to keep current value
|
|
73
|
+
*/
|
|
74
|
+
onSet?(key: string, newValue: any, oldValue: any): any;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Called when a subscriber is added
|
|
78
|
+
* Useful for tracking active subscriptions
|
|
79
|
+
*
|
|
80
|
+
* @param key - Property key being subscribed to
|
|
81
|
+
*/
|
|
82
|
+
onSubscribe?(key: string): void;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Called when subscribers are about to be notified
|
|
86
|
+
* Runs in microtask, before subscribers receive value
|
|
87
|
+
*
|
|
88
|
+
* @param key - Property key that changed
|
|
89
|
+
* @param value - New value being notified
|
|
90
|
+
*/
|
|
91
|
+
onNotify?(key: string, value: any): void;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Options for state creation
|
|
96
|
+
*/
|
|
97
|
+
export interface StateOptions {
|
|
98
|
+
/**
|
|
99
|
+
* Array of plugins to apply to this state object
|
|
100
|
+
* Plugins execute in the order they are registered
|
|
101
|
+
*/
|
|
102
|
+
plugins?: Plugin[];
|
|
103
|
+
}
|
|
104
|
+
|
|
17
105
|
/**
|
|
18
106
|
* Reactive state object with $subscribe method
|
|
19
107
|
*/
|
|
@@ -55,8 +143,30 @@ export type ReactiveState<T extends object> = T & {
|
|
|
55
143
|
* // Cleanup
|
|
56
144
|
* unsub();
|
|
57
145
|
* ```
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* // With plugins
|
|
150
|
+
* const store = state(
|
|
151
|
+
* { count: 0 },
|
|
152
|
+
* {
|
|
153
|
+
* plugins: [
|
|
154
|
+
* {
|
|
155
|
+
* name: 'logger',
|
|
156
|
+
* onGet: (key, value) => {
|
|
157
|
+
* console.log(`GET ${key}:`, value);
|
|
158
|
+
* return value;
|
|
159
|
+
* }
|
|
160
|
+
* }
|
|
161
|
+
* ]
|
|
162
|
+
* }
|
|
163
|
+
* );
|
|
164
|
+
* ```
|
|
58
165
|
*/
|
|
59
|
-
export function state<T extends object>(
|
|
166
|
+
export function state<T extends object>(
|
|
167
|
+
obj: T,
|
|
168
|
+
options?: StateOptions
|
|
169
|
+
): ReactiveState<T>;
|
|
60
170
|
|
|
61
171
|
/**
|
|
62
172
|
* Options for bindDom function
|
|
@@ -108,7 +218,13 @@ export function bindDom(
|
|
|
108
218
|
): Unsubscribe;
|
|
109
219
|
|
|
110
220
|
/**
|
|
111
|
-
*
|
|
221
|
+
* Dependency tuple for explicit effect tracking
|
|
222
|
+
* Format: [store, key1, key2, ...] where store is a ReactiveState and keys are property names
|
|
223
|
+
*/
|
|
224
|
+
export type EffectDependency = [ReactiveState<any>, ...string[]];
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Create an effect with auto-tracking (default mode)
|
|
112
228
|
*
|
|
113
229
|
* The effect runs immediately and re-runs when any accessed state properties change.
|
|
114
230
|
* Only tracks properties that are actually accessed during execution.
|
|
@@ -134,6 +250,31 @@ export function bindDom(
|
|
|
134
250
|
*/
|
|
135
251
|
export function effect(fn: () => void): Unsubscribe;
|
|
136
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Create an effect with explicit dependencies (no magic)
|
|
255
|
+
*
|
|
256
|
+
* The effect runs immediately and re-runs ONLY when specified dependencies change.
|
|
257
|
+
* Does not auto-track any state access. Ideal for side-effects like logging.
|
|
258
|
+
*
|
|
259
|
+
* @param fn - Function to run reactively
|
|
260
|
+
* @param deps - Array of [store, key] tuples specifying exact dependencies
|
|
261
|
+
* @returns Cleanup function to stop the effect
|
|
262
|
+
* @throws {Error} If fn is not a function
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```typescript
|
|
266
|
+
* const store = state({ count: 0 });
|
|
267
|
+
*
|
|
268
|
+
* // Explicit: only re-runs when store.count changes
|
|
269
|
+
* const cleanup = effect(() => {
|
|
270
|
+
* analytics.track('count', store.count);
|
|
271
|
+
* }, [[store, 'count']]);
|
|
272
|
+
*
|
|
273
|
+
* cleanup(); // Stop the effect
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export function effect(fn: () => void, deps: EffectDependency[]): Unsubscribe;
|
|
277
|
+
|
|
137
278
|
/**
|
|
138
279
|
* Check if a value is a Lume reactive proxy produced by state().
|
|
139
280
|
* Returns true only for objects created by state().
|