/**
 * Framework-agnostic store for thread item selection.
 *
 * Implements the `useSyncExternalStore` contract identical to
 * {@link ConversationStore} and `WorkflowExecutionEventStore`.
 *
 * **Render isolation strategy:** consumers subscribe to a
 * per-item boolean via `isSelected(id)`, so only the previously-
 * and newly-selected leaves re-render on a selection change (≤2).
 *
 * The context carries the **store instance (stable ref)**, not the
 * value — so the context provider never triggers consumer re-renders.
 */
export class SelectionStore {
    _selected = null;
    _listeners = new Set();
    // -- Mutations -----------------------------------------------------------
    select(item) {
        if (selectedEqual(this._selected, item))
            return;
        this._selected = item;
        this._notify();
    }
    deselect() {
        if (this._selected === null)
            return;
        this._selected = null;
        this._notify();
    }
    toggle(item) {
        if (selectedEqual(this._selected, item)) {
            this.deselect();
        }
        else {
            this.select(item);
        }
    }
    // -- useSyncExternalStore contract ---------------------------------------
    subscribe = (listener) => {
        this._listeners.add(listener);
        return () => {
            this._listeners.delete(listener);
        };
    };
    /** Returns the full selection object (for the InspectTab). */
    getSelection = () => {
        return this._selected;
    };
    /**
     * Per-item boolean selector. Each selectable leaf calls this inside
     * `useSyncExternalStore` so it only re-renders when its own
     * selected state changes.
     */
    isSelected = (kind, id) => {
        if (this._selected === null)
            return false;
        return this._selected.kind === kind && itemId(this._selected) === id;
    };
    // -- Internal ------------------------------------------------------------
    _notify() {
        for (const listener of this._listeners) {
            listener();
        }
    }
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function itemId(item) {
    switch (item.kind) {
        case "tool-call":
            return item.toolCallId;
        case "sub-agent":
            return item.subAgentId;
        case "artifact":
            return item.artifactKey;
        case "write-back":
            return item.workspaceEntryName;
    }
}
function selectedEqual(a, b) {
    if (a === b)
        return true;
    if (a === null || b === null)
        return false;
    return a.kind === b.kind && itemId(a) === itemId(b);
}
//# sourceMappingURL=selection-store.js.map