import RevealStateManager from './RevealStateManager.js';
export class AxRevealProvider extends HTMLElement {
    constructor() {
        super(...arguments);
        this.stateManager = new RevealStateManager();
    }
}
AxRevealProvider.ElementName = 'ax-reveal-provider';
export class AxRevealBoundary extends HTMLElement {
    constructor() {
        super(...arguments);
        this.updatePointerPosition = (ev) => {
            this.waitForStorage(storage => {
                storage.clientX = ev.clientX;
                storage.clientY = ev.clientY;
            });
        };
        this.handlePointerEnter = () => this.waitForStorage(storage => storage.onPointerEnterBoundary());
        this.handlePointerLeave = () => this.waitForStorage(storage => storage.onPointerLeaveBoundary());
        this.handlePointerMove = (ev) => this.updatePointerPosition(ev);
        this.handlePointerDown = (ev) => this.waitForStorage(storage => {
            this.updatePointerPosition(ev);
            storage.initializeAnimation();
        });
        this.handlePointerUp = () => this.waitForStorage(storage => storage.switchAnimation());
    }
    get storage() {
        return this._storage;
    }
    set storage(newS) {
        const old = this._storage;
        if (old)
            this.dispatchEvent(new CustomEvent(AxRevealBoundary.removeStorageEvent, { detail: old }));
        if (newS) {
            this._storage = newS;
            this.dispatchEvent(new CustomEvent(AxRevealBoundary.attachStorageEvent, { detail: this._storage }));
            if (old)
                this.dispatchEvent(new CustomEvent(AxRevealBoundary.replaceStorageEvent, { detail: { old, new: newS } }));
        }
    }
    waitForStorage(f) {
        if (this.storage === undefined)
            this.addEventListener(AxRevealBoundary.attachStorageEvent, () => f(this.storage), {
                once: true
            });
        else
            f(this.storage);
    }
    appendStorage(force = false) {
        if (!force)
            if (this.storage)
                return;
        const parent = this.closest(AxRevealProvider.ElementName);
        const stateManager = parent ? parent.stateManager : AxRevealBoundary.storage;
        this.storage = stateManager.newBoundary();
    }
    connectedCallback() {
        this.appendStorage(true);
        this.addEventListener('pointerenter', this.handlePointerEnter);
        this.addEventListener('pointerleave', this.handlePointerLeave);
        this.addEventListener('pointermove', this.handlePointerMove);
        this.addEventListener('pointerdown', this.handlePointerDown);
        this.addEventListener('pointerup', this.handlePointerUp);
    }
    disconnectedCallback() {
        this.storage = undefined;
    }
}
AxRevealBoundary.storage = new RevealStateManager();
AxRevealBoundary.ElementName = 'ax-reveal-bound';
AxRevealBoundary.removeStorageEvent = 'removeStorage';
AxRevealBoundary.attachStorageEvent = 'attachStorage';
AxRevealBoundary.replaceStorageEvent = 'replaceStorage';
export class AxReveal extends HTMLElement {
    constructor() {
        super();
        this.root = this.attachShadow({ mode: 'open' });
        this.root.innerHTML = `
<div>
    <slot></slot>
    <canvas></canvas>
    </div>
<style>
    div { display: content; }
    canvas { top: 0; left: 0; pointer-events: none; width: 100%; height: 100%; position: absolute; }
    :host { display: inline-block; position: relative; }
    :host([block]) { display: block; }
    :host([inline-block]) { display: inline-block; }
    :host([flex]) { display: flex; }
    :host([inline-flex]) { display: inline-flex; }
    :host([grid]) { display: grid; }
    :host([inline-grid]) { display: inline-grid; }
    ::slotted(button) { outline:none; }
</style>`;
        this.canvas = this.root.querySelector('canvas');
    }
    adoptedCallback() {
        this.disconnectedCallback();
        this.connectedCallback();
    }
    disconnectedCallback() {
        this.boundary && this.boundary.waitForStorage(storage => storage.removeReveal(this.canvas));
    }
    connectedCallback() {
        this.boundary = this.closest(AxRevealBoundary.ElementName);
        if (!this.boundary)
            throw new SyntaxError('You must use ' + AxRevealBoundary.ElementName + ' as the boundary of acrylic!');
        this.boundary.waitForStorage(storage => setTimeout(() => storage.addReveal(this.canvas), 0));
    }
}
AxReveal.ElementName = 'ax-reveal';
//# sourceMappingURL=CustomElements.js.map