55 lines
1.2 KiB
JavaScript
55 lines
1.2 KiB
JavaScript
|
|
/**
|
||
|
|
* 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 };
|
||
|
|
}
|