@xaendar/core 0.9.18 → 0.9.22

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,261 @@
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
+ Object.defineProperty(exports, "INPUT_SIGNAL_SET_SYMBOL", {
221
+ enumerable: true,
222
+ get: function() {
223
+ return INPUT_SIGNAL_SET_SYMBOL;
224
+ }
225
+ });
226
+ Object.defineProperty(exports, "computed", {
227
+ enumerable: true,
228
+ get: function() {
229
+ return computed;
230
+ }
231
+ });
232
+ Object.defineProperty(exports, "effect", {
233
+ enumerable: true,
234
+ get: function() {
235
+ return effect;
236
+ }
237
+ });
238
+ Object.defineProperty(exports, "input", {
239
+ enumerable: true,
240
+ get: function() {
241
+ return input;
242
+ }
243
+ });
244
+ Object.defineProperty(exports, "isInputSignal", {
245
+ enumerable: true,
246
+ get: function() {
247
+ return isInputSignal;
248
+ }
249
+ });
250
+ Object.defineProperty(exports, "signal", {
251
+ enumerable: true,
252
+ get: function() {
253
+ return signal;
254
+ }
255
+ });
256
+ Object.defineProperty(exports, "untracked", {
257
+ enumerable: true,
258
+ get: function() {
259
+ return untracked;
260
+ }
261
+ });
@@ -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 { }
@@ -0,0 +1,7 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_signals = require("./signals-C-55LNEj.cjs");
3
+ exports.computed = require_signals.computed;
4
+ exports.effect = require_signals.effect;
5
+ exports.input = require_signals.input;
6
+ exports.signal = require_signals.signal;
7
+ exports.untracked = require_signals.untracked;
@@ -604,7 +604,7 @@ declare type RenderElementAttribute = {
604
604
  /**
605
605
  * When `true`, the value is a static string literal; when `false`, it is a reactive expression.
606
606
  */
607
- literal: boolean;
607
+ reactive: boolean;
608
608
  };
609
609
 
610
610
  /**
@@ -1,3 +1,5 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_signals = require("./signals-C-55LNEj.cjs");
1
3
  //#region ../packages/core/src/decorators/event.decorator.ts
2
4
  function isEventOptions(value) {
3
5
  return !!value && typeof value === "object" && ("bubbles" in value || "cancelable" in value || "composed" in value);
@@ -63,89 +65,6 @@ var INTERNAL_OBSERVED_ATTRIBUTES = `observedAttributes`;
63
65
  var SVG_NS = "http://www.w3.org/2000/svg";
64
66
  var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
65
67
  //#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
68
  //#region ../packages/core/src/decorators/property.decorator.ts
150
69
  var propertyDecoratorOptionsWithRequiredBrand = Symbol("PropertyDecoratorOptionsWithRequiredBrand");
151
70
  function createPropertyDecorator(value, options) {
@@ -161,7 +80,7 @@ function createPropertyDecorator(value, options) {
161
80
  actualValue = value;
162
81
  actualOptions = options;
163
82
  } else actualOptions = value;
164
- const signal = input(actualValue, {
83
+ const signal = require_signals.input(actualValue, {
165
84
  equals: actualOptions?.equals,
166
85
  watched: actualOptions?.watched,
167
86
  unwatched: actualOptions?.unwatched,
@@ -338,8 +257,8 @@ var BaseWebComponent = class extends HTMLElement {
338
257
  attributeChangedCallback(name, _oldValue, newValue) {
339
258
  const context = this;
340
259
  if (!(name in context)) throw new Error(`Attribute ${name} is not associated to any property`);
341
- if (!isInputSignal(context[name])) throw new Error(`Property ${name} is not an InputSignal`);
342
- context[name].set(newValue, INPUT_SIGNAL_SET_SYMBOL);
260
+ if (!require_signals.isInputSignal(context[name])) throw new Error(`Property ${name} is not an InputSignal`);
261
+ context[name].set(newValue, require_signals.INPUT_SIGNAL_SET_SYMBOL);
343
262
  }
344
263
  /**
345
264
  * Called by the browser engine each time the element is inserted into the DOM.
@@ -362,142 +281,6 @@ var BaseWebComponent = class extends HTMLElement {
362
281
  }
363
282
  };
364
283
  //#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
284
  //#region ../packages/core/src/utils/context.util.ts
502
285
  /**
503
286
  * Tracks identifier scope during run time template function execution
@@ -719,11 +502,11 @@ function createAnchor(label, parentNode, context, referenceNode = null) {
719
502
  function _for(parentNode, parentContext, condition, trackExpression, forFn) {
720
503
  const anchor = createAnchor("for", parentNode, parentContext);
721
504
  let entries = /* @__PURE__ */ new Map();
722
- const unlistener = effect(() => {
505
+ const unlistener = require_signals.effect(() => {
723
506
  const items = condition();
724
507
  const newKeys = items.map((item) => trackExpression(item));
725
508
  const newKeySet = new Set(newKeys);
726
- untracked(() => {
509
+ require_signals.untracked(() => {
727
510
  const newEntries = /* @__PURE__ */ new Map();
728
511
  for (const [key, entry] of entries) if (!newKeySet.has(key)) {
729
512
  entry.context.unlisten();
@@ -769,11 +552,11 @@ function _for(parentNode, parentContext, condition, trackExpression, forFn) {
769
552
  * @returns A handle exposing the resolved variables and an `update` function.
770
553
  */
771
554
  function _iterationVariables(context, items, index, itemName, aliases) {
772
- const $index = signal(index);
773
- const $first = signal(index === 0);
774
- const $last = signal(index === items.length - 1);
775
- const $even = signal(index % 2 === 0);
776
- const $odd = signal(index % 2 !== 0);
555
+ const $index = require_signals.signal(index);
556
+ const $first = require_signals.signal(index === 0);
557
+ const $last = require_signals.signal(index === items.length - 1);
558
+ const $even = require_signals.signal(index % 2 === 0);
559
+ const $odd = require_signals.signal(index % 2 !== 0);
777
560
  const retVal = {
778
561
  vars: {
779
562
  [itemName]: items[index],
@@ -831,7 +614,7 @@ function _if(parentNode, parentContext, blocks) {
831
614
  break;
832
615
  default: fn = (state) => handleIfElseIf(parentNode, parentContext, blocks, state, anchor);
833
616
  }
834
- const unlistener = effect(() => state = fn(state));
617
+ const unlistener = require_signals.effect(() => state = fn(state));
835
618
  parentContext.listen(unlistener);
836
619
  }
837
620
  /**
@@ -915,7 +698,7 @@ function checkAndUpdateState(parentNode, parentContext, state, newState, conditi
915
698
  state.context.unlisten();
916
699
  parentContext.removeChild(state.context);
917
700
  }
918
- const context = untracked(() => conditionalBlockFn(parentNode, parentContext, anchor));
701
+ const context = require_signals.untracked(() => conditionalBlockFn(parentNode, parentContext, anchor));
919
702
  parentContext.addChild(context);
920
703
  return {
921
704
  activeBranch: newState,
@@ -962,8 +745,8 @@ function _renderElement(parentNode, context, anchor, tagName, attributes, events
962
745
  const element = context.createElement(tagName);
963
746
  mountNode(element, parentNode, context, anchor);
964
747
  for (let i = 0; i < attributes.length; i++) {
965
- const { name, value, literal } = attributes[i];
966
- literal ? element.setAttribute(name, String(value())) : context.listen(effect(() => element.setAttribute(name, String(value()))));
748
+ const { name, value, reactive } = attributes[i];
749
+ reactive ? context.listen(require_signals.effect(() => element.setAttribute(name, String(value())))) : element.setAttribute(name, String(value()));
967
750
  }
968
751
  for (let i = 0; i < events.length; i++) {
969
752
  const event = events[i];
@@ -1017,7 +800,7 @@ function createMATHMLElement(tagName) {
1017
800
  function _renderText(parentNode, context, textFn) {
1018
801
  const node = document.createTextNode(textFn());
1019
802
  mountNode(node, parentNode, context);
1020
- context.listen(effect(() => node.textContent = textFn()));
803
+ context.listen(require_signals.effect(() => node.textContent = textFn()));
1021
804
  }
1022
805
  /**
1023
806
  * Creates a static (non-reactive) text node with a literal string value.
@@ -1065,4 +848,25 @@ function _switch(parentNode, parentContext, expression, blocks) {
1065
848
  })));
1066
849
  }
1067
850
  //#endregion
1068
- export { BaseWebComponent, Context, Event, Property, WebComponent, _for, _if, _iterationVariables, _renderElement, _renderLiteralText, _renderText, _switch, computed, createAnchor, createElement, createMATHMLElement, createSVGElement, effect, input, mountNode, signal, untracked };
851
+ exports.BaseWebComponent = BaseWebComponent;
852
+ exports.Context = Context;
853
+ exports.Event = Event;
854
+ exports.Property = Property;
855
+ exports.WebComponent = WebComponent;
856
+ exports._for = _for;
857
+ exports._if = _if;
858
+ exports._iterationVariables = _iterationVariables;
859
+ exports._renderElement = _renderElement;
860
+ exports._renderLiteralText = _renderLiteralText;
861
+ exports._renderText = _renderText;
862
+ exports._switch = _switch;
863
+ exports.computed = require_signals.computed;
864
+ exports.createAnchor = createAnchor;
865
+ exports.createElement = createElement;
866
+ exports.createMATHMLElement = createMATHMLElement;
867
+ exports.createSVGElement = createSVGElement;
868
+ exports.effect = require_signals.effect;
869
+ exports.input = require_signals.input;
870
+ exports.mountNode = mountNode;
871
+ exports.signal = require_signals.signal;
872
+ exports.untracked = require_signals.untracked;
package/package.json CHANGED
@@ -1,22 +1,28 @@
1
1
  {
2
2
  "name": "@xaendar/core",
3
- "version": "0.9.18",
3
+ "version": "0.9.22",
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.es.js",
8
- "module": "./dist/xaendar-core.es.js",
9
- "types": "./dist/xaendar-core.es.d.ts",
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.es.d.ts",
14
- "default": "./dist/xaendar-core.es.js"
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.18",
20
- "@xaendar/types": "0.9.18"
25
+ "@xaendar/signals": "0.9.22",
26
+ "@xaendar/types": "0.9.22"
21
27
  }
22
28
  }