asciitorium
Version:
an ASCII CLUI framework
108 lines (107 loc) • 3 kB
JavaScript
/**
* Reactive state management class for asciitorium components.
*
* Provides a simple publish-subscribe pattern that notifies listeners
* whenever the state value changes. Subscribers are immediately notified
* upon registration with the current value.
*
* This class forms the foundation of asciitorium's reactive system, enabling
* components to automatically re-render when their dependencies change.
*
* @example
* Basic usage with primitive values:
* ```tsx
* const count = new State(0);
* count.subscribe((value) => console.log('Count:', value)); // Logs: "Count: 0"
* count.value = 42; // Logs: "Count: 42"
* ```
*
* @example
* Using with components:
* ```tsx
* const message = new State('Hello');
*
* const text = (
* <Text width={20} height={3}>
* {message}
* </Text>
* );
*
* message.value = 'World'; // Component automatically updates
* ```
*
* @typeParam T - The type of value stored in the state
*/
export class State {
/**
* Creates a new State instance with an initial value.
*
* @param initialValue - The initial value for the state
*/
constructor(initialValue) {
this.listeners = [];
this._value = initialValue;
}
/**
* Gets the current state value.
*
* @returns The current value
*/
get value() {
return this._value;
}
/**
* Sets a new state value and notifies all subscribers if the value changed.
*
* Only triggers notifications if the new value is different from the current
* value (using strict equality comparison).
*
* @param newValue - The new value to set
*/
set value(newValue) {
if (this._value !== newValue) {
this._value = newValue;
this.listeners.forEach((listener) => listener(newValue));
}
}
/**
* Subscribes to state changes.
*
* The callback function will be invoked immediately with the current value,
* and again whenever the state value changes.
*
* @param fn - Callback function to invoke on state changes
*
* @example
* ```tsx
* const state = new State(5);
* state.subscribe((value) => {
* console.log('Value changed to:', value);
* });
* ```
*/
subscribe(fn) {
this.listeners.push(fn);
// Immediately notify on subscribe
fn(this._value);
}
/**
* Unsubscribes from state changes.
*
* Removes the specified callback function from the list of subscribers.
* The function will no longer be called when the state changes.
*
* @param fn - The callback function to remove
*
* @example
* ```tsx
* const state = new State(10);
* const handler = (value) => console.log(value);
* state.subscribe(handler);
* state.unsubscribe(handler); // Stop listening
* ```
*/
unsubscribe(fn) {
this.listeners = this.listeners.filter((l) => l !== fn);
}
}