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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { html, nothing } from 'lit';
import { property, query, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
import { FormInternalsMixin } from '../../utils/mixins/FormInternalsMixin';
import { KEYS } from '../../utils/keys';
import FormfieldWrapper from '../formfieldwrapper/formfieldwrapper.component';
import { POPOVER_PLACEMENT, TRIGGER, DEFAULTS as POPOVER_DEFAULTS } from '../popover/popover.constants';
import { ARROW_ICON, DEFAULTS, TIME_FORMAT, TRIGGER_ID, LISTBOX_ID } from './timepicker.constants';
import styles from './timepicker.styles';
/**
 * mdc-timepicker is a component that allows users to select a specific time
 * or enter a time manually. It supports both 12-hour and 24-hour formats.
 *
 * The component consists of:
 * - label - describes the time picker field
 * - input field - made up of 2-3 spinbuttons (hours, minutes, optional AM/PM period)
 * - dropdown arrow button - opens a flyout menu with predefined time intervals
 * - helper text - displayed below the input field
 *
 * Users can input values by:
 * - Manually entering numbers/characters in spinbuttons
 * - Navigating using arrow keys to increment/decrement values
 * - Selecting a predefined time from the dropdown menu
 *
 * @tagname mdc-timepicker
 *
 * @dependency mdc-button
 * @dependency mdc-icon
 * @dependency mdc-option
 * @dependency mdc-popover
 * @dependency mdc-text
 * @dependency mdc-toggletip
 *
 * @event input - (React: onInput) This event is dispatched when the time value changes.
 * @event change - (React: onChange) This event is dispatched when the time value is committed.
 * @event focus - (React: onFocus) This event is dispatched when the timepicker receives focus.
 * @event blur - (React: onBlur) This event is dispatched when the timepicker loses focus.
 *
 * @slot label - Slot for the label element.
 * @slot toggletip - Slot for the toggletip info icon button.
 * @slot help-icon - Slot for the helper/validation icon.
 * @slot help-text - Slot for the helper/validation text.
 *
 * @cssproperty --mdc-timepicker-background-color - Background color of the timepicker input.
 * @cssproperty --mdc-timepicker-border-color - Border color of the timepicker input.
 * @cssproperty --mdc-timepicker-text-color - Text color of the timepicker input.
 * @cssproperty --mdc-timepicker-height - The height of the timepicker trigger control.
 * @cssproperty --mdc-timepicker-width - Width of the timepicker component.
 * @cssproperty --mdc-timepicker-listbox-height - The max-height of the dropdown listbox. Default shows ~6 items.
 *
 * @csspart label - The label element.
 * @csspart label-text - The container for the label and required indicator elements.
 * @csspart required-indicator - The required indicator element.
 * @csspart info-icon-btn - The info icon button element.
 * @csspart label-toggletip - The toggletip element.
 * @csspart help-text - The helper/validation text element.
 * @csspart helper-icon - The helper/validation icon element.
 * @csspart help-text-container - The container for helper/validation elements.
 * @csspart container - The outer container for the input and popover.
 * @csspart base-container - The input container with border and background.
 * @csspart spinbutton-group - The container for spinbutton elements.
 * @csspart spinbutton - A spinbutton input element.
 * @csspart separator - The colon separator between spinbuttons.
 * @csspart period - The AM/PM period spinbutton.
 * @csspart icon-container - The dropdown arrow button container.
 * @csspart leading-icon - The prefix icon element displayed before spinbuttons.
 * @csspart native-input - The hidden native input for form participation.
 * @csspart listbox - The dropdown list container.
 */
class TimePicker extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
    constructor() {
        super(...arguments);
        /**
         * The time format to use for display.
         * - `'12h'`: 12-hour format with AM/PM period
         * - `'24h'`: 24-hour format without period
         * @default '12h'
         */
        this.timeFormat = DEFAULTS.TIME_FORMAT;
        /**
         * The interval in minutes between time options in the dropdown menu.
         * @default 30
         */
        this.interval = DEFAULTS.INTERVAL;
        /**
         * The placement of the popover dropdown.
         * @default 'bottom-start'
         */
        this.placement = POPOVER_PLACEMENT.BOTTOM_START;
        /**
         * The strategy for positioning the popover.
         * @default 'absolute'
         */
        this.strategy = POPOVER_DEFAULTS.STRATEGY;
        /**
         * Determines whether the dropdown should flip its position when it hits the boundary.
         * @default false
         */
        this.disableFlip = DEFAULTS.DISABLE_FLIP;
        /**
         * Accessible label for the hours spinbutton.
         * Consumers must provide a translated string.
         */
        this.localeHoursLabel = '';
        /**
         * Accessible label for the minutes spinbutton.
         * Consumers must provide a translated string.
         */
        this.localeMinutesLabel = '';
        /**
         * Accessible label for the period (AM/PM) spinbutton.
         * Consumers must provide a translated string.
         */
        this.localePeriodLabel = '';
        /**
         * Placeholder text for the hours spinbutton.
         * Consumers must provide a translated string.
         */
        this.localeHoursPlaceholder = '';
        /**
         * Placeholder text for the minutes spinbutton.
         * Consumers must provide a translated string.
         */
        this.localeMinutesPlaceholder = '';
        /**
         * Placeholder text for the period spinbutton.
         * Consumers must provide a translated string.
         */
        this.localePeriodPlaceholder = '';
        /**
         * Label for the AM period.
         * Consumers must provide a translated string.
         */
        this.localeAmLabel = '';
        /**
         * Label for the PM period.
         * Consumers must provide a translated string.
         */
        this.localePmLabel = '';
        /**
         * Accessible label for the dropdown toggle button.
         * Consumers must provide a translated string.
         */
        this.localeShowTimePickerLabel = '';
        /**
         * Accessible label for the time options listbox.
         * Consumers must provide a translated string.
         */
        this.localeTimeOptionsLabel = '';
        /**
         * Accessible description for spinbutton inputs (instruction text).
         * Consumers must provide a translated string.
         */
        this.localeSpinbuttonDescription = '';
        /** @internal */
        this.displayPopover = false;
        /** @internal */
        this.internalHours = '';
        /** @internal */
        this.internalMinutes = '';
        /** @internal */
        this.internalPeriod = 'AM';
        /** @internal */
        this.focusedOptionIndex = -1;
        /** @internal */
        this.pendingDigits = '';
    }
    connectedCallback() {
        super.connectedCallback();
        this.updateComplete
            .then(() => {
            this.parseValueToInternal();
            this.syncFormValue();
        })
            .catch(error => {
            if (this.onerror) {
                this.onerror(error);
            }
        });
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        if (this.pendingDigitTimeout) {
            clearTimeout(this.pendingDigitTimeout);
        }
    }
    willUpdate(changedProperties) {
        super.willUpdate(changedProperties);
        if (changedProperties.has('value') && !this.displayPopover) {
            this.parseValueToInternal();
            this.syncFormValue();
        }
        if (changedProperties.has('disabled') ||
            changedProperties.has('softDisabled') ||
            changedProperties.has('readonly')) {
            if (this.disabled || this.softDisabled || this.readonly) {
                this.displayPopover = false;
            }
        }
    }
    updated(changedProperties) {
        super.updated(changedProperties);
        if (changedProperties.has('displayPopover') && this.displayPopover) {
            this.focusMenuItemOnOpen();
        }
    }
    /**
     * When the menu opens, focus the selected item or the first item.
     * @internal
     */
    focusMenuItemOnOpen() {
        this.focusedOptionIndex = this.getMenuItemFocusIndex();
        this.updateComplete
            .then(() => {
            window.requestAnimationFrame(() => {
                this.focusCurrentMenuItem();
            });
        })
            .catch(() => { });
    }
    /**
     * Gets the option index that should receive focus when the menu opens.
     * @internal
     */
    getMenuItemFocusIndex() {
        const options = this.getTimeOptions();
        const currentValue = this.internalToValue();
        const selectedIndex = options.findIndex(opt => opt.value === currentValue);
        return selectedIndex >= 0 ? selectedIndex : 0;
    }
    /**
     * Focuses the menu item at the current focusedOptionIndex.
     * @internal
     */
    focusCurrentMenuItem() {
        var _a;
        const listbox = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`#${LISTBOX_ID}`);
        if (!listbox)
            return;
        const items = listbox.querySelectorAll('mdc-option');
        const item = items[this.focusedOptionIndex];
        if (item) {
            item.focus({ preventScroll: true });
            item.scrollIntoView({ block: 'nearest' });
        }
    }
    /** @internal */
    formResetCallback() {
        this.value = '';
        this.internalHours = '';
        this.internalMinutes = '';
        this.internalPeriod = 'AM';
        this.syncFormValue();
        this.requestUpdate();
    }
    /** @internal */
    formStateRestoreCallback(state) {
        this.value = state;
        this.parseValueToInternal();
    }
    /**
     * Parses the value (24h HH:MM) into internal hours, minutes, and period.
     * @internal
     */
    parseValueToInternal() {
        if (!this.value) {
            this.internalHours = '';
            this.internalMinutes = '';
            this.internalPeriod = 'AM';
            return;
        }
        const match = this.value.match(/^(\d{1,2}):(\d{2})$/);
        if (!match)
            return;
        const hours = parseInt(match[1], 10);
        const minutes = parseInt(match[2], 10);
        if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59)
            return;
        this.internalMinutes = String(minutes).padStart(2, '0');
        if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
            if (hours === 0) {
                this.internalPeriod = 'AM';
                this.internalHours = '12';
            }
            else if (hours < 12) {
                this.internalPeriod = 'AM';
                this.internalHours = String(hours).padStart(2, '0');
            }
            else if (hours === 12) {
                this.internalPeriod = 'PM';
                this.internalHours = '12';
            }
            else {
                this.internalPeriod = 'PM';
                this.internalHours = String(hours - 12).padStart(2, '0');
            }
        }
        else {
            this.internalHours = String(hours).padStart(2, '0');
        }
    }
    /**
     * Converts internal hours, minutes, and period to 24h HH:MM value.
     * @internal
     */
    internalToValue() {
        if (!this.internalHours || !this.internalMinutes)
            return '';
        let hours = parseInt(this.internalHours, 10);
        if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
            if (this.internalPeriod === 'AM') {
                hours = hours === 12 ? 0 : hours;
            }
            else {
                hours = hours === 12 ? 12 : hours + 12;
            }
        }
        return `${String(hours).padStart(2, '0')}:${this.internalMinutes}`;
    }
    /**
     * Syncs the form value with the current internal state.
     * @internal
     */
    syncFormValue() {
        const val = this.internalToValue();
        this.internals.setFormValue(val || this.value);
    }
    /**
     * Updates the value from internal state and fires events.
     * @internal
     */
    commitValue() {
        const newValue = this.internalToValue();
        if (newValue && newValue !== this.value) {
            this.value = newValue;
            this.syncFormValue();
            this.dispatchEvent(new CustomEvent('input', {
                detail: { value: this.value },
                composed: true,
                bubbles: true,
            }));
            this.dispatchEvent(new CustomEvent('change', {
                detail: { value: this.value },
                composed: true,
                bubbles: true,
            }));
        }
    }
    /**
     * Generates time interval options for the dropdown.
     * @internal
     */
    getTimeOptions() {
        const options = [];
        const interval = Math.max(1, Math.min(this.interval, 60));
        for (let totalMinutes = 0; totalMinutes < 24 * 60; totalMinutes += interval) {
            const h = Math.floor(totalMinutes / 60);
            const m = totalMinutes % 60;
            const value24 = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
            let label;
            if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
                const period = h < 12 ? this.localeAmLabel : this.localePmLabel;
                let displayHour = h % 12;
                if (displayHour === 0)
                    displayHour = 12;
                const displayMin = String(m).padStart(2, '0');
                label = `${displayHour}:${displayMin} ${period}`;
            }
            else {
                label = `${h}:${String(m).padStart(2, '0')}`;
            }
            // Filter by min/max if provided
            const withinMin = !this.min || value24 >= this.min;
            const withinMax = !this.max || value24 <= this.max;
            if (withinMin && withinMax) {
                options.push({ label, value: value24 });
            }
        }
        return options;
    }
    /**
     * Handles clicking on a time option in the dropdown.
     * @internal
     */
    handleOptionClick(optionValue) {
        var _a;
        this.value = optionValue;
        this.parseValueToInternal();
        this.displayPopover = false;
        this.syncFormValue();
        this.dispatchEvent(new CustomEvent('input', {
            detail: { value: this.value },
            composed: true,
            bubbles: true,
        }));
        this.dispatchEvent(new CustomEvent('change', {
            detail: { value: this.value },
            composed: true,
            bubbles: true,
        }));
        // Return focus to the dropdown button
        (_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
    }
    /**
     * Handles clicking the dropdown arrow button.
     * @internal
     */
    handleDropdownClick(event) {
        if (this.disabled || this.softDisabled || this.readonly)
            return;
        this.displayPopover = !this.displayPopover;
        event.stopPropagation();
    }
    /**
     * Handles clicking on the base container.
     * @internal
     */
    handleBaseContainerClick(event) {
        var _a, _b, _c;
        if (this.disabled || this.softDisabled || this.readonly)
            return;
        const target = event.target;
        // If clicking on a spinbutton itself, let it handle focus
        if (target.getAttribute('role') === 'spinbutton')
            return;
        // If clicking the non-editable blank area, treat it like the dropdown button.
        if (target.getAttribute('part') === 'base-container' || target.getAttribute('part') === 'spinbutton-group') {
            this.displayPopover = !this.displayPopover;
            (_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
            event.stopPropagation();
            return;
        }
        // Otherwise focus the hours spinbutton
        (_b = this.hoursInput) === null || _b === void 0 ? void 0 : _b.focus();
        (_c = this.hoursInput) === null || _c === void 0 ? void 0 : _c.select();
    }
    /**
     * Handles keydown on the base container (when popover is closed).
     * @internal
     */
    handleBaseKeydown(event) {
        var _a;
        if (this.disabled || this.softDisabled || this.readonly)
            return;
        if (event.key === KEYS.ESCAPE && this.displayPopover) {
            this.displayPopover = false;
            (_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
            event.preventDefault();
            event.stopPropagation();
        }
    }
    /**
     * Handles keydown on the popover/listbox (when open).
     * Supports ArrowDown/ArrowUp to navigate, Enter to select, Escape to close.
     * @internal
     */
    handleListboxKeydown(event) {
        var _a;
        const options = this.getTimeOptions();
        const optionCount = options.length;
        if (optionCount === 0)
            return;
        switch (event.key) {
            case KEYS.ARROW_DOWN: {
                event.preventDefault();
                event.stopPropagation();
                this.focusedOptionIndex = (this.focusedOptionIndex + 1) % optionCount;
                this.focusCurrentMenuItem();
                break;
            }
            case KEYS.ARROW_UP: {
                event.preventDefault();
                event.stopPropagation();
                this.focusedOptionIndex = (this.focusedOptionIndex - 1 + optionCount) % optionCount;
                this.focusCurrentMenuItem();
                break;
            }
            case KEYS.ENTER: {
                event.preventDefault();
                event.stopPropagation();
                if (this.focusedOptionIndex >= 0 && this.focusedOptionIndex < optionCount) {
                    this.handleOptionClick(options[this.focusedOptionIndex].value);
                }
                break;
            }
            case KEYS.ESCAPE: {
                event.preventDefault();
                event.stopPropagation();
                this.displayPopover = false;
                (_a = this.dropdownButton) === null || _a === void 0 ? void 0 : _a.focus();
                break;
            }
            default:
                break;
        }
    }
    /**
     * Handles keydown on the hours spinbutton.
     * @internal
     */
    handleHoursKeydown(event) {
        this.handleSpinbuttonKeydown(event, 'hours');
    }
    /**
     * Handles keydown on the minutes spinbutton.
     * @internal
     */
    handleMinutesKeydown(event) {
        this.handleSpinbuttonKeydown(event, 'minutes');
    }
    /**
     * Handles keydown on the period spinbutton.
     * @internal
     */
    handlePeriodKeydown(event) {
        var _a, _b;
        switch (event.key) {
            case KEYS.ARROW_UP:
            case KEYS.ARROW_DOWN:
                event.preventDefault();
                this.internalPeriod = this.internalPeriod === 'AM' ? 'PM' : 'AM';
                this.commitValue();
                this.requestUpdate();
                break;
            case KEYS.TAB:
                // Allow default tab behavior
                break;
            case KEYS.ARROW_LEFT:
                event.preventDefault();
                (_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
                (_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
                break;
            default: {
                event.preventDefault();
                const amChar = this.localeAmLabel.charAt(0).toLowerCase();
                const pmChar = this.localePmLabel.charAt(0).toLowerCase();
                const pressed = event.key.toLowerCase();
                if (pressed === amChar) {
                    this.internalPeriod = 'AM';
                    this.commitValue();
                    this.requestUpdate();
                }
                else if (pressed === pmChar) {
                    this.internalPeriod = 'PM';
                    this.commitValue();
                    this.requestUpdate();
                }
                break;
            }
        }
    }
    /**
     * Generic spinbutton keydown handler for hours and minutes.
     * @internal
     */
    handleSpinbuttonKeydown(event, field) {
        var _a, _b, _c, _d, _e, _f;
        const is12h = this.timeFormat === TIME_FORMAT.TWELVE_HOUR;
        let minVal;
        let maxVal;
        if (field === 'hours') {
            minVal = is12h ? DEFAULTS.MIN_HOUR_12 : DEFAULTS.MIN_HOUR_24;
            maxVal = is12h ? DEFAULTS.MAX_HOUR_12 : DEFAULTS.MAX_HOUR_24;
        }
        else {
            minVal = DEFAULTS.MIN_MINUTE;
            maxVal = DEFAULTS.MAX_MINUTE;
        }
        const currentStr = field === 'hours' ? this.internalHours : this.internalMinutes;
        let current = currentStr ? parseInt(currentStr, 10) : minVal;
        switch (event.key) {
            case KEYS.ARROW_UP: {
                event.preventDefault();
                current = current >= maxVal ? minVal : current + 1;
                this.setSpinbuttonValue(field, current);
                this.commitValue();
                break;
            }
            case KEYS.ARROW_DOWN: {
                event.preventDefault();
                current = current <= minVal ? maxVal : current - 1;
                this.setSpinbuttonValue(field, current);
                this.commitValue();
                break;
            }
            case KEYS.ARROW_RIGHT: {
                event.preventDefault();
                if (field === 'hours') {
                    (_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
                    (_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
                }
                else if (is12h) {
                    (_c = this.periodInput) === null || _c === void 0 ? void 0 : _c.focus();
                    (_d = this.periodInput) === null || _d === void 0 ? void 0 : _d.select();
                }
                break;
            }
            case KEYS.ARROW_LEFT: {
                event.preventDefault();
                if (field === 'minutes') {
                    (_e = this.hoursInput) === null || _e === void 0 ? void 0 : _e.focus();
                    (_f = this.hoursInput) === null || _f === void 0 ? void 0 : _f.select();
                }
                break;
            }
            case KEYS.TAB: {
                // Allow default tab behavior for navigation
                break;
            }
            default: {
                // Handle digit input
                if (/^\d$/.test(event.key)) {
                    event.preventDefault();
                    this.handleDigitInput(event.key, field, minVal, maxVal);
                }
                else {
                    event.preventDefault();
                }
                break;
            }
        }
    }
    /**
     * Handles digit input for spinbuttons with auto-advance logic.
     * @internal
     */
    handleDigitInput(digit, field, minVal, maxVal) {
        if (this.pendingDigitTimeout) {
            clearTimeout(this.pendingDigitTimeout);
        }
        this.pendingDigits += digit;
        if (this.pendingDigits.length >= 2) {
            // Two digits entered - commit and advance
            let val = parseInt(this.pendingDigits, 10);
            if (val > maxVal)
                val = maxVal;
            if (val < minVal)
                val = minVal;
            this.setSpinbuttonValue(field, val);
            this.pendingDigits = '';
            this.commitValue();
            this.advanceToNextField(field);
        }
        else {
            // Single digit - check if we can determine the value needs a second digit
            const firstDigit = parseInt(this.pendingDigits, 10);
            const maxFirstDigit = Math.floor(maxVal / 10);
            if (firstDigit > maxFirstDigit) {
                // Single digit already exceeds max first digit - auto-pad and advance
                let val = firstDigit;
                if (val > maxVal)
                    val = maxVal;
                if (val < minVal)
                    val = minVal;
                this.setSpinbuttonValue(field, val);
                this.pendingDigits = '';
                this.commitValue();
                this.advanceToNextField(field);
            }
            else {
                // Wait for second digit with timeout
                this.setSpinbuttonValue(field, firstDigit);
                this.pendingDigitTimeout = setTimeout(() => {
                    // Auto-pad with leading zero
                    let val = firstDigit;
                    if (val < minVal)
                        val = minVal;
                    this.setSpinbuttonValue(field, val);
                    this.pendingDigits = '';
                    this.commitValue();
                    this.advanceToNextField(field);
                }, 1000);
            }
        }
    }
    /**
     * Sets the value of a spinbutton field.
     * @internal
     */
    setSpinbuttonValue(field, val) {
        const padded = String(val).padStart(2, '0');
        if (field === 'hours') {
            this.internalHours = padded;
        }
        else {
            this.internalMinutes = padded;
        }
        this.requestUpdate();
    }
    /**
     * Advances focus to the next spinbutton field.
     * @internal
     */
    advanceToNextField(currentField) {
        if (currentField === 'hours') {
            this.updateComplete
                .then(() => {
                var _a, _b;
                (_a = this.minutesInput) === null || _a === void 0 ? void 0 : _a.focus();
                (_b = this.minutesInput) === null || _b === void 0 ? void 0 : _b.select();
            })
                .catch(() => { });
        }
        else if (this.timeFormat === TIME_FORMAT.TWELVE_HOUR) {
            this.updateComplete
                .then(() => {
                var _a, _b;
                (_a = this.periodInput) === null || _a === void 0 ? void 0 : _a.focus();
                (_b = this.periodInput) === null || _b === void 0 ? void 0 : _b.select();
            })
                .catch(() => { });
        }
    }
    /**
     * Handles focus on a spinbutton - selects all text.
     * @internal
     */
    handleSpinbuttonFocus(event) {
        const target = event.target;
        target.select();
        // Clear pending digits when switching fields
        this.pendingDigits = '';
        if (this.pendingDigitTimeout) {
            clearTimeout(this.pendingDigitTimeout);
        }
    }
    /**
     * Gets the display text for the current period using locale labels.
     * @internal
     */
    get displayPeriod() {
        return this.internalPeriod === 'AM' ? this.localeAmLabel : this.localePmLabel;
    }
    /**
     * Gets the placeholder text for the hours spinbutton.
     * @internal
     */
    get hoursPlaceholder() {
        return this.localeHoursPlaceholder;
    }
    /**
     * Gets the placeholder text for the minutes spinbutton.
     * @internal
     */
    get minutesPlaceholder() {
        return this.localeMinutesPlaceholder;
    }
    /**
     * Gets the placeholder text for the period spinbutton.
     * @internal
     */
    get periodPlaceholder() {
        return this.localePeriodPlaceholder;
    }
    /**
     * Renders the dropdown time options list using mdc-option components.
     * @internal
     */
    renderTimeOptions() {
        const options = this.getTimeOptions();
        const currentValue = this.internalToValue();
        return options.map(option => html `
        <mdc-option
          label="${this.optionLabelFormatter ? this.optionLabelFormatter(option.label, option.value) : option.label}"
          ?selected="${option.value === currentValue}"
          aria-selected="${option.value === currentValue ? 'true' : 'false'}"
          @click="${() => this.handleOptionClick(option.value)}"
        ></mdc-option>
      `);
    }
    render() {
        const is12h = this.timeFormat === TIME_FORMAT.TWELVE_HOUR;
        const hoursMin = is12h ? DEFAULTS.MIN_HOUR_12 : DEFAULTS.MIN_HOUR_24;
        const hoursMax = is12h ? DEFAULTS.MAX_HOUR_12 : DEFAULTS.MAX_HOUR_24;
        return html `
      ${this.renderLabel()}
      <div part="container">
        <div
          id="${TRIGGER_ID}"
          part="base-container"
          class="mdc-focus-ring"
          @click="${this.handleBaseContainerClick}"
          @keydown="${this.handleBaseKeydown}"
        >
          ${this.prefixIcon
            ? html `<mdc-icon part="leading-icon" name="${this.prefixIcon}" size="1"></mdc-icon>`
            : nothing}
          <div part="spinbutton-group">
            <input
              id="hours-spinbutton"
              part="spinbutton"
              role="spinbutton"
              aria-label="${this.localeHoursLabel}"
              aria-valuemin="${hoursMin}"
              aria-valuemax="${hoursMax}"
              aria-valuenow="${this.internalHours ? parseInt(this.internalHours, 10) : ''}"
              aria-description="${this.localeSpinbuttonDescription}"
              .value="${this.internalHours}"
              placeholder="${this.hoursPlaceholder}"
              ?disabled="${this.disabled}"
              ?readonly="${this.readonly}"
              tabindex="${this.disabled ? '-1' : '0'}"
              @keydown="${this.handleHoursKeydown}"
              @focus="${this.handleSpinbuttonFocus}"
            />
            <span part="separator">:</span>
            <input
              id="minutes-spinbutton"
              part="spinbutton"
              role="spinbutton"
              aria-label="${this.localeMinutesLabel}"
              aria-valuemin="${DEFAULTS.MIN_MINUTE}"
              aria-valuemax="${DEFAULTS.MAX_MINUTE}"
              aria-valuenow="${this.internalMinutes ? parseInt(this.internalMinutes, 10) : ''}"
              aria-description="${this.localeSpinbuttonDescription}"
              .value="${this.internalMinutes}"
              placeholder="${this.minutesPlaceholder}"
              ?disabled="${this.disabled}"
              ?readonly="${this.readonly}"
              tabindex="${this.disabled ? '-1' : '0'}"
              @keydown="${this.handleMinutesKeydown}"
              @focus="${this.handleSpinbuttonFocus}"
            />
            ${is12h
            ? html `
                  <input
                    id="period-spinbutton"
                    part="period"
                    role="spinbutton"
                    aria-label="${this.localePeriodLabel}"
                    aria-valuetext="${this.displayPeriod}"
                    aria-description="${this.localeSpinbuttonDescription}"
                    .value="${this.displayPeriod || ''}"
                    placeholder="${this.periodPlaceholder}"
                    ?disabled="${this.disabled}"
                    ?readonly="${this.readonly}"
                    tabindex="${this.disabled ? '-1' : '0'}"
                    @keydown="${this.handlePeriodKeydown}"
                    @focus="${this.handleSpinbuttonFocus}"
                  />
                `
            : nothing}
          </div>
          <mdc-button
            part="icon-container"
            class="own-focus-ring"
            variant="tertiary"
            prefix-icon="${this.displayPopover ? ARROW_ICON.ARROW_UP : ARROW_ICON.ARROW_DOWN}"
            aria-label="${this.localeShowTimePickerLabel}"
            aria-expanded="${this.displayPopover ? 'true' : 'false'}"
            aria-haspopup="true"
            ?disabled="${this.disabled}"
            size="20"
            @click="${this.handleDropdownClick}"
          ></mdc-button>
        </div>
        <input
          id="${this.inputId}"
          part="native-input"
          name="${this.name}"
          type="text"
          ?disabled="${this.disabled}"
          ?required="${this.required}"
          ?readonly="${this.readonly}"
          tabindex="-1"
          aria-hidden="true"
          aria-disabled="${ifDefined(this.disabled || this.softDisabled)}"
        />
        <mdc-popover
          trigger="${TRIGGER.MANUAL}"
          triggerid="${TRIGGER_ID}"
          interactive
          ?visible="${this.displayPopover}"
          role=""
          backdrop
          backdrop-append-to="${ifDefined(this.backdropAppendTo)}"
          append-to="${ifDefined(this.appendTo)}"
          hide-on-outside-click
          hide-on-escape
          focus-back-to-trigger
          focus-trap
          element-index-to-receive-focus="${this.getMenuItemFocusIndex()}"
          disable-aria-expanded
          size
          ?disable-flip="${this.disableFlip}"
          placement="${this.placement}"
          strategy="${ifDefined(this.strategy)}"
          @closebyescape="${(event) => {
            if (event.target === event.currentTarget) {
                this.displayPopover = false;
            }
        }}"
          @closebyoutsideclick="${() => {
            this.displayPopover = false;
        }}"
          exportparts="popover-content"
        >
          <mdc-selectlistbox
            id="${LISTBOX_ID}"
            part="listbox"
            aria-label="${this.localeTimeOptionsLabel}"
            @keydown="${this.handleListboxKeydown}"
          >
            ${this.renderTimeOptions()}
          </mdc-selectlistbox>
        </mdc-popover>
      </div>
      ${this.helpText ? this.renderHelperText() : nothing}
    `;
    }
}
TimePicker.styles = [...FormfieldWrapper.styles, ...styles];
__decorate([
    property({ type: String, reflect: true, attribute: 'time-format' }),
    __metadata("design:type", String)
], TimePicker.prototype, "timeFormat", void 0);
__decorate([
    property({ type: Number, reflect: true }),
    __metadata("design:type", Number)
], TimePicker.prototype, "interval", void 0);
__decorate([
    property({ type: String, reflect: true }),
    __metadata("design:type", String)
], TimePicker.prototype, "placement", void 0);
__decorate([
    property({ type: String, reflect: true }),
    __metadata("design:type", String)
], TimePicker.prototype, "strategy", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: 'disable-flip' }),
    __metadata("design:type", Boolean)
], TimePicker.prototype, "disableFlip", void 0);
__decorate([
    property({ type: String, reflect: true, attribute: 'append-to' }),
    __metadata("design:type", String)
], TimePicker.prototype, "appendTo", void 0);
__decorate([
    property({ type: String, reflect: true, attribute: 'backdrop-append-to' }),
    __metadata("design:type", String)
], TimePicker.prototype, "backdropAppendTo", void 0);
__decorate([
    property({ type: String, reflect: true }),
    __metadata("design:type", String)
], TimePicker.prototype, "min", void 0);
__decorate([
    property({ type: String, reflect: true }),
    __metadata("design:type", String)
], TimePicker.prototype, "max", void 0);
__decorate([
    property({ type: String, attribute: 'locale-hours-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeHoursLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-minutes-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeMinutesLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-period-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localePeriodLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-hours-placeholder' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeHoursPlaceholder", void 0);
__decorate([
    property({ type: String, attribute: 'locale-minutes-placeholder' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeMinutesPlaceholder", void 0);
__decorate([
    property({ type: String, attribute: 'locale-period-placeholder' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localePeriodPlaceholder", void 0);
__decorate([
    property({ type: String, attribute: 'locale-am-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeAmLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-pm-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localePmLabel", void 0);
__decorate([
    property({ type: String, reflect: true, attribute: 'prefix-icon' }),
    __metadata("design:type", String)
], TimePicker.prototype, "prefixIcon", void 0);
__decorate([
    property({ attribute: false }),
    __metadata("design:type", Function)
], TimePicker.prototype, "optionLabelFormatter", void 0);
__decorate([
    property({ type: String, attribute: 'locale-show-time-picker-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeShowTimePickerLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-time-options-label' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeTimeOptionsLabel", void 0);
__decorate([
    property({ type: String, attribute: 'locale-spinbutton-description' }),
    __metadata("design:type", Object)
], TimePicker.prototype, "localeSpinbuttonDescription", void 0);
__decorate([
    query('mdc-button[part="icon-container"]'),
    __metadata("design:type", HTMLElement)
], TimePicker.prototype, "dropdownButton", void 0);
__decorate([
    query('#hours-spinbutton'),
    __metadata("design:type", HTMLInputElement)
], TimePicker.prototype, "hoursInput", void 0);
__decorate([
    query('#minutes-spinbutton'),
    __metadata("design:type", HTMLInputElement)
], TimePicker.prototype, "minutesInput", void 0);
__decorate([
    query('#period-spinbutton'),
    __metadata("design:type", HTMLInputElement)
], TimePicker.prototype, "periodInput", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], TimePicker.prototype, "displayPopover", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], TimePicker.prototype, "internalHours", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], TimePicker.prototype, "internalMinutes", void 0);
__decorate([
    state(),
    __metadata("design:type", String)
], TimePicker.prototype, "internalPeriod", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], TimePicker.prototype, "focusedOptionIndex", void 0);
export default TimePicker;
