first commit

This commit is contained in:
2026-07-12 15:55:18 +05:30
commit ee98026cc5
404 changed files with 44522 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
/**
* @wrnexus/reactive — tiny reactive primitives.
*/
export type { Signal, Subscriber, Unsubscribe } from "./signal.ts";
export { signal } from "./signal.ts";
+53
View File
@@ -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);
};
},
};
}