@xaendar/core 0.9.19 → 0.9.23
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.
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
//#region ../packages/core/src/signals/input/input-instance.symbol.ts
|
|
2
|
+
/**
|
|
3
|
+
* Unique symbol used to mark an object as a valid `InputSignal` instance.
|
|
4
|
+
*
|
|
5
|
+
* Set to `true` on every `InputSignal` created by the `input()` factory.
|
|
6
|
+
* Used by {@link isInputSignal} to distinguish input signals from plain
|
|
7
|
+
* `Signal.State` instances at runtime without exposing the marker in the
|
|
8
|
+
* public API.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
var INPUT_SIGNAL_INSTANCE_SYMBOL = Symbol(`InputSignalInstance`);
|
|
13
|
+
/**
|
|
14
|
+
* Type guard that checks whether a given value is an `InputSignal` instance.
|
|
15
|
+
*
|
|
16
|
+
* Inspects the presence of {@link INPUT_SIGNAL_INSTANCE_SYMBOL} on the object,
|
|
17
|
+
* which is set to `true` by the `input()` factory for every valid instance.
|
|
18
|
+
*
|
|
19
|
+
* @param instance - The value to inspect.
|
|
20
|
+
* @returns `true` if `instance` is an `InputSignal`, `false` otherwise.
|
|
21
|
+
*/
|
|
22
|
+
function isInputSignal(instance) {
|
|
23
|
+
return instance?.[INPUT_SIGNAL_INSTANCE_SYMBOL];
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region ../packages/core/src/signals/input/input-set.symbol.ts
|
|
27
|
+
/**
|
|
28
|
+
* This symbol is used to call the set method of the InputSignal
|
|
29
|
+
* Normally the set method is permitted internally and should not be called
|
|
30
|
+
* by the User
|
|
31
|
+
*/
|
|
32
|
+
var INPUT_SIGNAL_SET_SYMBOL = Symbol(`InputSignalSet`);
|
|
33
|
+
/**
|
|
34
|
+
* Asserts that the provided symbol matches the internal {@link INPUT_SIGNAL_SET_SYMBOL} symbol,
|
|
35
|
+
* ensuring the caller has access to internal APIs.
|
|
36
|
+
*
|
|
37
|
+
* Throws if the symbol does not match, preventing external code from
|
|
38
|
+
* invoking methods intended for internal use only.
|
|
39
|
+
*
|
|
40
|
+
* @param symbol - The symbol to validate against {@link INPUT_SIGNAL_SET_SYMBOL}.
|
|
41
|
+
* @throws {Error} If `symbol` does not match {@link INPUT_SIGNAL_SET_SYMBOL}.
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
function assertPrivateContext(symbol) {
|
|
45
|
+
if (symbol !== INPUT_SIGNAL_SET_SYMBOL) throw new Error("Invalid symbol for InputSignal set method");
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region ../packages/core/src/signals/input/input.ts
|
|
49
|
+
/**
|
|
50
|
+
* Creates an `InputSignal` — a specialized reactive state designed for use
|
|
51
|
+
* as a property signal in web components.
|
|
52
|
+
*
|
|
53
|
+
* Unlike a plain `Signal.State`, the `set` method of an `InputSignal` is
|
|
54
|
+
* restricted to internal callers (identified by the private symbol) and
|
|
55
|
+
* accepts an optional `transform` function that converts incoming values
|
|
56
|
+
* (e.g. raw HTML attribute strings) into the internally stored type before
|
|
57
|
+
* updating the signal.
|
|
58
|
+
*
|
|
59
|
+
* @param value - The initial value of the signal.
|
|
60
|
+
* @param options - Optional configuration including an equality function,
|
|
61
|
+
* lifecycle hooks, and a `transform` function applied to incoming values.
|
|
62
|
+
* @returns A new `InputSignal` instance.
|
|
63
|
+
*/
|
|
64
|
+
function input(value, options) {
|
|
65
|
+
const transform = options?.transform;
|
|
66
|
+
delete options?.transform;
|
|
67
|
+
const signal = new Signal.State(value, options);
|
|
68
|
+
const originalSet = signal.set;
|
|
69
|
+
const getter = function() {
|
|
70
|
+
return signal.get();
|
|
71
|
+
};
|
|
72
|
+
Object.assign(getter, {
|
|
73
|
+
set(newValue, symbol) {
|
|
74
|
+
assertPrivateContext(symbol);
|
|
75
|
+
const transformedValue = transform ? transform(newValue) : newValue;
|
|
76
|
+
originalSet.call(signal, transformedValue);
|
|
77
|
+
},
|
|
78
|
+
get: signal.get.bind(signal)
|
|
79
|
+
});
|
|
80
|
+
getter[INPUT_SIGNAL_INSTANCE_SYMBOL] = true;
|
|
81
|
+
return getter;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region ../packages/core/src/signals/computed/computed.ts
|
|
85
|
+
/**
|
|
86
|
+
* Creates a read-only computed signal whose value is derived from other signals.
|
|
87
|
+
*
|
|
88
|
+
* Returns a callable getter that reads the current value, augmented with the
|
|
89
|
+
* underlying {@link Signal.State} API.
|
|
90
|
+
*
|
|
91
|
+
* @template Value - The type of the computed value. Defaults to `any`.
|
|
92
|
+
* @param value - The initial (seed) value of the computed signal.
|
|
93
|
+
* @param options - Configuration options for the underlying signal.
|
|
94
|
+
* @returns A {@link Computed} instance.
|
|
95
|
+
*/
|
|
96
|
+
function computed(value, options) {
|
|
97
|
+
const signal = new Signal.State(value, options);
|
|
98
|
+
const getter = function() {
|
|
99
|
+
return signal.get();
|
|
100
|
+
};
|
|
101
|
+
Object.assign(getter, { get: signal.get.bind(signal) });
|
|
102
|
+
return getter;
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region ../packages/core/src/signals/effect/effect.ts
|
|
106
|
+
/**
|
|
107
|
+
* Runs a side-effectful function and automatically re-runs it whenever any
|
|
108
|
+
* Signal read during its execution changes.
|
|
109
|
+
*
|
|
110
|
+
* Internally, `effect` wraps the user callback inside a `Computed` node
|
|
111
|
+
* (for dependency tracking) and observes it with a `Watcher` (for push
|
|
112
|
+
* notifications). When any tracked dependency changes, the `Watcher`
|
|
113
|
+
* schedules a microtask that re-evaluates the `Computed`, which in turn
|
|
114
|
+
* re-runs the user callback and re-registers the new set of dependencies.
|
|
115
|
+
*
|
|
116
|
+
* The returned disposer function stops the effect: it unwatches the internal
|
|
117
|
+
* `Computed` from the `Watcher`, severing all dependency subscriptions so
|
|
118
|
+
* the callback is never called again and the graph nodes can be
|
|
119
|
+
* garbage-collected.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* const count = new State(0);
|
|
124
|
+
*
|
|
125
|
+
* const stop = effect(() => {
|
|
126
|
+
* console.log('count is', count.get());
|
|
127
|
+
* });
|
|
128
|
+
* // logs: "count is 0"
|
|
129
|
+
*
|
|
130
|
+
* count.set(1); // logs: "count is 1"
|
|
131
|
+
* count.set(2); // logs: "count is 2"
|
|
132
|
+
*
|
|
133
|
+
* stop(); // no more logs
|
|
134
|
+
* count.set(3); // silent
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @param fn - The side-effectful function to run. Any Signal read inside it
|
|
138
|
+
* is tracked as a dependency.
|
|
139
|
+
* @returns A disposer function that, when called, permanently stops the effect.
|
|
140
|
+
*/
|
|
141
|
+
function effect(fn, options) {
|
|
142
|
+
/**
|
|
143
|
+
* Wrap the user callback in a Computed so that automatic dependency
|
|
144
|
+
* tracking (via pushComputed / popComputed) works for free.
|
|
145
|
+
* The Computed always returns `undefined` — we only care about the
|
|
146
|
+
* side-effects and the tracked sources, not the value.
|
|
147
|
+
*/
|
|
148
|
+
const computed = new Signal.Computed(() => fn());
|
|
149
|
+
let needsEnqueue = true;
|
|
150
|
+
/**
|
|
151
|
+
* The Watcher is notified synchronously as soon as any tracked dependency
|
|
152
|
+
* changes. Its job is purely to schedule the re-execution; the actual
|
|
153
|
+
* re-evaluation happens asynchronously in a microtask so that multiple
|
|
154
|
+
* synchronous signal updates are batched into a single re-run.
|
|
155
|
+
*/
|
|
156
|
+
const watcher = new Signal.subtle.Watcher(() => {
|
|
157
|
+
if (needsEnqueue) {
|
|
158
|
+
needsEnqueue = false;
|
|
159
|
+
queueMicrotask(() => {
|
|
160
|
+
needsEnqueue = true;
|
|
161
|
+
options?.onBeforeRun?.();
|
|
162
|
+
const pendings = watcher.getPending();
|
|
163
|
+
for (let i = 0; i < pendings.length; i++) pendings[i].get();
|
|
164
|
+
options?.onAfterRun?.();
|
|
165
|
+
watcher.watch();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
options?.onBeforeRun?.();
|
|
170
|
+
watcher.watch(computed);
|
|
171
|
+
computed.get();
|
|
172
|
+
options?.onAfterRun?.();
|
|
173
|
+
/**
|
|
174
|
+
* Disposer — call this to permanently stop the effect.
|
|
175
|
+
*
|
|
176
|
+
* Unwatching the Computed tears down the entire live dependency chain
|
|
177
|
+
* (Watcher → Computed → all sources), preventing any further
|
|
178
|
+
* notifications and allowing GC.
|
|
179
|
+
*/
|
|
180
|
+
return () => {
|
|
181
|
+
options?.onCleanup?.();
|
|
182
|
+
watcher.unwatch(computed);
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region ../packages/core/src/signals/signal/signal.ts
|
|
187
|
+
/**
|
|
188
|
+
* Creates a writable reactive signal.
|
|
189
|
+
*
|
|
190
|
+
* Returns a callable getter that reads the current value, augmented with the
|
|
191
|
+
* underlying {@link Signal.State} API and an `update` method to derive the next
|
|
192
|
+
* value from the previous one.
|
|
193
|
+
*
|
|
194
|
+
* @template T - The type of the stored value. Defaults to `any`.
|
|
195
|
+
* @param value - The initial value of the signal.
|
|
196
|
+
* @param options - Configuration options for the signal.
|
|
197
|
+
* @returns A {@link SignalType} instance.
|
|
198
|
+
*/
|
|
199
|
+
function signal(value, options) {
|
|
200
|
+
const signal = new Signal.State(value, options);
|
|
201
|
+
const getter = function() {
|
|
202
|
+
return signal.get();
|
|
203
|
+
};
|
|
204
|
+
Object.assign(getter, {
|
|
205
|
+
set: signal.set.bind(signal),
|
|
206
|
+
get: signal.get.bind(signal),
|
|
207
|
+
update: (updater) => signal.set(updater(signal.get()))
|
|
208
|
+
});
|
|
209
|
+
return getter;
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region ../packages/core/src/signals/untracked.ts
|
|
213
|
+
/**
|
|
214
|
+
* Executes a function without tracking any dependencies.
|
|
215
|
+
* @param fn - The function to execute without tracking.
|
|
216
|
+
* @returns The result of the function execution.
|
|
217
|
+
*/
|
|
218
|
+
var untracked = Signal.subtle.untrack;
|
|
219
|
+
//#endregion
|
|
220
|
+
export { input as a, computed as i, signal as n, INPUT_SIGNAL_SET_SYMBOL as o, effect as r, isInputSignal as s, untracked as t };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { EffectOptions } from '../../../../../schematics/packages/signals/src/public-api';
|
|
2
|
+
import { NoArgsVoidFunction } from '../../../../../schematics/packages/types/src/public-api';
|
|
3
|
+
import { SignalOptions } from '../../../../../schematics/packages/signals/src/public-api';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A read-only reactive value derived from other signals.
|
|
7
|
+
*
|
|
8
|
+
* Wraps {@link Signal.Computed} and is also callable as a function to read the
|
|
9
|
+
* current computed value.
|
|
10
|
+
*
|
|
11
|
+
* @template Value - The type of the computed value. Defaults to `any`.
|
|
12
|
+
*/
|
|
13
|
+
declare type Computed<Value = any> = Signal.Computed<Value> & {
|
|
14
|
+
/**
|
|
15
|
+
* Reads the current computed value, recomputing it if any dependency changed.
|
|
16
|
+
*
|
|
17
|
+
* @returns The current value of type `Value`.
|
|
18
|
+
*/
|
|
19
|
+
(): Value;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Creates a read-only computed signal whose value is derived from other signals.
|
|
24
|
+
*
|
|
25
|
+
* Returns a callable getter that reads the current value, augmented with the
|
|
26
|
+
* underlying {@link Signal.State} API.
|
|
27
|
+
*
|
|
28
|
+
* @template Value - The type of the computed value. Defaults to `any`.
|
|
29
|
+
* @param value - The initial (seed) value of the computed signal.
|
|
30
|
+
* @param options - Configuration options for the underlying signal.
|
|
31
|
+
* @returns A {@link Computed} instance.
|
|
32
|
+
*/
|
|
33
|
+
export declare function computed<Value = any>(value: Value, options?: SignalOptions<Value>): Computed<Value>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Runs a side-effectful function and automatically re-runs it whenever any
|
|
37
|
+
* Signal read during its execution changes.
|
|
38
|
+
*
|
|
39
|
+
* Internally, `effect` wraps the user callback inside a `Computed` node
|
|
40
|
+
* (for dependency tracking) and observes it with a `Watcher` (for push
|
|
41
|
+
* notifications). When any tracked dependency changes, the `Watcher`
|
|
42
|
+
* schedules a microtask that re-evaluates the `Computed`, which in turn
|
|
43
|
+
* re-runs the user callback and re-registers the new set of dependencies.
|
|
44
|
+
*
|
|
45
|
+
* The returned disposer function stops the effect: it unwatches the internal
|
|
46
|
+
* `Computed` from the `Watcher`, severing all dependency subscriptions so
|
|
47
|
+
* the callback is never called again and the graph nodes can be
|
|
48
|
+
* garbage-collected.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* const count = new State(0);
|
|
53
|
+
*
|
|
54
|
+
* const stop = effect(() => {
|
|
55
|
+
* console.log('count is', count.get());
|
|
56
|
+
* });
|
|
57
|
+
* // logs: "count is 0"
|
|
58
|
+
*
|
|
59
|
+
* count.set(1); // logs: "count is 1"
|
|
60
|
+
* count.set(2); // logs: "count is 2"
|
|
61
|
+
*
|
|
62
|
+
* stop(); // no more logs
|
|
63
|
+
* count.set(3); // silent
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @param fn - The side-effectful function to run. Any Signal read inside it
|
|
67
|
+
* is tracked as a dependency.
|
|
68
|
+
* @returns A disposer function that, when called, permanently stops the effect.
|
|
69
|
+
*/
|
|
70
|
+
export declare function effect(fn: NoArgsVoidFunction, options?: EffectOptions): NoArgsVoidFunction;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Creates an `InputSignal` — a specialized reactive state designed for use
|
|
74
|
+
* as a property signal in web components.
|
|
75
|
+
*
|
|
76
|
+
* Unlike a plain `Signal.State`, the `set` method of an `InputSignal` is
|
|
77
|
+
* restricted to internal callers (identified by the private symbol) and
|
|
78
|
+
* accepts an optional `transform` function that converts incoming values
|
|
79
|
+
* (e.g. raw HTML attribute strings) into the internally stored type before
|
|
80
|
+
* updating the signal.
|
|
81
|
+
*
|
|
82
|
+
* @param value - The initial value of the signal.
|
|
83
|
+
* @param options - Optional configuration including an equality function,
|
|
84
|
+
* lifecycle hooks, and a `transform` function applied to incoming values.
|
|
85
|
+
* @returns A new `InputSignal` instance.
|
|
86
|
+
*/
|
|
87
|
+
export declare function input<ActualValue = unknown, IncomingValue = ActualValue>(value?: ActualValue, options?: InputSignalOptions<ActualValue, IncomingValue>): InputSignal<ActualValue, IncomingValue>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A reactive value sourced from outside the component (e.g. an attribute).
|
|
91
|
+
*
|
|
92
|
+
* Wraps {@link Signal.State} without its `set` method (inputs are not set
|
|
93
|
+
* directly) and is callable as a function to read the current value. An
|
|
94
|
+
* optional {@link InputSignalOptions.transform} can convert the incoming value
|
|
95
|
+
* into the actual stored value.
|
|
96
|
+
*
|
|
97
|
+
* @template ActualValue - The internal type stored by the signal. Defaults to `unknown`.
|
|
98
|
+
* @template IncomingValue - The raw type received from outside. Defaults to `ActualValue`.
|
|
99
|
+
*/
|
|
100
|
+
declare type InputSignal<ActualValue = unknown, IncomingValue = ActualValue> = Omit<Signal.State<ActualValue>, 'set'> & {
|
|
101
|
+
/**
|
|
102
|
+
* Reads the current value of the input signal.
|
|
103
|
+
*
|
|
104
|
+
* @returns The current value of type `ActualValue`.
|
|
105
|
+
*/
|
|
106
|
+
(): ActualValue;
|
|
107
|
+
/**
|
|
108
|
+
* Creates a new input signal.
|
|
109
|
+
*
|
|
110
|
+
* @param value - The initial incoming value.
|
|
111
|
+
* @param options - Optional configuration, including a `transform` function.
|
|
112
|
+
*/
|
|
113
|
+
new (value: IncomingValue, options?: InputSignalOptions<ActualValue, IncomingValue>): InputSignal<ActualValue, IncomingValue>;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Options used to configure an `InputSignal`.
|
|
118
|
+
*
|
|
119
|
+
* Extends {@link SignalOptions} with an optional `transform` function that
|
|
120
|
+
* converts the incoming value (e.g. an attribute string) into the actual
|
|
121
|
+
* internal value stored by the signal.
|
|
122
|
+
*
|
|
123
|
+
* @template ActualValue - The internal type stored by the signal. Defaults to `unknown`.
|
|
124
|
+
* @template IncomingValue - The raw type received from outside (e.g. from an attribute). Defaults to `ActualValue`.
|
|
125
|
+
*/
|
|
126
|
+
declare type InputSignalOptions<ActualValue = unknown, IncomingValue = ActualValue> = SignalOptions<ActualValue> & {
|
|
127
|
+
/**
|
|
128
|
+
* Optional function to transform the incoming value before it is stored.
|
|
129
|
+
*
|
|
130
|
+
* @param value - The raw incoming value.
|
|
131
|
+
* @returns The transformed value of type `ActualValue`.
|
|
132
|
+
*/
|
|
133
|
+
transform?: (value: IncomingValue) => ActualValue;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Creates a writable reactive signal.
|
|
138
|
+
*
|
|
139
|
+
* Returns a callable getter that reads the current value, augmented with the
|
|
140
|
+
* underlying {@link Signal.State} API and an `update` method to derive the next
|
|
141
|
+
* value from the previous one.
|
|
142
|
+
*
|
|
143
|
+
* @template T - The type of the stored value. Defaults to `any`.
|
|
144
|
+
* @param value - The initial value of the signal.
|
|
145
|
+
* @param options - Configuration options for the signal.
|
|
146
|
+
* @returns A {@link SignalType} instance.
|
|
147
|
+
*/
|
|
148
|
+
export declare function signal<T = any>(value: T, options?: SignalOptions<T>): Signal_2<T>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* A writable reactive value.
|
|
152
|
+
*
|
|
153
|
+
* Wraps {@link Signal.State} and is also callable as a function to set a new
|
|
154
|
+
* value directly.
|
|
155
|
+
*
|
|
156
|
+
* @template Value - The type of the stored value. Defaults to `any`.
|
|
157
|
+
*/
|
|
158
|
+
declare type Signal_2<Value = any> = Signal.State<Value> & {
|
|
159
|
+
/**
|
|
160
|
+
* Get the current value of the signal.
|
|
161
|
+
*
|
|
162
|
+
* @returns The current value of the signal.
|
|
163
|
+
*/
|
|
164
|
+
(): Value;
|
|
165
|
+
/**
|
|
166
|
+
* Updates the signal value based on its previous value.
|
|
167
|
+
*
|
|
168
|
+
* @param updater - Function receiving the previous value and returning the next one.
|
|
169
|
+
*/
|
|
170
|
+
update(updater: (prev: Value) => Value): void;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Executes a function without tracking any dependencies.
|
|
175
|
+
* @param fn - The function to execute without tracking.
|
|
176
|
+
* @returns The result of the function execution.
|
|
177
|
+
*/
|
|
178
|
+
export declare const untracked: typeof Signal.subtle.untrack;
|
|
179
|
+
|
|
180
|
+
export { }
|
package/dist/signals.js
ADDED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { a as input, i as computed, n as signal, o as INPUT_SIGNAL_SET_SYMBOL, r as effect, s as isInputSignal, t as untracked } from "./signals-CxEAdVoe.js";
|
|
1
2
|
//#region ../packages/core/src/decorators/event.decorator.ts
|
|
2
3
|
function isEventOptions(value) {
|
|
3
4
|
return !!value && typeof value === "object" && ("bubbles" in value || "cancelable" in value || "composed" in value);
|
|
@@ -63,89 +64,6 @@ var INTERNAL_OBSERVED_ATTRIBUTES = `observedAttributes`;
|
|
|
63
64
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
64
65
|
var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
|
|
65
66
|
//#endregion
|
|
66
|
-
//#region ../packages/core/src/signals/input/input-instance.symbol.ts
|
|
67
|
-
/**
|
|
68
|
-
* Unique symbol used to mark an object as a valid `InputSignal` instance.
|
|
69
|
-
*
|
|
70
|
-
* Set to `true` on every `InputSignal` created by the `input()` factory.
|
|
71
|
-
* Used by {@link isInputSignal} to distinguish input signals from plain
|
|
72
|
-
* `Signal.State` instances at runtime without exposing the marker in the
|
|
73
|
-
* public API.
|
|
74
|
-
*
|
|
75
|
-
* @internal
|
|
76
|
-
*/
|
|
77
|
-
var INPUT_SIGNAL_INSTANCE_SYMBOL = Symbol(`InputSignalInstance`);
|
|
78
|
-
/**
|
|
79
|
-
* Type guard that checks whether a given value is an `InputSignal` instance.
|
|
80
|
-
*
|
|
81
|
-
* Inspects the presence of {@link INPUT_SIGNAL_INSTANCE_SYMBOL} on the object,
|
|
82
|
-
* which is set to `true` by the `input()` factory for every valid instance.
|
|
83
|
-
*
|
|
84
|
-
* @param instance - The value to inspect.
|
|
85
|
-
* @returns `true` if `instance` is an `InputSignal`, `false` otherwise.
|
|
86
|
-
*/
|
|
87
|
-
function isInputSignal(instance) {
|
|
88
|
-
return instance?.[INPUT_SIGNAL_INSTANCE_SYMBOL];
|
|
89
|
-
}
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region ../packages/core/src/signals/input/input-set.symbol.ts
|
|
92
|
-
/**
|
|
93
|
-
* This symbol is used to call the set method of the InputSignal
|
|
94
|
-
* Normally the set method is permitted internally and should not be called
|
|
95
|
-
* by the User
|
|
96
|
-
*/
|
|
97
|
-
var INPUT_SIGNAL_SET_SYMBOL = Symbol(`InputSignalSet`);
|
|
98
|
-
/**
|
|
99
|
-
* Asserts that the provided symbol matches the internal {@link INPUT_SIGNAL_SET_SYMBOL} symbol,
|
|
100
|
-
* ensuring the caller has access to internal APIs.
|
|
101
|
-
*
|
|
102
|
-
* Throws if the symbol does not match, preventing external code from
|
|
103
|
-
* invoking methods intended for internal use only.
|
|
104
|
-
*
|
|
105
|
-
* @param symbol - The symbol to validate against {@link INPUT_SIGNAL_SET_SYMBOL}.
|
|
106
|
-
* @throws {Error} If `symbol` does not match {@link INPUT_SIGNAL_SET_SYMBOL}.
|
|
107
|
-
* @internal
|
|
108
|
-
*/
|
|
109
|
-
function assertPrivateContext(symbol) {
|
|
110
|
-
if (symbol !== INPUT_SIGNAL_SET_SYMBOL) throw new Error("Invalid symbol for InputSignal set method");
|
|
111
|
-
}
|
|
112
|
-
//#endregion
|
|
113
|
-
//#region ../packages/core/src/signals/input/input.ts
|
|
114
|
-
/**
|
|
115
|
-
* Creates an `InputSignal` — a specialized reactive state designed for use
|
|
116
|
-
* as a property signal in web components.
|
|
117
|
-
*
|
|
118
|
-
* Unlike a plain `Signal.State`, the `set` method of an `InputSignal` is
|
|
119
|
-
* restricted to internal callers (identified by the private symbol) and
|
|
120
|
-
* accepts an optional `transform` function that converts incoming values
|
|
121
|
-
* (e.g. raw HTML attribute strings) into the internally stored type before
|
|
122
|
-
* updating the signal.
|
|
123
|
-
*
|
|
124
|
-
* @param value - The initial value of the signal.
|
|
125
|
-
* @param options - Optional configuration including an equality function,
|
|
126
|
-
* lifecycle hooks, and a `transform` function applied to incoming values.
|
|
127
|
-
* @returns A new `InputSignal` instance.
|
|
128
|
-
*/
|
|
129
|
-
function input(value, options) {
|
|
130
|
-
const transform = options?.transform;
|
|
131
|
-
delete options?.transform;
|
|
132
|
-
const signal = new Signal.State(value, options);
|
|
133
|
-
const originalSet = signal.set;
|
|
134
|
-
const getter = function() {
|
|
135
|
-
return signal.get();
|
|
136
|
-
};
|
|
137
|
-
Object.assign(getter, {
|
|
138
|
-
set(newValue, symbol) {
|
|
139
|
-
assertPrivateContext(symbol);
|
|
140
|
-
const transformedValue = transform ? transform(newValue) : newValue;
|
|
141
|
-
originalSet.call(signal, transformedValue);
|
|
142
|
-
},
|
|
143
|
-
get: signal.get.bind(signal)
|
|
144
|
-
});
|
|
145
|
-
getter[INPUT_SIGNAL_INSTANCE_SYMBOL] = true;
|
|
146
|
-
return getter;
|
|
147
|
-
}
|
|
148
|
-
//#endregion
|
|
149
67
|
//#region ../packages/core/src/decorators/property.decorator.ts
|
|
150
68
|
var propertyDecoratorOptionsWithRequiredBrand = Symbol("PropertyDecoratorOptionsWithRequiredBrand");
|
|
151
69
|
function createPropertyDecorator(value, options) {
|
|
@@ -362,142 +280,6 @@ var BaseWebComponent = class extends HTMLElement {
|
|
|
362
280
|
}
|
|
363
281
|
};
|
|
364
282
|
//#endregion
|
|
365
|
-
//#region ../packages/core/src/signals/computed/computed.ts
|
|
366
|
-
/**
|
|
367
|
-
* Creates a read-only computed signal whose value is derived from other signals.
|
|
368
|
-
*
|
|
369
|
-
* Returns a callable getter that reads the current value, augmented with the
|
|
370
|
-
* underlying {@link Signal.State} API.
|
|
371
|
-
*
|
|
372
|
-
* @template Value - The type of the computed value. Defaults to `any`.
|
|
373
|
-
* @param value - The initial (seed) value of the computed signal.
|
|
374
|
-
* @param options - Configuration options for the underlying signal.
|
|
375
|
-
* @returns A {@link Computed} instance.
|
|
376
|
-
*/
|
|
377
|
-
function computed(value, options) {
|
|
378
|
-
const signal = new Signal.State(value, options);
|
|
379
|
-
const getter = function() {
|
|
380
|
-
return signal.get();
|
|
381
|
-
};
|
|
382
|
-
Object.assign(getter, { get: signal.get.bind(signal) });
|
|
383
|
-
return getter;
|
|
384
|
-
}
|
|
385
|
-
//#endregion
|
|
386
|
-
//#region ../packages/core/src/signals/effect/effect.ts
|
|
387
|
-
/**
|
|
388
|
-
* Runs a side-effectful function and automatically re-runs it whenever any
|
|
389
|
-
* Signal read during its execution changes.
|
|
390
|
-
*
|
|
391
|
-
* Internally, `effect` wraps the user callback inside a `Computed` node
|
|
392
|
-
* (for dependency tracking) and observes it with a `Watcher` (for push
|
|
393
|
-
* notifications). When any tracked dependency changes, the `Watcher`
|
|
394
|
-
* schedules a microtask that re-evaluates the `Computed`, which in turn
|
|
395
|
-
* re-runs the user callback and re-registers the new set of dependencies.
|
|
396
|
-
*
|
|
397
|
-
* The returned disposer function stops the effect: it unwatches the internal
|
|
398
|
-
* `Computed` from the `Watcher`, severing all dependency subscriptions so
|
|
399
|
-
* the callback is never called again and the graph nodes can be
|
|
400
|
-
* garbage-collected.
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* ```ts
|
|
404
|
-
* const count = new State(0);
|
|
405
|
-
*
|
|
406
|
-
* const stop = effect(() => {
|
|
407
|
-
* console.log('count is', count.get());
|
|
408
|
-
* });
|
|
409
|
-
* // logs: "count is 0"
|
|
410
|
-
*
|
|
411
|
-
* count.set(1); // logs: "count is 1"
|
|
412
|
-
* count.set(2); // logs: "count is 2"
|
|
413
|
-
*
|
|
414
|
-
* stop(); // no more logs
|
|
415
|
-
* count.set(3); // silent
|
|
416
|
-
* ```
|
|
417
|
-
*
|
|
418
|
-
* @param fn - The side-effectful function to run. Any Signal read inside it
|
|
419
|
-
* is tracked as a dependency.
|
|
420
|
-
* @returns A disposer function that, when called, permanently stops the effect.
|
|
421
|
-
*/
|
|
422
|
-
function effect(fn, options) {
|
|
423
|
-
/**
|
|
424
|
-
* Wrap the user callback in a Computed so that automatic dependency
|
|
425
|
-
* tracking (via pushComputed / popComputed) works for free.
|
|
426
|
-
* The Computed always returns `undefined` — we only care about the
|
|
427
|
-
* side-effects and the tracked sources, not the value.
|
|
428
|
-
*/
|
|
429
|
-
const computed = new Signal.Computed(() => fn());
|
|
430
|
-
let needsEnqueue = true;
|
|
431
|
-
/**
|
|
432
|
-
* The Watcher is notified synchronously as soon as any tracked dependency
|
|
433
|
-
* changes. Its job is purely to schedule the re-execution; the actual
|
|
434
|
-
* re-evaluation happens asynchronously in a microtask so that multiple
|
|
435
|
-
* synchronous signal updates are batched into a single re-run.
|
|
436
|
-
*/
|
|
437
|
-
const watcher = new Signal.subtle.Watcher(() => {
|
|
438
|
-
if (needsEnqueue) {
|
|
439
|
-
needsEnqueue = false;
|
|
440
|
-
queueMicrotask(() => {
|
|
441
|
-
needsEnqueue = true;
|
|
442
|
-
options?.onBeforeRun?.();
|
|
443
|
-
const pendings = watcher.getPending();
|
|
444
|
-
for (let i = 0; i < pendings.length; i++) pendings[i].get();
|
|
445
|
-
options?.onAfterRun?.();
|
|
446
|
-
watcher.watch();
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
options?.onBeforeRun?.();
|
|
451
|
-
watcher.watch(computed);
|
|
452
|
-
computed.get();
|
|
453
|
-
options?.onAfterRun?.();
|
|
454
|
-
/**
|
|
455
|
-
* Disposer — call this to permanently stop the effect.
|
|
456
|
-
*
|
|
457
|
-
* Unwatching the Computed tears down the entire live dependency chain
|
|
458
|
-
* (Watcher → Computed → all sources), preventing any further
|
|
459
|
-
* notifications and allowing GC.
|
|
460
|
-
*/
|
|
461
|
-
return () => {
|
|
462
|
-
options?.onCleanup?.();
|
|
463
|
-
watcher.unwatch(computed);
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
//#endregion
|
|
467
|
-
//#region ../packages/core/src/signals/signal/signal.ts
|
|
468
|
-
/**
|
|
469
|
-
* Creates a writable reactive signal.
|
|
470
|
-
*
|
|
471
|
-
* Returns a callable getter that reads the current value, augmented with the
|
|
472
|
-
* underlying {@link Signal.State} API and an `update` method to derive the next
|
|
473
|
-
* value from the previous one.
|
|
474
|
-
*
|
|
475
|
-
* @template T - The type of the stored value. Defaults to `any`.
|
|
476
|
-
* @param value - The initial value of the signal.
|
|
477
|
-
* @param options - Configuration options for the signal.
|
|
478
|
-
* @returns A {@link SignalType} instance.
|
|
479
|
-
*/
|
|
480
|
-
function signal(value, options) {
|
|
481
|
-
const signal = new Signal.State(value, options);
|
|
482
|
-
const getter = function() {
|
|
483
|
-
return signal.get();
|
|
484
|
-
};
|
|
485
|
-
Object.assign(getter, {
|
|
486
|
-
set: signal.set.bind(signal),
|
|
487
|
-
get: signal.get.bind(signal),
|
|
488
|
-
update: (updater) => signal.set(updater(signal.get()))
|
|
489
|
-
});
|
|
490
|
-
return getter;
|
|
491
|
-
}
|
|
492
|
-
//#endregion
|
|
493
|
-
//#region ../packages/core/src/signals/untracked.ts
|
|
494
|
-
/**
|
|
495
|
-
* Executes a function without tracking any dependencies.
|
|
496
|
-
* @param fn - The function to execute without tracking.
|
|
497
|
-
* @returns The result of the function execution.
|
|
498
|
-
*/
|
|
499
|
-
var untracked = Signal.subtle.untrack;
|
|
500
|
-
//#endregion
|
|
501
283
|
//#region ../packages/core/src/utils/context.util.ts
|
|
502
284
|
/**
|
|
503
285
|
* Tracks identifier scope during run time template function execution
|
|
@@ -962,8 +744,8 @@ function _renderElement(parentNode, context, anchor, tagName, attributes, events
|
|
|
962
744
|
const element = context.createElement(tagName);
|
|
963
745
|
mountNode(element, parentNode, context, anchor);
|
|
964
746
|
for (let i = 0; i < attributes.length; i++) {
|
|
965
|
-
const { name, value,
|
|
966
|
-
|
|
747
|
+
const { name, value, reactive } = attributes[i];
|
|
748
|
+
reactive ? context.listen(effect(() => element.setAttribute(name, String(value())))) : element.setAttribute(name, String(value()));
|
|
967
749
|
}
|
|
968
750
|
for (let i = 0; i < events.length; i++) {
|
|
969
751
|
const event = events[i];
|
package/package.json
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.23",
|
|
4
4
|
"description": "A library containing core utils such as webcomponent base classes and theming support",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./dist/xaendar-core.
|
|
8
|
-
"module": "./dist/xaendar-core.
|
|
9
|
-
"types": "./dist/xaendar-core.
|
|
7
|
+
"main": "./dist/xaendar-core.js",
|
|
8
|
+
"module": "./dist/xaendar-core.js",
|
|
9
|
+
"types": "./dist/xaendar-core.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"import": {
|
|
13
|
-
"types": "./dist/xaendar-core.
|
|
14
|
-
"default": "./dist/xaendar-core.
|
|
13
|
+
"types": "./dist/xaendar-core.d.ts",
|
|
14
|
+
"default": "./dist/xaendar-core.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"signals": {
|
|
18
|
+
"import": {
|
|
19
|
+
"types": "./dist/signals.d.ts",
|
|
20
|
+
"default": "./dist/signals.js"
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
23
|
},
|
|
18
24
|
"dependencies": {
|
|
19
|
-
"@xaendar/signals": "0.9.
|
|
20
|
-
"@xaendar/types": "0.9.
|
|
25
|
+
"@xaendar/signals": "0.9.23",
|
|
26
|
+
"@xaendar/types": "0.9.23"
|
|
21
27
|
}
|
|
22
28
|
}
|