memlnaut-nisps/playground/js/shapeseq/signal.js

55 lines
1.2 KiB
JavaScript
Raw Normal View History

/**
* Minimal signal/observable for reactive UI updates.
* No framework dependency. ~40 lines.
*
* @module shapeseq/signal
*/
export function createSignal(initialValue) {
let value = initialValue;
const subscribers = new Set();
function get() { return value; }
function set(newValue) {
if (newValue === value) return;
value = newValue;
for (const fn of subscribers) fn(value);
}
function subscribe(fn) {
subscribers.add(fn);
return () => subscribers.delete(fn);
}
return { get, set, subscribe };
}
/**
* Signal backed by a Float32Array for param vectors.
* Subscribers are called when any element changes.
*/
export function createArraySignal(length) {
const value = new Float32Array(length);
const subscribers = new Set();
function get() { return value; }
function update(newArray) {
let changed = false;
for (let i = 0; i < value.length && i < newArray.length; i++) {
if (value[i] !== newArray[i]) { value[i] = newArray[i]; changed = true; }
}
if (changed) {
for (const fn of subscribers) fn(value);
}
}
function subscribe(fn) {
subscribers.add(fn);
return () => subscribers.delete(fn);
}
return { get, update, subscribe };
}