/**
 * Drives the open/close lifecycle of a slide-out panel inside a component's
 * shadow root, with a tracked close timer instead of an `animationend`
 * listener so the panel cannot wedge open if it's unmounted mid-animation
 * (pop-in/pop-out, dock change, host disconnect).
 *
 * @internal
 */
export class AnimatedPanelToggle {
    constructor(host, selector, closeDurationMs, getOpen, setOpen) {
        this.host = host;
        this.selector = selector;
        this.closeDurationMs = closeDurationMs;
        this.getOpen = getOpen;
        this.setOpen = setOpen;
    }
    queryPanel() {
        var _a;
        return (_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(this.selector);
    }
    toggle() {
        var _a;
        if (this.getOpen()) {
            // Capture the panel reference now so the timer callback strips
            // `closing` from the same node, regardless of any later remounts.
            // Leftover `closing` is what breaks the next open: with
            // `animation-fill-mode: forwards` the slide-out keyframe pins the panel
            // to opacity 0, so a remount looks like a no-op.
            const panel = this.queryPanel();
            panel === null || panel === void 0 ? void 0 : panel.classList.add('closing');
            if (this.timer != null)
                clearTimeout(this.timer);
            this.timer = setTimeout(() => {
                this.timer = undefined;
                panel === null || panel === void 0 ? void 0 : panel.classList.remove('closing');
                this.setOpen(false);
            }, this.closeDurationMs);
        }
        else {
            // Re-opened mid-close: cancel the pending flip and strip the closing
            // class so the panel snaps back to the open state.
            if (this.timer != null) {
                clearTimeout(this.timer);
                this.timer = undefined;
                (_a = this.queryPanel()) === null || _a === void 0 ? void 0 : _a.classList.remove('closing');
            }
            this.setOpen(true);
        }
    }
    /**
     * Synchronously finalise an in-flight close — call from
     * `disconnectedCallback` so the closed state lands in the store before any
     * session ref is cleared.
     */
    finalize() {
        if (this.timer == null)
            return;
        clearTimeout(this.timer);
        this.timer = undefined;
        this.setOpen(false);
    }
}
