easy-signal 3.0.3 → 3.0.4
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/{eventSignal.js → dist/eventSignal.js} +1 -0
- package/dist/eventSignal.js.map +1 -0
- package/{index.js → dist/index.js} +1 -0
- package/dist/index.js.map +1 -0
- package/{reactiveSignal.js → dist/reactiveSignal.js} +1 -0
- package/dist/reactiveSignal.js.map +1 -0
- package/{signalStore.js → dist/signalStore.js} +1 -0
- package/dist/signalStore.js.map +1 -0
- package/package.json +6 -3
- package/.gitattributes +0 -2
- package/.prettierrc.cjs +0 -8
- package/.vscode/settings.json +0 -18
- package/eventSignal.ts +0 -74
- package/index.ts +0 -3
- package/reactiveSignal.ts +0 -311
- package/signalStore.ts +0 -14
- package/tsconfig.json +0 -16
- /package/{eventSignal.d.ts → dist/eventSignal.d.ts} +0 -0
- /package/{index.d.ts → dist/index.d.ts} +0 -0
- /package/{reactiveSignal.d.ts → dist/reactiveSignal.d.ts} +0 -0
- /package/{signalStore.d.ts → dist/signalStore.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventSignal.js","sourceRoot":"","sources":["../src/eventSignal.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;IAExD,SAAS,QAAQ,CAAC,UAA+B,EAAE,IAAuB;QACxE,MAAM,SAAS,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC;QACpE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1B,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC,CAAC;IACJ,CAAC;IAQD,SAAS,MAAM,CAAC,GAAG,IAAW;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;YAC7B,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;SACtB;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE;YAC9B,WAAW,CAAC,KAAK,EAAE,CAAC;YACpB,cAAc,CAAC,KAAK,EAAE,CAAC;SACxB;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE;YAC9B,OAAO,QAAuB,CAAC;SAChC;aAAM,IAAI,GAAG,YAAY,KAAK,EAAE;YAC/B,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;SACnD;aAAM;YACL,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;SACpD;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactiveSignal.js","sourceRoot":"","sources":["../src/reactiveSignal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signalStore.js","sourceRoot":"","sources":["../src/signalStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvF;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAI,MAAyB;IACtD,OAAO;QACL,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,MAAM;QACX,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,CAAC,GAAgC,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;KACxE,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "easy-signal",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "A tiny (25 LOC), simple utility for alerting subscribers when an event happens, allowing for error handling and clearing.",
|
|
5
|
-
"
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"main": "dist/index.js",
|
|
6
9
|
"scripts": {
|
|
7
10
|
"build": "tsc",
|
|
8
|
-
"
|
|
11
|
+
"watch": "tsc --watch",
|
|
9
12
|
"prepublishOnly": "tsc"
|
|
10
13
|
},
|
|
11
14
|
"repository": {
|
package/.gitattributes
DELETED
package/.prettierrc.cjs
DELETED
package/.vscode/settings.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"[typescript]": {
|
|
3
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
4
|
-
},
|
|
5
|
-
"[json]": {
|
|
6
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
7
|
-
},
|
|
8
|
-
"eslint.format.enable": true,
|
|
9
|
-
"editor.codeActionsOnSave": {
|
|
10
|
-
"source.organizeImports": "explicit"
|
|
11
|
-
},
|
|
12
|
-
"editor.formatOnSave": true,
|
|
13
|
-
"eslint.validate": [
|
|
14
|
-
"javascript",
|
|
15
|
-
"javascriptreact",
|
|
16
|
-
"svelte"
|
|
17
|
-
]
|
|
18
|
-
}
|
package/eventSignal.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
type Args<T> = T extends (...args: infer A) => any ? A : never;
|
|
2
|
-
export type EventSignalSubscriber = (...args: any[]) => any;
|
|
3
|
-
export type ErrorSubscriber = (error: Error) => any;
|
|
4
|
-
export type Unsubscriber = () => void;
|
|
5
|
-
|
|
6
|
-
export type OnSignal<T extends EventSignalSubscriber = EventSignalSubscriber> = {
|
|
7
|
-
(subscriber: T): Unsubscriber;
|
|
8
|
-
(errorListener: ErrorSubscriber, what: typeof ForErrors): Unsubscriber;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type EventSignal<T extends EventSignalSubscriber = EventSignalSubscriber> = OnSignal<T> & {
|
|
12
|
-
(...args: Args<T>): void;
|
|
13
|
-
(data: Error): void;
|
|
14
|
-
(data: typeof ClearSignal): void;
|
|
15
|
-
(data: typeof GetOnSignal): OnSignal<T>;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const ClearSignal = Symbol();
|
|
19
|
-
export const GetOnSignal = Symbol();
|
|
20
|
-
export const ForErrors = Symbol();
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Creates a signal, a function that can be used to subscribe to events. The signal can be called with a subscriber
|
|
24
|
-
* function, which will be called when the signal is dispatched. The signal can also be called with data, which will
|
|
25
|
-
* dispatch to all subscribers. An optional second argument can be passed to subscribe to errors instead. When the
|
|
26
|
-
* signal is called with an instance of Error, it will dispatch to all error listeners.
|
|
27
|
-
* The signal can also be called with `ClearSignal`, which will clear all subscribers.
|
|
28
|
-
* @example
|
|
29
|
-
* const onLoad = signal();
|
|
30
|
-
*
|
|
31
|
-
* // Subscribe to data
|
|
32
|
-
* onLoad((data) => console.log('loaded', data));
|
|
33
|
-
* onLoad((error) => console.error('error', error), true);
|
|
34
|
-
*
|
|
35
|
-
* // Dispatch data
|
|
36
|
-
* onLoad('data'); // logs 'loaded data'
|
|
37
|
-
* onLoad(new Error('error')); // logs 'error Error: error'
|
|
38
|
-
*/
|
|
39
|
-
export function eventSignal<T extends EventSignalSubscriber = EventSignalSubscriber>(): EventSignal<T> {
|
|
40
|
-
const subscribers = new Set<EventSignalSubscriber>();
|
|
41
|
-
const errorListeners = new Set<EventSignalSubscriber>();
|
|
42
|
-
|
|
43
|
-
function onSignal(subscriber: T | ErrorSubscriber, what?: typeof ForErrors): Unsubscriber {
|
|
44
|
-
const listeners = what === ForErrors ? errorListeners : subscribers;
|
|
45
|
-
listeners.add(subscriber);
|
|
46
|
-
return () => {
|
|
47
|
-
listeners.delete(subscriber);
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function signal(...args: Args<T>): void;
|
|
52
|
-
function signal(error: Error): void;
|
|
53
|
-
function signal(data: typeof ClearSignal): void;
|
|
54
|
-
function signal(data: typeof GetOnSignal): OnSignal<T>;
|
|
55
|
-
function signal(subscriber: T): Unsubscriber;
|
|
56
|
-
function signal(errorListener: EventSignalSubscriber, what: typeof ForErrors): Unsubscriber;
|
|
57
|
-
function signal(...args: any[]): Unsubscriber | OnSignal<T> | void {
|
|
58
|
-
const arg = args[0];
|
|
59
|
-
if (typeof arg === 'function') {
|
|
60
|
-
return onSignal(arg);
|
|
61
|
-
} else if (arg === ClearSignal) {
|
|
62
|
-
subscribers.clear();
|
|
63
|
-
errorListeners.clear();
|
|
64
|
-
} else if (arg === GetOnSignal) {
|
|
65
|
-
return onSignal as OnSignal<T>;
|
|
66
|
-
} else if (arg instanceof Error) {
|
|
67
|
-
errorListeners.forEach(listener => listener(arg));
|
|
68
|
-
} else {
|
|
69
|
-
subscribers.forEach(listener => listener(...args));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return signal;
|
|
74
|
-
}
|
package/index.ts
DELETED
package/reactiveSignal.ts
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
// The options for a Signal
|
|
2
|
-
export interface SignalOptions<T> {
|
|
3
|
-
equals?: false | ((prev: T, next: T) => boolean);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// The types for an unsubscribe and cancel function
|
|
7
|
-
export type Unsubscribe = () => void;
|
|
8
|
-
export type Cancel = () => void;
|
|
9
|
-
|
|
10
|
-
// Different timings for when to execute an observer observing a signal
|
|
11
|
-
export const Timing = {
|
|
12
|
-
// Execute the function on the next tick of the event loop
|
|
13
|
-
Tick: (fn: () => void) => {
|
|
14
|
-
Promise.resolve(fn);
|
|
15
|
-
},
|
|
16
|
-
// Execute the function on the next animation frame
|
|
17
|
-
AnimationFrame: (fn: () => void) => {
|
|
18
|
-
(globalThis as any).requestAnimationFrame(fn);
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// The context for the current run and its unsubscribes
|
|
23
|
-
let context: { subscriber: ReactiveSignalSubscriber<any>; unsubscribes: Set<Unsubscribe> } | null = null;
|
|
24
|
-
|
|
25
|
-
// A map to keep track of listeners to subscription changes
|
|
26
|
-
const onSubscriptionChanges = new WeakMap<ReactiveSignal<any>, Set<SubscriptionChange>>();
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A Signal is a single getter/setter function that holds a value and notifies subscribers when the value changes
|
|
30
|
-
* The signal function can be called with no arguments to get the current value, with a function argument to run an
|
|
31
|
-
* update function which should receive the value and return a new one, or with a value argument which will replace the
|
|
32
|
-
* signal's current value. The signal function always returns the current value.
|
|
33
|
-
*
|
|
34
|
-
* The optional second argument, `set`, can be used to force the first argument as the new value. This is useful when
|
|
35
|
-
* the first argument is a function or `undefined` since the signal will assume any function is an updater function and
|
|
36
|
-
* any `undefined` value is a request to get the current value.
|
|
37
|
-
*/
|
|
38
|
-
export type ReactiveSignal<T> = {
|
|
39
|
-
(): T;
|
|
40
|
-
(value: T | ReactiveSignalUpdater<T>, set?: false): T;
|
|
41
|
-
(value: T, set: true): T;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* A Computed Signal is a signal that is the result of a function that depends on other signals. The function is called
|
|
46
|
-
* whenever the computed signal is accessed if there are no subscribers, or whenever its dependent signals change if
|
|
47
|
-
* there are subscribers so that subscribers to the computed signal can be informed.
|
|
48
|
-
*/
|
|
49
|
-
export type ComputedSignal<T> = () => T;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* A Signal Subscriber is a function that will be called whenever the signal's value changes. The subscriber will be
|
|
53
|
-
* called with the new value. The subscriber can be used to update the DOM or trigger other side effects.
|
|
54
|
-
*/
|
|
55
|
-
export type ReactiveSignalSubscriber<T> = (value: T) => void;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* A Signal Updater is a function that will be called with the current value of the signal and should return a new
|
|
59
|
-
* value. The updater can be used to update the signal's value based on its current value.
|
|
60
|
-
*/
|
|
61
|
-
export type ReactiveSignalUpdater<T> = (prev: T) => T;
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* An Observer is a function that will be called whenever any of the signals it depends on change. The observer can be
|
|
65
|
-
* used to update the DOM or trigger other side effects.
|
|
66
|
-
* The observer will be called immediately (or after certain a timing option) and whenever any of the signals it depends
|
|
67
|
-
* on change.
|
|
68
|
-
*/
|
|
69
|
-
export type ReactiveSignalObserver = () => void;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* A Timing is a function that will be called with a function to execute. The timing function should execute the passed
|
|
73
|
-
* function at some point in the future. The default timing is `Timing.Immediate` which executes the function
|
|
74
|
-
* immediately.
|
|
75
|
-
*/
|
|
76
|
-
export type Timing = (fn: () => void) => void;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* A Subscription Change is a function that will be called whenever the signal's subscribers changes from none to some
|
|
80
|
-
* or some to none. The subscription change will be called with a boolean indicating whether there are any subscribers.
|
|
81
|
-
*/
|
|
82
|
-
export type SubscriptionChange = (hasSubscribers: boolean) => void;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Create a Signal with an initial value and optional options. The options can include an `equals` function which will
|
|
86
|
-
* be used to determine if the new value is different from the current value. If the new value is different, the signal
|
|
87
|
-
* will be updated and all subscribers will be notified.
|
|
88
|
-
* The returned signal function can be called with no arguments to get the current value, with a function argument to
|
|
89
|
-
* run an update function which should receive the value and return a new one, or with a value argument which will
|
|
90
|
-
* replace the signal's current value. The signal function always returns the current value.
|
|
91
|
-
*/
|
|
92
|
-
export function reactiveSignal<T>(value: T, options?: SignalOptions<T>): ReactiveSignal<T> {
|
|
93
|
-
// A map to keep track of subscribers
|
|
94
|
-
const subscribers = new Map<ReactiveSignalSubscriber<T>, Unsubscribe>();
|
|
95
|
-
|
|
96
|
-
// The signal is a function that will return a value when called without arguments, or update the value when called
|
|
97
|
-
// with an argument. The update value can be a new value or an updater function.
|
|
98
|
-
const signal = ((newValue?: T | ReactiveSignalUpdater<T>, set?: boolean) => {
|
|
99
|
-
// If no new value is provided, subscribe the current run to this signal and return the current value
|
|
100
|
-
if (!set && newValue === undefined) {
|
|
101
|
-
// If there is a context (an observer is running), add the observer's subscriber to the signal
|
|
102
|
-
if (context) {
|
|
103
|
-
const { subscriber: run, unsubscribes } = context;
|
|
104
|
-
let unsubscribe = subscribers.get(run);
|
|
105
|
-
|
|
106
|
-
// If the run is not already subscribed, subscribe it
|
|
107
|
-
if (!unsubscribe) {
|
|
108
|
-
// Create the unsubscribe function
|
|
109
|
-
unsubscribe = () => {
|
|
110
|
-
subscribers.delete(run);
|
|
111
|
-
|
|
112
|
-
// If there are no more subscribers, notify the subscription changes
|
|
113
|
-
if (subscribers.size === 0) {
|
|
114
|
-
const onChanges = onSubscriptionChanges.get(signal);
|
|
115
|
-
if (onChanges) onChanges.forEach(onChange => onChange(false));
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// Add the unsubscribe function to the signal's subscribers
|
|
120
|
-
subscribers.set(run, unsubscribe);
|
|
121
|
-
|
|
122
|
-
// If this changed the number of subscribers from 0 to 1, notify any subscription change subscribers
|
|
123
|
-
if (subscribers.size === 1) {
|
|
124
|
-
const onChanges = onSubscriptionChanges.get(signal);
|
|
125
|
-
if (onChanges) onChanges.forEach(onChange => onChange(true));
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Add the unsubscribe function to the run's unsubscribes
|
|
130
|
-
unsubscribes.add(unsubscribe);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Return the current value
|
|
134
|
-
return value;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// If the new value is a function, call it with the current value as an argument
|
|
138
|
-
if (!set && typeof newValue === 'function') {
|
|
139
|
-
newValue = (newValue as ReactiveSignalUpdater<T>)(value);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// If the new value is different from the current value (according to the equals function if provided), update the
|
|
143
|
-
// value and notify all subscribers
|
|
144
|
-
if (options?.equals ? !options.equals(value!, newValue as T) : value !== newValue) {
|
|
145
|
-
value = newValue as T;
|
|
146
|
-
subscribers.forEach((_, run) => run(value!));
|
|
147
|
-
}
|
|
148
|
-
return value;
|
|
149
|
-
}) as ReactiveSignal<T>;
|
|
150
|
-
|
|
151
|
-
// Return the signal function
|
|
152
|
-
return signal;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Subscribe to be notified whenever a Signal's value changes. The Subscriber function will be called immediately with
|
|
157
|
-
* the current value of the Signal and again whenever the Signal's value changes.
|
|
158
|
-
*
|
|
159
|
-
* The optional third argument, `timing`, can be used to specify when the function should be called. The default is
|
|
160
|
-
* `Timing.Immediate` which executes the function immediately.
|
|
161
|
-
*
|
|
162
|
-
* The returned function can be called to unsubscribe from the Signal.
|
|
163
|
-
*/
|
|
164
|
-
export function subscribe<T>(
|
|
165
|
-
signal: ReactiveSignal<T>,
|
|
166
|
-
subscriber: ReactiveSignalSubscriber<T>,
|
|
167
|
-
timing: Timing | null = Timing.Tick
|
|
168
|
-
): Unsubscribe {
|
|
169
|
-
if (timing) {
|
|
170
|
-
let queued = false;
|
|
171
|
-
const subFn = subscriber;
|
|
172
|
-
subscriber = () => {
|
|
173
|
-
if (!queued) {
|
|
174
|
-
queued = true;
|
|
175
|
-
timing(() => {
|
|
176
|
-
queued = false;
|
|
177
|
-
subFn(signal());
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Set the current context so we can get the unsubscribe
|
|
184
|
-
context = { subscriber, unsubscribes: new Set() };
|
|
185
|
-
|
|
186
|
-
// Get the current value of the signal
|
|
187
|
-
const value = signal();
|
|
188
|
-
|
|
189
|
-
// Get the unsubscribe function for the subscriber
|
|
190
|
-
const unsubscribe = context.unsubscribes.values().next().value;
|
|
191
|
-
|
|
192
|
-
// Clear the current context
|
|
193
|
-
context = null;
|
|
194
|
-
|
|
195
|
-
// Call the subscriber with the current value
|
|
196
|
-
subscriber(value);
|
|
197
|
-
|
|
198
|
-
// Return the unsubscribe function
|
|
199
|
-
return unsubscribe;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Get notified when a Signal's subscribers changes from none to some or some to none.
|
|
204
|
-
*/
|
|
205
|
-
export function onSubscriptionChange(
|
|
206
|
-
signal: ReactiveSignal<any>,
|
|
207
|
-
onChange: (hasSubscribers: boolean) => void
|
|
208
|
-
): Unsubscribe {
|
|
209
|
-
// Get the set of onChange functions for the signal
|
|
210
|
-
let onChanges = onSubscriptionChanges.get(signal);
|
|
211
|
-
|
|
212
|
-
// If there is no set, create one and add it to the map
|
|
213
|
-
if (!onChanges) onSubscriptionChanges.set(signal, (onChanges = new Set()));
|
|
214
|
-
|
|
215
|
-
// Add the onChange function to the set
|
|
216
|
-
onChanges.add(onChange);
|
|
217
|
-
|
|
218
|
-
// Return a function that removes the onChange function from the set
|
|
219
|
-
return () => {
|
|
220
|
-
onChanges!.delete(onChange);
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Calls an Observer function after Timing amount of time (default is immediate, but can be on the next tick or the next
|
|
226
|
-
* animation frame) and again after Timing whenever any of the signals it depends on change.
|
|
227
|
-
* The Observer function will be called immediately (or after the timing) and again whenever any of the signals it
|
|
228
|
-
* depends on change.
|
|
229
|
-
* The returned function can be called to unsubscribe from the signals that are called when the effect is run.
|
|
230
|
-
*
|
|
231
|
-
* The optional second argument, `timing`, can be used to specify when the function should be called. The default is
|
|
232
|
-
* undefined which executes the function immediately.
|
|
233
|
-
*/
|
|
234
|
-
export function observe(fn: ReactiveSignalObserver, timing?: Timing): Unsubscribe {
|
|
235
|
-
let dirty = true;
|
|
236
|
-
let unsubscribes = new Set<Unsubscribe>();
|
|
237
|
-
|
|
238
|
-
// Subscribe to all the signals that are called when the effect is run
|
|
239
|
-
const subscriber = () => {
|
|
240
|
-
if (dirty) return;
|
|
241
|
-
dirty = true;
|
|
242
|
-
if (timing) timing(() => onChange());
|
|
243
|
-
else onChange();
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// Called immediately and whenever any of the signals it depends on change (after the timing)
|
|
247
|
-
const onChange = () => {
|
|
248
|
-
if (!dirty) return;
|
|
249
|
-
dirty = false;
|
|
250
|
-
|
|
251
|
-
// Set the context for the effect
|
|
252
|
-
context = { subscriber, unsubscribes: new Set() };
|
|
253
|
-
|
|
254
|
-
// Run the effect collecting all the unsubscribes from the signals that are called when it is run
|
|
255
|
-
fn();
|
|
256
|
-
|
|
257
|
-
// Filter out unchanged unsubscribes, leaving only those which no longer apply
|
|
258
|
-
context.unsubscribes.forEach(u => unsubscribes.delete(u));
|
|
259
|
-
|
|
260
|
-
// Unsubscribe from all the signals that are no longer needed
|
|
261
|
-
unsubscribes.forEach(u => u());
|
|
262
|
-
|
|
263
|
-
// Set the new unsubscribes
|
|
264
|
-
unsubscribes = context.unsubscribes;
|
|
265
|
-
|
|
266
|
-
// Clear the context
|
|
267
|
-
context = null;
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// Call immediately (or on the next timing)
|
|
271
|
-
if (timing) timing(() => onChange());
|
|
272
|
-
else onChange();
|
|
273
|
-
|
|
274
|
-
// Return a function that unsubscribes from all the signals that are called when the effect is run
|
|
275
|
-
return () => unsubscribes.forEach(u => u());
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Create a Computed Signal which is a signal that is the result of a function that depends on other signals. The
|
|
280
|
-
* function is called immediately whenever the computed signal is accessed if there are no subscribers, or whenever its
|
|
281
|
-
* dependent signals change if there are subscribers so that subscribers to the computed signal can be informed.
|
|
282
|
-
*
|
|
283
|
-
* The optional second argument, `when`, can be used to specify when updater function should be called. The default is
|
|
284
|
-
* undefined which executes the function immediately after any change to any signal it relies on. This can
|
|
285
|
-
* prevent unnecessary updates if the function is expensive to run.
|
|
286
|
-
*/
|
|
287
|
-
export function computedSignal<T>(fn: ReactiveSignalUpdater<T>, when?: Timing): ComputedSignal<T> {
|
|
288
|
-
// Create the signal
|
|
289
|
-
const signal = reactiveSignal<T>(undefined as T);
|
|
290
|
-
|
|
291
|
-
// Store the unsubscribe function from the observer. We will only observe the function when there are subscribers to
|
|
292
|
-
// this computed signal.
|
|
293
|
-
let unsubscribe: Unsubscribe | null = null;
|
|
294
|
-
|
|
295
|
-
// Subscribe to the signal's subscription changes so we know when to start and stop observing
|
|
296
|
-
onSubscriptionChange(signal, hasSubscribers => {
|
|
297
|
-
// If there are subscribers, start observing the function
|
|
298
|
-
if (hasSubscribers) {
|
|
299
|
-
if (!unsubscribe) unsubscribe = observe(() => signal(fn), when);
|
|
300
|
-
} else if (unsubscribe) {
|
|
301
|
-
// If there are no subscribers, stop observing the function
|
|
302
|
-
unsubscribe();
|
|
303
|
-
unsubscribe = null;
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
const computed = () => (unsubscribe ? signal() : signal(fn));
|
|
308
|
-
|
|
309
|
-
// Return the signal
|
|
310
|
-
return computed;
|
|
311
|
-
}
|
package/signalStore.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ReactiveSignal, ReactiveSignalSubscriber, subscribe } from './reactiveSignal';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A store wrapper around a reactive signal. The store can be used to get, set, update, and subscribe to the signal.
|
|
5
|
-
* This is for use in Svelte 3-4.
|
|
6
|
-
*/
|
|
7
|
-
export function signalStore<T>(signal: ReactiveSignal<T>) {
|
|
8
|
-
return {
|
|
9
|
-
get: signal,
|
|
10
|
-
set: signal,
|
|
11
|
-
update: signal,
|
|
12
|
-
subscribe: (sub: ReactiveSignalSubscriber<T>) => subscribe(signal, sub),
|
|
13
|
-
};
|
|
14
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2021",
|
|
4
|
-
"declaration": true,
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"allowJs": true,
|
|
8
|
-
"allowSyntheticDefaultImports": true,
|
|
9
|
-
"isolatedModules": true,
|
|
10
|
-
"lib": [
|
|
11
|
-
"es2021"
|
|
12
|
-
],
|
|
13
|
-
"resolveJsonModule": true
|
|
14
|
-
},
|
|
15
|
-
"exclude": ["node_modules"]
|
|
16
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|