first commit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @wrnexus/reactive — tiny reactive primitives.
|
||||
*/
|
||||
export type { Signal, Subscriber, Unsubscribe } from "./signal.ts";
|
||||
export { signal } from "./signal.ts";
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* A minimal, type-safe reactive signal with zero dependencies.
|
||||
*
|
||||
* This is the seed of the framework's reactivity. Today it powers nothing on
|
||||
* its own, but it is shaped so client islands (and later the `.wrn` compiler's
|
||||
* `state` blocks) can build reactive bindings on top of it.
|
||||
*
|
||||
* const count = signal(0)
|
||||
* count.get() // 0
|
||||
* count.set(1) // notifies subscribers
|
||||
* const off = count.subscribe(v => console.log(v))
|
||||
* off() // unsubscribe
|
||||
*/
|
||||
|
||||
export type Subscriber<T> = (value: T) => void;
|
||||
export type Unsubscribe = () => void;
|
||||
|
||||
export interface Signal<T> {
|
||||
/** Read the current value. */
|
||||
get(): T;
|
||||
/** Write a new value; subscribers run only when the value actually changes. */
|
||||
set(next: T): void;
|
||||
/** Apply a function to the current value. */
|
||||
update(fn: (current: T) => T): void;
|
||||
/** Subscribe to changes; returns an unsubscribe function. */
|
||||
subscribe(fn: Subscriber<T>): Unsubscribe;
|
||||
}
|
||||
|
||||
export function signal<T>(initial: T): Signal<T> {
|
||||
let value = initial;
|
||||
const subscribers = new Set<Subscriber<T>>();
|
||||
|
||||
return {
|
||||
get(): T {
|
||||
return value;
|
||||
},
|
||||
set(next: T): void {
|
||||
if (Object.is(next, value)) return; // skip no-op updates
|
||||
value = next;
|
||||
// Iterate a copy so a subscriber may unsubscribe during notification.
|
||||
for (const fn of [...subscribers]) fn(value);
|
||||
},
|
||||
update(fn: (current: T) => T): void {
|
||||
this.set(fn(value));
|
||||
},
|
||||
subscribe(fn: Subscriber<T>): Unsubscribe {
|
||||
subscribers.add(fn);
|
||||
return () => {
|
||||
subscribers.delete(fn);
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user