import { __esDecorate, __runInitializers } from "tslib";
import { html } from 'lit';
import { property } from 'lit/decorators.js';
import { UiElement } from '../../UiElement.js';
import { setDisabled } from '../../../lib/disabled.js';
let UiCollapse = (() => {
    let _classSuper = UiElement;
    let _disabled_decorators;
    let _disabled_initializers = [];
    let _disabled_extraInitializers = [];
    let _noAnimation_decorators;
    let _noAnimation_initializers = [];
    let _noAnimation_extraInitializers = [];
    let _horizontal_decorators;
    let _horizontal_initializers = [];
    let _horizontal_extraInitializers = [];
    let _open_decorators;
    let _open_initializers = [];
    let _open_extraInitializers = [];
    return class UiCollapse extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _disabled_decorators = [property({ type: Boolean, reflect: true })];
            _noAnimation_decorators = [property({ type: Boolean, reflect: true })];
            _horizontal_decorators = [property({ type: Boolean })];
            _open_decorators = [property({ type: Boolean, reflect: true })];
            __esDecorate(this, null, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
            __esDecorate(this, null, _noAnimation_decorators, { kind: "accessor", name: "noAnimation", static: false, private: false, access: { has: obj => "noAnimation" in obj, get: obj => obj.noAnimation, set: (obj, value) => { obj.noAnimation = value; } }, metadata: _metadata }, _noAnimation_initializers, _noAnimation_extraInitializers);
            __esDecorate(this, null, _horizontal_decorators, { kind: "accessor", name: "horizontal", static: false, private: false, access: { has: obj => "horizontal" in obj, get: obj => obj.horizontal, set: (obj, value) => { obj.horizontal = value; } }, metadata: _metadata }, _horizontal_initializers, _horizontal_extraInitializers);
            __esDecorate(this, null, _open_decorators, { kind: "accessor", name: "open", static: false, private: false, access: { has: obj => "open" in obj, get: obj => obj.open, set: (obj, value) => { obj.open = value; } }, metadata: _metadata }, _open_initializers, _open_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #disabled_accessor_storage = __runInitializers(this, _disabled_initializers, false
        /**
         * Set noAnimation to true to disable animations.
         * @attr
         */
        );
        /**
         * Whether the chip is disabled. The user can't interact with the chip when `true`.
         * @attribute
         */
        get disabled() { return this.#disabled_accessor_storage; }
        set disabled(value) { this.#disabled_accessor_storage = value; }
        #noAnimation_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _noAnimation_initializers, void 0));
        /**
         * Set noAnimation to true to disable animations.
         * @attr
         */
        get noAnimation() { return this.#noAnimation_accessor_storage; }
        set noAnimation(value) { this.#noAnimation_accessor_storage = value; }
        #horizontal_accessor_storage = (__runInitializers(this, _noAnimation_extraInitializers), __runInitializers(this, _horizontal_initializers, false
        /**
         * Set opened to true to show the collapse element and to false to hide it.
         * @attribute
         */
        ));
        /**
         * Renders the collapse horizontally when true and vertically otherwise
         * @attribute
         */
        get horizontal() { return this.#horizontal_accessor_storage; }
        set horizontal(value) { this.#horizontal_accessor_storage = value; }
        #open_accessor_storage = (__runInitializers(this, _horizontal_extraInitializers), __runInitializers(this, _open_initializers, false));
        /**
         * Set opened to true to show the collapse element and to false to hide it.
         * @attribute
         */
        get open() { return this.#open_accessor_storage; }
        set open(value) { this.#open_accessor_storage = value; }
        get dimension() {
            return this.horizontal ? 'width' : 'height';
        }
        /**
         * `maxWidth` or `maxHeight`.
         * @private
         */
        get dimensionMax() {
            return this.horizontal ? 'maxWidth' : 'maxHeight';
        }
        /**
         * `max-width` or `max-height`.
         * @private
         */
        get dimensionMaxCss() {
            return this.horizontal ? 'max-width' : 'max-height';
        }
        get isAttached() {
            return !!this.parentNode;
        }
        transitioningInternal = (__runInitializers(this, _open_extraInitializers), false);
        /**
         * @return When true, the element is transitioning its open state. When false,
         * the element has finished opening/closing.
         */
        get transitioning() {
            return this.transitioningInternal;
        }
        /**
         * Stores the desired size of the collapse body.
         */
        desiredSize = '';
        constructor() {
            super();
            this.addEventListener('transitionend', this.handleTransitionEnd.bind(this));
        }
        connectedCallback() {
            super.connectedCallback();
            if (!this.hasAttribute('role')) {
                this.setAttribute('role', 'group');
            }
            if (!this.hasAttribute('aria-hidden')) {
                this.setAttribute('aria-hidden', 'true');
            }
        }
        willUpdate(cp) {
            if (cp.has('open')) {
                this.handleOpenChange();
            }
            if (cp.has('horizontal')) {
                this.handleHorizontalChange();
            }
            if (cp.has('disabled')) {
                setDisabled(this, cp.get('disabled'));
            }
            super.willUpdate(cp);
        }
        /**
         * Toggle the opened state.
         */
        toggle() {
            this.open = !this.open;
            this.dispatchEvent(new Event('toggle'));
        }
        /**
         * Updates the size of the element.
         * @param size The new value for `maxWidth`/`maxHeight` as css property value, usually `auto` or `0px`.
         * @param animated if `true` updates the size with an animation, otherwise without.
         */
        updateSize(size, animated) {
            // Consider 'auto' as '', to take full size.
            let sizeValue = size === 'auto' ? '' : size;
            let willAnimate = animated && !this.noAnimation && this.isAttached;
            this.desiredSize = sizeValue;
            this.updateTransition(false);
            // If we can animate, must do some prep work.
            if (willAnimate) {
                // Animation will start at the current size.
                const startSize = this.calcSize();
                // For `auto` we must calculate what is the final size for the animation.
                // After the transition is done, _transitionEnd will set the size back to
                // `auto`.
                if (sizeValue === '') {
                    // Temporarily remove constraint to measure natural size
                    const currentMaxDimension = this.style[this.dimensionMax];
                    this.style[this.dimensionMax] = '';
                    sizeValue = this.calcSize();
                    this.style[this.dimensionMax] = currentMaxDimension;
                }
                // Go to startSize without animation.
                this.style[this.dimensionMax] = startSize;
                // Force layout to ensure transition will go. Set scrollTop to itself
                // so that compilers won't remove it.
                // eslint-disable-next-line no-self-assign
                this.scrollTop = this.scrollTop;
                // Enable animation.
                this.updateTransition(true);
                // If final size is the same as startSize it will not animate.
                willAnimate = sizeValue !== startSize;
            }
            // Set the final size.
            this.style[this.dimensionMax] = sizeValue;
            // If it won't animate, call transitionEnd to set correct styles.
            if (!willAnimate) {
                this.transitionEnd();
            }
        }
        updateTransition(enabled) {
            this.style.transitionDuration = enabled && !this.noAnimation ? '' : '0s';
        }
        /**
         * Calculates the size of the element when opened.
         */
        calcSize() {
            const value = this.getBoundingClientRect()[this.dimension];
            return `${value}px`;
        }
        transitionEnd() {
            this.style[this.dimensionMax] = this.desiredSize;
            this.toggleAttribute('collapse-closed', !this.open);
            this.toggleAttribute('collapse-opened', this.open);
            this.updateTransition(false);
            this.notifyResize();
            this.transitioningInternal = false;
            this.notifyTransitioning();
        }
        notifyResize() {
            this.dispatchEvent(new Event('resize', { bubbles: true, composed: true, cancelable: true }));
        }
        notifyTransitioning() {
            this.dispatchEvent(new Event('transitioning', { bubbles: true, composed: true, cancelable: true }));
        }
        handleTransitionEnd(e) {
            const target = e.composedPath().find((node) => node === this);
            if (target) {
                this.transitionEnd();
            }
        }
        handleOpenChange() {
            const { open } = this;
            this.setAttribute('aria-hidden', String(!open));
            this.transitioningInternal = true;
            this.notifyTransitioning();
            this.toggleAttribute('collapse-closed', false);
            this.toggleAttribute('collapse-opened', false);
            this.updateSize(open ? 'auto' : '0px', true);
            // Focus the current collapse.
            if (open) {
                this.focus();
            }
        }
        handleHorizontalChange() {
            this.style.transitionProperty = this.dimensionMaxCss;
            const otherDimension = this.dimensionMax === 'maxWidth' ? 'maxHeight' : 'maxWidth';
            this.style[otherDimension] = '';
            this.updateSize(this.open ? 'auto' : '0px', false);
        }
        render() {
            return html `<slot></slot>`;
        }
    };
})();
/**
 * @fires transitioning - When the element is transitioning.
 * @slot - Main slot for the content
 */
export default UiCollapse;
//# sourceMappingURL=Collapse.js.map