var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { arrow, autoUpdate, computePosition, flip, inline, limitShift, offset, shift, size, } from '@floating-ui/dom';
import { LitElement, html } from 'lit';
import { property, query, queryAssignedElements } from 'lit/decorators.js';
import { watch } from '../common/decorators/watch.js';
import { registerComponent } from '../common/definitions/register.js';
import { first, getElementByIdFromRoot, isEmpty, isString, roundByDPR, } from '../common/util.js';
import { styles } from './themes/light/popover.base.css.js';
class IgcPopoverComponent extends LitElement {
    constructor() {
        super(...arguments);
        this.arrow = null;
        this.arrowOffset = 0;
        this.inline = false;
        this.flip = false;
        this.offset = 0;
        this.open = false;
        this.placement = 'bottom-start';
        this.sameWidth = false;
        this.shift = false;
        this.shiftPadding = 0;
    }
    static register() {
        registerComponent(IgcPopoverComponent);
    }
    anchorChange() {
        const newTarget = isString(this.anchor)
            ? getElementByIdFromRoot(this, this.anchor)
            : this.anchor;
        if (newTarget) {
            this.target = newTarget;
            this._updateState();
        }
    }
    openChange() {
        this.open ? this.show() : this.hide();
    }
    floatingPropChange() {
        this._updateState();
    }
    async connectedCallback() {
        super.connectedCallback();
        await this.updateComplete;
        if (this.open) {
            this.show();
        }
    }
    disconnectedCallback() {
        this.hide();
        super.disconnectedCallback();
    }
    show() {
        if (!this.target) {
            return;
        }
        this._showPopover();
        this.dispose = autoUpdate(this.target, this._container, this._updatePosition.bind(this));
    }
    async hide() {
        this._hidePopover();
        return new Promise((resolve) => {
            this.dispose?.();
            this.dispose = undefined;
            resolve();
        });
    }
    _showPopover() {
        this._container?.showPopover();
    }
    _hidePopover() {
        this._container?.hidePopover();
    }
    _createMiddleware() {
        const middleware = [];
        const styles = this._container.style;
        if (this.offset) {
            middleware.push(offset(this.offset));
        }
        if (this.inline) {
            middleware.push(inline());
        }
        if (this.shift) {
            middleware.push(shift({
                padding: this.shiftPadding,
                limiter: limitShift(),
            }));
        }
        if (this.arrow) {
            middleware.push(arrow({ element: this.arrow }));
        }
        if (this.flip) {
            middleware.push(flip());
        }
        if (this.sameWidth) {
            middleware.push(size({
                apply: ({ rects }) => {
                    Object.assign(styles, { width: `${rects.reference.width}px` });
                },
            }));
        }
        else {
            Object.assign(styles, { width: '' });
        }
        return middleware;
    }
    async _updateState() {
        if (this.open) {
            await this.hide();
            this.show();
        }
    }
    async _updatePosition() {
        if (!(this.open && this.target)) {
            return;
        }
        const { x, y, middlewareData, placement } = await computePosition(this.target, this._container, {
            placement: this.placement ?? 'bottom-start',
            middleware: this._createMiddleware(),
            strategy: 'absolute',
        });
        Object.assign(this._container.style, {
            left: 0,
            top: 0,
            transform: `translate(${roundByDPR(x)}px,${roundByDPR(y)}px)`,
        });
        this._positionArrow(placement, middlewareData);
    }
    _positionArrow(placement, data) {
        if (!(data.arrow && this.arrow)) {
            return;
        }
        const { x, y } = data.arrow;
        const currentPlacement = first(placement.split('-'));
        const staticSide = {
            top: 'bottom',
            right: 'left',
            bottom: 'top',
            left: 'right',
        }[currentPlacement];
        this.arrow.part = currentPlacement;
        Object.assign(this.arrow.style, {
            left: x != null ? `${roundByDPR(x + this.arrowOffset)}px` : '',
            top: y != null ? `${roundByDPR(y + this.arrowOffset)}px` : '',
            [staticSide]: '-4px',
        });
    }
    _anchorSlotChange() {
        if (this.anchor || isEmpty(this._anchors)) {
            return;
        }
        this.target = this._anchors[0];
        this._updateState();
    }
    render() {
        return html `
      <slot name="anchor" @slotchange=${this._anchorSlotChange}></slot>
      <div id="container" part="container" popover="manual">
        <slot></slot>
      </div>
    `;
    }
}
IgcPopoverComponent.tagName = 'igc-popover';
IgcPopoverComponent.styles = styles;
export default IgcPopoverComponent;
__decorate([
    query('#container')
], IgcPopoverComponent.prototype, "_container", void 0);
__decorate([
    queryAssignedElements({ slot: 'anchor', flatten: true })
], IgcPopoverComponent.prototype, "_anchors", void 0);
__decorate([
    property()
], IgcPopoverComponent.prototype, "anchor", void 0);
__decorate([
    property({ attribute: false })
], IgcPopoverComponent.prototype, "arrow", void 0);
__decorate([
    property({ type: Number, attribute: 'arrow-offset' })
], IgcPopoverComponent.prototype, "arrowOffset", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], IgcPopoverComponent.prototype, "inline", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], IgcPopoverComponent.prototype, "flip", void 0);
__decorate([
    property({ type: Number })
], IgcPopoverComponent.prototype, "offset", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], IgcPopoverComponent.prototype, "open", void 0);
__decorate([
    property()
], IgcPopoverComponent.prototype, "placement", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: 'same-width' })
], IgcPopoverComponent.prototype, "sameWidth", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], IgcPopoverComponent.prototype, "shift", void 0);
__decorate([
    property({ type: Number, attribute: 'shift-padding' })
], IgcPopoverComponent.prototype, "shiftPadding", void 0);
__decorate([
    watch('anchor')
], IgcPopoverComponent.prototype, "anchorChange", null);
__decorate([
    watch('open', { waitUntilFirstUpdate: true })
], IgcPopoverComponent.prototype, "openChange", null);
__decorate([
    watch('arrow', { waitUntilFirstUpdate: true }),
    watch('arrowOffset', { waitUntilFirstUpdate: true }),
    watch('flip', { waitUntilFirstUpdate: true }),
    watch('inline', { waitUntilFirstUpdate: true }),
    watch('offset', { waitUntilFirstUpdate: true }),
    watch('placement', { waitUntilFirstUpdate: true }),
    watch('sameWidth', { waitUntilFirstUpdate: true }),
    watch('shift', { waitUntilFirstUpdate: true }),
    watch('shiftPadding', { waitUntilFirstUpdate: true })
], IgcPopoverComponent.prototype, "floatingPropChange", null);
//# sourceMappingURL=popover.js.map