import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
import { _ as __decorate, a as __metadata } from './tslib.es6.js';
import { i as isEscapeKey } from './index.esm.js';
import { a as ariaBooleanToString } from './aria.js';
import { i as inheritAttributes } from './attributes.js';
import { B as BEM } from './bem.js';
import { b as balBrowser } from './browser.js';
import { b as balFloatingUi } from './floating-ui.js';
import { F as FOCUS_KEYS } from './focus-visible.js';
import { d as defaultBalAriaForm } from './form.js';
import { s as stopEventBubbling } from './form-input.js';
import { m as rIC, k as debounceEvent, p as addEventListener, q as removeEventListener, e as waitAfterIdleCallback } from './helpers.js';
import { L as Logger } from './log.js';
import { i as i18nBalDate } from './bal-date.i18n.js';
import { d as defineCustomElement$6 } from './bal-date-calendar2.js';
import { d as defineCustomElement$5 } from './bal-date-calendar-cell2.js';
import { d as defineCustomElement$4 } from './bal-icon2.js';
import { d as defineCustomElement$3 } from './bal-input-date2.js';
import { d as defineCustomElement$2 } from './bal-input-group2.js';
import { d as defaultConfig } from './config.default.js';
import { B as BalDate$1 } from './date.js';
import { a as isSpaceKey } from './keyboard.helpers.js';
import { L as ListenToConfig } from './config.decorator.js';

const balDateCss = ":root{--bal-date-popup-z-index:var(--bal-z-index-tooltip);--bal-date-popup-shadow:var(--bal-shadow-normal);--bal-date-popup-radius:var(--bal-radius-normal)}:root{--bal-z-index-tooltip:1300}.bal-date{display:block;font-family:var(--bal-font-family-text);width:100%}.bal-date__icon--clickable{cursor:pointer}.bal-date__popup{display:none;width:-webkit-max-content;width:-moz-max-content;width:max-content;position:absolute;top:0;left:0;z-index:var(--bal-date-popup-z-index);-webkit-box-shadow:var(--bal-date-popup-shadow);box-shadow:var(--bal-date-popup-shadow);border-radius:var(--bal-date-popup-radius)}.bal-date__popup--visible{display:block}";

const Date = /*@__PURE__*/ proxyCustomElement(class Date extends HTMLElement {
    constructor(registerHost) {
        super();
        if (registerHost !== false) {
            this.__registerHost();
        }
        this.balInput = createEvent(this, "balInput", 7);
        this.balChange = createEvent(this, "balChange", 7);
        this.balWillAnimate = createEvent(this, "balWillAnimate", 7);
        this.balDidAnimate = createEvent(this, "balDidAnimate", 7);
        this.balBlur = createEvent(this, "balBlur", 7);
        this.balFocus = createEvent(this, "balFocus", 7);
        this.balInputClick = createEvent(this, "balInputClick", 7);
        this.balIconClick = createEvent(this, "balIconClick", 7);
        this.inputId = `bal-da-${dateIds++}`;
        this.inheritedAttributes = {};
        this.isKeyboardMode = false;
        this.hasFocus = false;
        this.isExpanded = false;
        this.language = defaultConfig.language;
        this.ariaForm = defaultBalAriaForm;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * The name of the control, which is submitted with the form data.
         */
        this.name = this.inputId;
        /**
         * If `true` the component gets a invalid style.
         */
        this.invalid = false;
        /**
         * If `true` the attribute required is added to the native input.
         */
        this.required = false;
        /**
         * If `true`, the element is not mutable, focusable, or even submitted with the form. The user can neither edit nor focus on the control, nor its form control descendants.
         */
        this.disabled = false;
        /**
         * If `true` the element can not mutated, meaning the user can not edit the control.
         */
        this.readonly = false;
        /**
         * If `true` there will be no trigger icon visible, so no UX indicator for a picker
         */
        this.freeSolo = false;
        /**
         * If `true` the datepicker only open on click of the icon
         */
        this.triggerIcon = false;
        /**
         * Closes the datepicker popover after selection
         */
        this.closeOnSelect = true;
        /**
         * Indicates whether the value of the control can be automatically completed by the browser.
         */
        this.autocomplete = 'off';
        /**
         * The value of the form field, which accepts ISO 8601 date strings (YYYY-MM-DD).
         */
        this.value = undefined;
        /**
         * Callback to determine which date in the datepicker should be selectable.
         */
        this.allowedDates = undefined;
        /**
         * If `true`, it returns the string `INVALID_VALUE` within the balChange event if the input provided is not valid.
         */
        this.allowInvalidValue = false;
        /**
         * Set the amount of time, in milliseconds, to wait to trigger the `ionChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`.
         */
        this.debounce = 0;
        /**
         * If `true`, in Angular reactive forms the control will not be set invalid
         */
        this.autoInvalidOff = false;
        /**
         * LIFECYCLE
         * ------------------------------------------------------
         */
        this.hasConnected = false;
        /**
         * PRIVATE METHOD
         * ------------------------------------------------------
         */
        this.handleKeydown = (ev) => {
            this.isKeyboardMode = FOCUS_KEYS.includes(ev.key);
        };
        this.handlePointerDown = () => {
            this.isKeyboardMode = false;
        };
        this.handleOutsideClick = (ev) => {
            if (this.isExpanded) {
                if (!this.el.contains(ev.target)) {
                    this.isExpanded = false;
                    this.hasFocus = false;
                    rIC(() => this.balBlur.emit(ev));
                }
            }
        };
        this.handleFocus = (ev) => {
            stopEventBubbling(ev);
            this.hasFocus = true;
            this.balFocus.emit(ev.detail);
        };
        this.handleBlur = (ev) => {
            stopEventBubbling(ev);
            if (!this.isExpanded) {
                this.hasFocus = false;
                rIC(() => this.balBlur.emit(ev.detail));
            }
        };
        /**
         * EVENT BINDING
         * ------------------------------------------------------
         */
        this.onIconClick = async (_ev) => {
            if (this.triggerIcon) {
                await this.toggle();
            }
            else {
                await this.open();
            }
        };
        this.onInputClick = async (_ev) => {
            if (!this.triggerIcon) {
                await this.open();
            }
        };
        this.onCalendarChange = (ev) => {
            stopEventBubbling(ev);
            this.value = ev.detail;
            this.balChange.emit(this.value);
            if (this.closeOnSelect) {
                this.close();
                this.hasFocus = false;
                rIC(() => this.balBlur.emit());
            }
        };
        this.onInputInput = (ev) => {
            stopEventBubbling(ev);
            this.balInput.emit(ev.detail);
            if (ev.detail) {
                const date = BalDate$1.fromAnyFormat(ev.detail);
                if (date.isValid) {
                    this.calendarValue = date.toISODate();
                }
            }
        };
        this.onInputChange = (ev) => {
            stopEventBubbling(ev);
            this.value = ev.detail;
            this.balChange.emit(this.value);
        };
        this.onKeyPress = async ({ detail }) => {
            if (detail && detail.key) {
                if (this.isExpanded) {
                    if (detail.key === 'Tab' || isEscapeKey(detail) || isSpaceKey(detail)) {
                        await this.close();
                    }
                }
                else {
                    if (isSpaceKey(detail)) {
                        await this.open();
                    }
                }
            }
        };
    }
    createLogger(log) {
        this.log = log;
    }
    valueChanged() {
        this.calendarValue = this.value;
    }
    debounceChanged() {
        this.balChange = debounceEvent(this.balChange, this.debounce);
    }
    connectedCallback() {
        if (balBrowser.hasDocument) {
            addEventListener(document, 'keydown', this.handleKeydown);
            addEventListener(document, 'touchstart', this.handlePointerDown);
            addEventListener(document, 'mousedown', this.handlePointerDown);
            addEventListener(document, 'click', this.handleOutsideClick);
        }
        this.hasConnected = true;
        this.valueChanged();
    }
    disconnectedCallback() {
        if (balBrowser.hasDocument) {
            removeEventListener(document, 'keydown', this.handleKeydown);
            removeEventListener(document, 'touchstart', this.handlePointerDown);
            removeEventListener(document, 'mousedown', this.handlePointerDown);
            removeEventListener(document, 'click', this.handleOutsideClick);
        }
    }
    componentWillLoad() {
        this.inheritedAttributes = inheritAttributes(this.el, ['aria-label', 'tabindex', 'title', 'data-hj-allow']);
    }
    /**
     * @internal define config for the component
     */
    async configChanged(state) {
        this.language = state.language;
    }
    /**
     * PUBLIC METHOD
     * ------------------------------------------------------
     */
    /**
     * Opens the accordion
     */
    async open() {
        return this.expand();
    }
    /**
     * Closes the accordion
     */
    async close() {
        return this.collapse();
    }
    /**
     * Triggers the accordion
     */
    async toggle() {
        if (this.isExpanded) {
            return this.collapse();
        }
        else {
            return this.expand();
        }
    }
    /**
     * Selects an option
     */
    async select(dateString) {
        const date = BalDate$1.fromISO(dateString);
        if (date.isValid) {
            this.value = date.toISODate();
            this.calendarValue = this.value;
        }
    }
    /**
     * Sets focus on the native `input` in `bal-input`. Use this method instead of the global
     * `input.focus()`.
     */
    async setFocus() {
        if (this.inputEl && !this.disabled && !this.readonly) {
            await waitAfterIdleCallback();
            this.inputEl.focus();
        }
    }
    /**
     * Sets blur on the native `input` in `bal-input`. Use this method instead of the global
     * `input.blur()`.
     * @internal
     */
    async setBlur() {
        var _a;
        if (this.inputEl && !this.disabled && !this.readonly) {
            await waitAfterIdleCallback();
            (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.setBlur();
        }
    }
    /**
     * Returns the native `<input>` element used under the hood.
     */
    async getInputElement() {
        var _a;
        return (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.getInputElement();
    }
    /**
     * @internal
     */
    async setAriaForm(ariaForm) {
        var _a;
        this.ariaForm = Object.assign({}, ariaForm);
        (_a = this.inputEl) === null || _a === void 0 ? void 0 : _a.setAriaForm(ariaForm);
    }
    async expand() {
        if (this.referenceEl && this.floatingEl) {
            const lib = await balFloatingUi.load();
            this.balWillAnimate.emit();
            this.isExpanded = true;
            this.popupCleanup = lib.autoUpdate(this.referenceEl, this.floatingEl, () => {
                this.updatePosition(this.referenceEl, this.floatingEl);
            });
        }
        return this.isExpanded;
    }
    async collapse() {
        if (this.floatingEl) {
            this.balWillAnimate.emit();
            this.isExpanded = false;
            if (this.popupCleanup) {
                this.popupCleanup();
            }
            this.balDidAnimate.emit();
        }
        return this.isExpanded;
    }
    async updatePosition(referenceEl, floatingEl) {
        const lib = await balFloatingUi.load();
        lib
            .computePosition(referenceEl, floatingEl, {
            placement: 'bottom-start',
            middleware: [lib.offset(4), lib.flip({ crossAxis: false })],
        })
            .then(({ x, y }) => {
            Object.assign(floatingEl.style, {
                left: `${x}px`,
                top: `${y}px`,
            });
            this.balDidAnimate.emit();
        });
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = BEM.block('date');
        const blockIcon = block.element('icon');
        const blockPopup = block.element('popup');
        return (h(Host, { key: '66accfbf681e12eefdc6e61912fe5736f75c4501', id: this.inputId, class: Object.assign({}, block.class()) }, h("bal-input-group", { key: '4e816b701215387a395c6a73da929609302d0c8f', invalid: this.invalid, readonly: this.readonly, disabled: this.disabled, ref: el => (this.referenceEl = el) }, h("bal-input-date", Object.assign({ key: '188d50af76d1625bafb08b2d8ad4d13756bc4468', name: this.name, required: this.required, placeholder: this.placeholder, value: this.value, min: this.min, max: this.max, invalid: this.invalid, readonly: this.readonly, disabled: this.disabled, allowInvalidValue: this.allowInvalidValue, autocomplete: this.autocomplete, onClick: this.onInputClick, onBalInput: this.onInputInput, onBalChange: this.onInputChange, onBalFocus: ev => this.handleFocus(ev), onBalBlur: ev => this.handleBlur(ev), onBalKeyPress: this.onKeyPress, ref: el => (this.inputEl = el) }, this.inheritedAttributes)), !this.freeSolo ? (h("bal-icon", { name: "date", role: "button", tabindex: -1, class: Object.assign(Object.assign({}, blockIcon.class()), blockIcon.modifier('clickable').class(!this.disabled && !this.readonly)), "is-right": true, color: this.disabled || this.readonly ? 'grey' : this.invalid ? 'danger' : 'primary', onClick: this.onIconClick, "aria-label": i18nBalDate[this.language].toggleDatepicker, "aria-haspopup": "true", "aria-expanded": ariaBooleanToString(this.isExpanded) })) : ('')), h("div", { key: '8eaee6ea09c2099057a2ad0165d63f70154d4095', role: "dialog", class: Object.assign(Object.assign({}, blockPopup.class()), blockPopup.modifier('visible').class(this.isExpanded)), ref: el => (this.floatingEl = el), "aria-hidden": `${this.isExpanded !== true}`, "aria-presented": `${this.isExpanded === true}` }, h("bal-date-calendar", { key: '16f6680967612f55e9f8259b780a02e61c830090', value: this.calendarValue, min: this.min, max: this.max, minYearProp: this.minYearProp, maxYearProp: this.maxYearProp, defaultDate: this.defaultDate, allowedDates: this.allowedDates, onBalChange: this.onCalendarChange }))));
    }
    get el() { return this; }
    static get watchers() { return {
        "value": ["valueChanged"],
        "debounce": ["debounceChanged"]
    }; }
    static get style() { return balDateCss; }
}, [256, "bal-date", {
        "name": [1],
        "invalid": [4],
        "required": [4],
        "disabled": [4],
        "readonly": [4],
        "freeSolo": [4, "free-solo"],
        "placeholder": [1],
        "triggerIcon": [4, "trigger-icon"],
        "closeOnSelect": [4, "close-on-select"],
        "autocomplete": [1],
        "value": [1025],
        "min": [1025],
        "max": [1025],
        "minYearProp": [2, "min-year"],
        "maxYearProp": [2, "max-year"],
        "defaultDate": [1, "default-date"],
        "allowedDates": [16],
        "allowInvalidValue": [4, "allow-invalid-value"],
        "debounce": [2],
        "autoInvalidOff": [516, "auto-invalid-off"],
        "isKeyboardMode": [32],
        "hasFocus": [32],
        "isExpanded": [32],
        "language": [32],
        "calendarValue": [32],
        "ariaForm": [32],
        "configChanged": [64],
        "open": [64],
        "close": [64],
        "toggle": [64],
        "select": [64],
        "setFocus": [64],
        "setBlur": [64],
        "getInputElement": [64],
        "setAriaForm": [64]
    }, undefined, {
        "value": ["valueChanged"],
        "debounce": ["debounceChanged"]
    }]);
__decorate([
    Logger('bal-date'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function]),
    __metadata("design:returntype", void 0)
], Date.prototype, "createLogger", null);
__decorate([
    ListenToConfig(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Date.prototype, "configChanged", null);
let dateIds = 0;
function defineCustomElement$1() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["bal-date", "bal-date-calendar", "bal-date-calendar-cell", "bal-icon", "bal-input-date", "bal-input-group"];
    components.forEach(tagName => { switch (tagName) {
        case "bal-date":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, Date);
            }
            break;
        case "bal-date-calendar":
            if (!customElements.get(tagName)) {
                defineCustomElement$6();
            }
            break;
        case "bal-date-calendar-cell":
            if (!customElements.get(tagName)) {
                defineCustomElement$5();
            }
            break;
        case "bal-icon":
            if (!customElements.get(tagName)) {
                defineCustomElement$4();
            }
            break;
        case "bal-input-date":
            if (!customElements.get(tagName)) {
                defineCustomElement$3();
            }
            break;
        case "bal-input-group":
            if (!customElements.get(tagName)) {
                defineCustomElement$2();
            }
            break;
    } });
}

const BalDate = Date;
const defineCustomElement = defineCustomElement$1;

export { BalDate, defineCustomElement };
