// #region Imports
// #endregion
/**
 * Singleton manager for current effect, to avoid mutable global state.
 *
 * @private
 */
class SignalManager {
    static _currentEffect = null;
    static setCurrentEffect(e) {
        this._currentEffect = e;
    }
    static getCurrentEffect() {
        return this._currentEffect;
    }
}
/**
 * Implementation of writable signal with private listeners and strong typing.
 *
 * @public
 */
export class Signal {
    // #region Fields
    _listeners;
    _value;
    // #endregion
    // #region Constructor
    constructor(initialValue) {
        this._value = initialValue;
        this._listeners = new Set();
    }
    // #endregion
    // #region Public Methods
    /**
     * Factory method for creating a new Signal instance.
     * @param value Initial value of the signal.
     */
    static from(value) {
        return new Signal(value);
    }
    /**
     * Returns the current value, adding the current effect to listeners if it exists.
     */
    get() {
        const e = SignalManager.getCurrentEffect();
        if (e) {
            this._listeners.add(e);
        }
        return this._value;
    }
    /**
     * Sets a new value for the signal and notifies all listeners if value has changed.
     * @param next - The new value to set.
     */
    set(next) {
        if (this._value !== next) {
            this._value = next;
            this._notifyListeners(next);
        }
    }
    /**
     * Updates the value using an update function and notifies listeners.
     * @param updateFn Function that receives the current value and returns a new value.
     */
    update(updateFn) {
        this.set(updateFn(this.get()));
    }
    /**
     * Returns a readonly version of this signal.
     */
    asReadonly() {
        return { get: () => this.get() };
    }
    /**
     * Subscribes a function to be called on value changes.
     * @param fn Function to call on updates.
     * @returns A function to unsubscribe.
     */
    subscribe(fn) {
        const e = SignalManager.getCurrentEffect();
        if (e) {
            this._listeners.add(e);
        }
        this._listeners.add(fn);
        return () => this._listeners.delete(fn);
    }
    // #endregion
    // #region Private Methods
    /**
     * Notifies all subscribed listeners of the new value.
     * @param next - The new value to notify listeners with.
     */
    _notifyListeners(next) {
        this._listeners.forEach((listener) => listener(next));
    }
}
/**
 * Wraps an effect function to manage the SignalManager’s current effect.
 * @param fn Effect function to be executed.
 * @public
 */
export function effect(fn) {
    SignalManager.setCurrentEffect(fn);
    fn();
    SignalManager.setCurrentEffect(null);
}
//# sourceMappingURL=Signal.js.map