@tempots/dom 31.6.1 → 32.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 +6 -1
- package/index.cjs +1 -1
- package/index.d.ts +3 -0
- package/index.js +823 -575
- package/package.json +1 -1
- package/renderable/render.d.ts +4 -0
- package/renderable/utils.d.ts +1 -0
- package/renderable/with-scope.d.ts +39 -0
- package/std/disposal-scope.d.ts +97 -0
- package/std/element-position.d.ts +8 -0
- package/std/scope-stack.d.ts +76 -0
- package/std/signal.d.ts +49 -3
- package/std/value.d.ts +8 -0
package/package.json
CHANGED
package/renderable/render.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ import { Value } from '../std/value';
|
|
|
5
5
|
/**
|
|
6
6
|
* Renders the given `renderable` with the provided `ctx` DOM context.
|
|
7
7
|
*
|
|
8
|
+
* Creates a DisposalScope for automatic signal disposal. All signals created
|
|
9
|
+
* during the renderable execution are tracked and disposed when the clear
|
|
10
|
+
* function is called.
|
|
11
|
+
*
|
|
8
12
|
* @param renderable - The renderable node to be rendered.
|
|
9
13
|
* @param ctx - The DOM context to be used for rendering.
|
|
10
14
|
* @returns A function that can be called to clear the rendered node.
|
package/renderable/utils.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare const handleValueOrSignal: <T, R>(value: Value<T>, onSignal: (sig
|
|
|
20
20
|
* - Setting up a signal listener that re-renders on changes
|
|
21
21
|
* - Properly cleaning up the old render before creating a new one
|
|
22
22
|
* - Disposing the signal listener and context on cleanup
|
|
23
|
+
* - Creating a disposal scope for each branch to track signals
|
|
23
24
|
*
|
|
24
25
|
* @param ctx - The parent DOM context
|
|
25
26
|
* @param signal - The signal to watch for changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DisposalScope } from '../std/disposal-scope';
|
|
2
|
+
import { Renderable, TNode } from '../types/domain';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a renderable that provides explicit access to a DisposalScope.
|
|
5
|
+
*
|
|
6
|
+
* This is useful when you need to create signals in async contexts (like setTimeout,
|
|
7
|
+
* fetch callbacks, event handlers) where automatic scope tracking doesn't work.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Using scope in async context
|
|
12
|
+
* WithScope(scope => {
|
|
13
|
+
* setTimeout(() => {
|
|
14
|
+
* const signal = scope.prop(42)
|
|
15
|
+
* // signal will be disposed when component unmounts
|
|
16
|
+
* }, 1000)
|
|
17
|
+
*
|
|
18
|
+
* return html.div('Loading...')
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Using scope with fetch
|
|
25
|
+
* WithScope(scope => {
|
|
26
|
+
* fetch('/api/data').then(response => {
|
|
27
|
+
* const data = scope.prop(response.data)
|
|
28
|
+
* // data will be disposed when component unmounts
|
|
29
|
+
* })
|
|
30
|
+
*
|
|
31
|
+
* return html.div('Fetching...')
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @param fn - Function that receives the scope and returns content to render
|
|
36
|
+
* @returns A renderable that manages the scope lifecycle
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export declare const WithScope: (fn: (scope: DisposalScope) => TNode) => Renderable;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AnySignal, Computed, ListenerOptions, Prop } from './signal';
|
|
2
|
+
import { Value } from './value';
|
|
3
|
+
import { ValueTypes } from '../types/domain';
|
|
4
|
+
/**
|
|
5
|
+
* A DisposalScope tracks signals created during its lifetime and disposes them when the scope ends.
|
|
6
|
+
* This enables automatic signal disposal without manual OnDispose() calls.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export declare class DisposalScope {
|
|
11
|
+
private _signals;
|
|
12
|
+
private _callbacks;
|
|
13
|
+
private _disposed;
|
|
14
|
+
/**
|
|
15
|
+
* Register a signal with this scope for automatic disposal.
|
|
16
|
+
*
|
|
17
|
+
* @param signal - The signal to track
|
|
18
|
+
* @throws Error if the scope has already been disposed
|
|
19
|
+
* @throws Error if the signal has already been disposed
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
track(signal: AnySignal): void;
|
|
23
|
+
/**
|
|
24
|
+
* Register a disposal callback to be called when this scope is disposed.
|
|
25
|
+
* Callbacks are called before signals are disposed.
|
|
26
|
+
* Use this for cleanup that doesn't need the `removeTree` parameter.
|
|
27
|
+
*
|
|
28
|
+
* @param callback - The callback to call on disposal
|
|
29
|
+
* @throws Error if the scope has already been disposed
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
onDispose(callback: () => void): void;
|
|
33
|
+
/**
|
|
34
|
+
* Dispose all signals tracked by this scope.
|
|
35
|
+
* This method is idempotent - calling it multiple times is safe.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
dispose(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Check if this scope has been disposed.
|
|
42
|
+
*
|
|
43
|
+
* @returns true if the scope has been disposed
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
get disposed(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Creates a prop signal and tracks it in this scope.
|
|
49
|
+
* Use this method in async contexts where automatic tracking doesn't work.
|
|
50
|
+
*
|
|
51
|
+
* @param value - The initial value
|
|
52
|
+
* @param equals - Optional equality function
|
|
53
|
+
* @returns A tracked Prop signal
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
prop<T>(value: T, equals?: (a: T, b: T) => boolean): Prop<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a computed signal and tracks it in this scope.
|
|
59
|
+
* Use this method in async contexts where automatic tracking doesn't work.
|
|
60
|
+
*
|
|
61
|
+
* @param fn - The computation function
|
|
62
|
+
* @param dependencies - Array of signals this computed depends on
|
|
63
|
+
* @param equals - Optional equality function
|
|
64
|
+
* @returns A tracked Computed signal
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
computed<T>(fn: () => T, dependencies: Array<AnySignal>, equals?: (a: T, b: T) => boolean): Computed<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Creates an effect and tracks it in this scope.
|
|
70
|
+
* Use this method in async contexts where automatic tracking doesn't work.
|
|
71
|
+
*
|
|
72
|
+
* @param fn - The effect function
|
|
73
|
+
* @param signals - Array of signals to listen to
|
|
74
|
+
* @param options - Optional listener options
|
|
75
|
+
* @returns A clear function (the effect itself is tracked in the scope)
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
effect(fn: () => void, signals: Array<AnySignal>, options?: ListenerOptions): () => void;
|
|
79
|
+
/**
|
|
80
|
+
* Creates a computed signal with curried signature and tracks it in this scope.
|
|
81
|
+
* Use this method in async contexts where automatic tracking doesn't work.
|
|
82
|
+
*
|
|
83
|
+
* @param args - Values or signals to compute from
|
|
84
|
+
* @returns A function that takes the computation function and returns a tracked Computed signal
|
|
85
|
+
* @public
|
|
86
|
+
*/
|
|
87
|
+
computedOf<T extends Value<unknown>[]>(...args: T): <O>(fn: (...args: ValueTypes<T>) => O, equals?: (a: O, b: O) => boolean) => Computed<O>;
|
|
88
|
+
/**
|
|
89
|
+
* Creates an effect with curried signature and tracks it in this scope.
|
|
90
|
+
* Use this method in async contexts where automatic tracking doesn't work.
|
|
91
|
+
*
|
|
92
|
+
* @param args - Values or signals to listen to
|
|
93
|
+
* @returns A function that takes the effect function and returns a clear function
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
effectOf<T extends Value<unknown>[]>(...args: T): (fn: (...args: ValueTypes<T>) => void, options?: ListenerOptions) => (() => void);
|
|
97
|
+
}
|
|
@@ -52,5 +52,13 @@ export declare class ElementPosition {
|
|
|
52
52
|
* @returns `true` if the element is the last element, `false` otherwise.
|
|
53
53
|
*/
|
|
54
54
|
get isLast(): Signal<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Disposes the internal signal created by `isLast`.
|
|
57
|
+
*
|
|
58
|
+
* **Note:** With automatic signal disposal, this method is now a no-op when used within
|
|
59
|
+
* a disposal scope (e.g., inside a renderable). The signal created by `isLast` is
|
|
60
|
+
* automatically tracked and disposed when the scope ends. This method is kept for
|
|
61
|
+
* backward compatibility and for cases where ElementPosition is used outside a scope.
|
|
62
|
+
*/
|
|
55
63
|
readonly dispose: () => void;
|
|
56
64
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { DisposalScope } from './disposal-scope';
|
|
2
|
+
/**
|
|
3
|
+
* Global scope stack for tracking active disposal scopes.
|
|
4
|
+
* The last element in the array is the current scope.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare const scopeStack: DisposalScope[];
|
|
9
|
+
/**
|
|
10
|
+
* Push a scope onto the stack, making it the current scope.
|
|
11
|
+
*
|
|
12
|
+
* @param scope - The scope to push
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export declare const pushScope: (scope: DisposalScope) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Pop the current scope from the stack.
|
|
18
|
+
*
|
|
19
|
+
* @throws Error if the stack is empty
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare const popScope: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Get the current active scope.
|
|
25
|
+
*
|
|
26
|
+
* @returns The current scope, or null if no scope is active
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export declare const getCurrentScope: () => DisposalScope | null;
|
|
30
|
+
/**
|
|
31
|
+
* Get the full scope stack.
|
|
32
|
+
* Useful for debugging scope hierarchy.
|
|
33
|
+
*
|
|
34
|
+
* @advanced Most users don't need this. Use getCurrentScope() instead.
|
|
35
|
+
* @returns Read-only array of active scopes
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export declare const getScopeStack: () => readonly DisposalScope[];
|
|
39
|
+
/**
|
|
40
|
+
* Get the parent scope of the current scope.
|
|
41
|
+
*
|
|
42
|
+
* @advanced Most users don't need this. Accessing parent scopes can lead to
|
|
43
|
+
* unexpected behavior. Only use this for debugging or advanced use cases.
|
|
44
|
+
* @returns The parent scope or null if no parent exists
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export declare const getParentScope: () => DisposalScope | null;
|
|
48
|
+
/**
|
|
49
|
+
* Execute a function within a scope context.
|
|
50
|
+
* The scope is pushed before the function executes and popped after.
|
|
51
|
+
* The scope is NOT disposed - the caller is responsible for disposal.
|
|
52
|
+
*
|
|
53
|
+
* @param scope - The scope to use
|
|
54
|
+
* @param fn - The function to execute
|
|
55
|
+
* @returns The result of the function
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export declare const withScope: <T>(scope: DisposalScope, fn: () => T) => T;
|
|
59
|
+
/**
|
|
60
|
+
* Execute a function in a new scope and dispose the scope immediately after.
|
|
61
|
+
* Useful for one-off scoped operations.
|
|
62
|
+
*
|
|
63
|
+
* @param fn - The function to execute, receives the scope as parameter
|
|
64
|
+
* @returns The result of the function
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
export declare const scoped: <T>(fn: (scope: DisposalScope) => T) => T;
|
|
68
|
+
/**
|
|
69
|
+
* Execute a function without any scope tracking.
|
|
70
|
+
* Signals created inside will NOT be automatically tracked.
|
|
71
|
+
*
|
|
72
|
+
* @param fn - The function to execute
|
|
73
|
+
* @returns The result of the function
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export declare const untracked: <T>(fn: () => T) => T;
|
package/std/signal.d.ts
CHANGED
|
@@ -157,6 +157,15 @@ export declare class Signal<T> {
|
|
|
157
157
|
* @param options - Options for the listener.
|
|
158
158
|
*/
|
|
159
159
|
readonly on: (listener: (value: T, previousValue: T | undefined) => void, options?: ListenerOptions) => () => void;
|
|
160
|
+
/**
|
|
161
|
+
* Registers a listener function to be called whenever the value of the signal changes.
|
|
162
|
+
* The listener function will not be called with the current value of the signal.
|
|
163
|
+
* Returns a function that can be called to unregister the listener.
|
|
164
|
+
*
|
|
165
|
+
* @param listener - The listener function to be called when the value of the signal changes.
|
|
166
|
+
* @param options - Options for the listener.
|
|
167
|
+
*/
|
|
168
|
+
readonly onChange: (listener: (value: T, previousValue: T) => void, options?: ListenerOptions) => () => void;
|
|
160
169
|
/**
|
|
161
170
|
* @internal
|
|
162
171
|
*/
|
|
@@ -225,10 +234,22 @@ export declare class Signal<T> {
|
|
|
225
234
|
* )
|
|
226
235
|
* ```
|
|
227
236
|
*
|
|
237
|
+
* **Auto-Disposal:** The returned computed signal is automatically registered with the current
|
|
238
|
+
* disposal scope (if one exists). When used within a renderable or `WithScope()`, the signal
|
|
239
|
+
* will be automatically disposed when the component unmounts. No manual `OnDispose()` needed!
|
|
240
|
+
*
|
|
241
|
+
* ```typescript
|
|
242
|
+
* const MyComponent: Renderable = (ctx) => {
|
|
243
|
+
* const count = prop(0);
|
|
244
|
+
* const doubled = count.map(x => x * 2); // ✅ Auto-disposed
|
|
245
|
+
* return html.div(doubled);
|
|
246
|
+
* };
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
228
249
|
* @typeParam O - The type of the transformed value
|
|
229
250
|
* @param fn - Function that transforms the signal's value to a new value
|
|
230
251
|
* @param equals - Optional function to determine if two transformed values are equal (defaults to strict equality)
|
|
231
|
-
* @returns A new computed signal with the transformed value
|
|
252
|
+
* @returns A new computed signal with the transformed value (auto-registered with current scope)
|
|
232
253
|
*/
|
|
233
254
|
readonly map: <O>(fn: (value: T) => O, equals?: (a: O, b: O) => boolean) => Computed<O>;
|
|
234
255
|
/**
|
|
@@ -365,9 +386,28 @@ export declare class Computed<T> extends Signal<T> {
|
|
|
365
386
|
*/
|
|
366
387
|
protected _isDirty: boolean;
|
|
367
388
|
/**
|
|
368
|
-
*
|
|
369
|
-
*
|
|
389
|
+
* Creates a new Computed signal.
|
|
390
|
+
*
|
|
391
|
+
* **Auto-Registration:** This constructor automatically registers the signal with the current
|
|
392
|
+
* disposal scope (if one exists). This ensures that computed signals created by methods like
|
|
393
|
+
* `.map()`, `.flatMap()`, `.filter()`, etc. are automatically tracked and disposed.
|
|
394
|
+
*
|
|
395
|
+
* When a computed signal is created within a renderable or `WithScope()`, it will be
|
|
396
|
+
* automatically disposed when the component unmounts or the scope is disposed.
|
|
397
|
+
*
|
|
398
|
+
* To create a computed signal that outlives the current scope, use `untracked()`:
|
|
399
|
+
* ```typescript
|
|
400
|
+
* const globalSignal = untracked(() => mySignal.map(x => x * 2));
|
|
401
|
+
* // Remember to dispose manually: globalSignal.dispose()
|
|
402
|
+
* ```
|
|
403
|
+
*
|
|
404
|
+
* @param _fn - The function that computes the value of the signal.
|
|
370
405
|
* @param equals - The function used to compare two values of type T for equality.
|
|
406
|
+
*
|
|
407
|
+
* @see {@link computed} - Factory function for creating computed signals with explicit dependencies
|
|
408
|
+
* @see {@link Signal.map} - Creates a computed signal by transforming values
|
|
409
|
+
* @see {@link getCurrentScope} - Get the current disposal scope
|
|
410
|
+
* @see {@link untracked} - Create signals outside of scope tracking
|
|
371
411
|
*/
|
|
372
412
|
constructor(_fn: () => T, equals: (a: T, b: T) => boolean);
|
|
373
413
|
/**
|
|
@@ -390,6 +430,12 @@ export declare class Computed<T> extends Signal<T> {
|
|
|
390
430
|
readonly get: () => T;
|
|
391
431
|
/** {@inheritDoc Signal.value} */
|
|
392
432
|
get value(): T;
|
|
433
|
+
/**
|
|
434
|
+
* Disposes the computed signal and cancels any pending recomputations.
|
|
435
|
+
* This override increments the schedule count to invalidate all pending
|
|
436
|
+
* microtasks before disposing the signal.
|
|
437
|
+
*/
|
|
438
|
+
readonly dispose: () => void;
|
|
393
439
|
}
|
|
394
440
|
/**
|
|
395
441
|
* Represents the data passed to a reducer effect.
|
package/std/value.d.ts
CHANGED
|
@@ -57,6 +57,14 @@ export declare const Value: {
|
|
|
57
57
|
* @param value - The value or Signal instance to dispose of.
|
|
58
58
|
*/
|
|
59
59
|
dispose: <T>(value: Value<T>) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Returns a function that disposes of a value or a Signal.
|
|
62
|
+
* If the value is a Signal, it returns a function that disposes of the Signal.
|
|
63
|
+
* If the value is not a Signal, it returns a function that does nothing.
|
|
64
|
+
* @param value - The value or Signal instance to dispose of.
|
|
65
|
+
* @returns A function to dispose of the value or Signal.
|
|
66
|
+
*/
|
|
67
|
+
disposeFn: <T>(value: Value<T>) => () => void;
|
|
60
68
|
/**
|
|
61
69
|
* Derives a Prop from a Signal.
|
|
62
70
|
* If the value is a Signal, it returns a new Prop with the derived value.
|