UNPKG

@postnord/web-components

Version:
2,019 lines 84.3 kB
/*!
 * Built with Stencil
 * By PostNord.
 */
import { h, Host, Mixin, forceUpdate, } from "@stencil/core";
import { awaitTopbar, uuidv4, en, getTotalHeightOffset, getMenuWidth } from "../../../index";
import { animateHeightFactory } from "../../../globals/mixins/index";
import { translations } from "./translations";
import { CALENDAR, MONTHS, YEARS, validateDate, isBefore, isAfter, selectedDate, getDateObject, getDiff, getToday, getDate, getReadableDate, getGrid, setYear, setMonth, navigateGrid, } from "../../../globals/date/index";
import { calendar, arrow_left, arrow_right, pn_return } from "pn-design-assets/pn-assets/icons.js";
/**
 * The date picker allows a single or a range of dates to be selected.
 *
 * Based on the `format` prop, separators will automatically be added if you type the date.
 *
 * You can navigate the calendar grid with your keyboard.
 *
 * @nativeInput Use the `input` event to listen to content being modified by the user. It is emitted everytime a user writes or removes content in the input.
 * @nativeChange The `change` event is emitted when the input loses focus, the user clicks `Enter` or makes a selection (such as auto complete or suggestions).
 *
 * @slot chips - Introduce some quick date selectors underneath the calendar grid. Use the `pn-choice-chip` component. {@since v7.6.0}
 * @slot helpertext - You can use this slot instead of the prop `helpertext`. Recommended, only if you need to include additional HTML markup. Such as a `pn-text-link`. Use a `span` element to wrap the text and link. {@since v7.6.0}
 * @slot error - You can use this slot instead of the prop `error`. Recommended, only if you need to include additional HTML markup. Such as a `pn-text-link`. Use a `span` element to wrap the text and link. {@since v7.6.0}
 */
export class PnDatePicker extends Mixin(animateHeightFactory) {
    constructor() {
        super();
    }
    id = `pn-date-picker-${uuidv4()}`;
    idStart = `${this.id}-from`;
    idEnd = `${this.id}-to`;
    idStartButton = `${this.id}-from-button`;
    idEndButton = `${this.id}-to-button`;
    idHelper = `${this.id}-helper`;
    idError = `${this.id}-error`;
    idCalendar = `${this.id}-calendar`;
    mo;
    calendarElement;
    today = getToday();
    separators = [];
    separatorRegex = /[^a-zA-Z\d\s:]/g;
    listMonths = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
    listWeek = [1, 2, 3, 4, 5, 6, 0];
    hostElement;
    open = false;
    openUp = false;
    selectingEnd = false;
    grid;
    viewYearStart = null;
    dateViewYear;
    dateViewMonth;
    dateViewDate;
    showHelperSlot;
    showErrorSlot;
    /** Set a label for the from date. */
    labelFrom;
    /** Set a label for the to date. @see {@link range} */
    labelTo;
    /** Provide a helpertext for the date input. */
    helpertext;
    /** Manually set language; this will be inherited from the topbar. */
    language = undefined;
    /** Set a predefined value for the from date (input value). @see {@link format} @category Native attributes */
    start = '';
    /**
     * Set a predefined value for the from date. (input value end)
     *
     * @see {@link range}
     * @see {@link format}
     * @category Native attributes
     */
    end = '';
    /** HTML input name @since v7.6.0 @category Native attributes*/
    name;
    /** HTML input name @since v7.25.0 @category Native attributes */
    nameEnd;
    /**
     * Placeholder for the input field (defaults to the format prop).
     * @see {@link format}
     * @category Native attributes
     **/
    placeholder;
    /**
     * Placeholder for end date (defaults to the format prop).
     * @see {@link format}
     * @deprecated Use `placeholder-end` instead
     * @category Native attributes
     **/
    endPlaceholder;
    /**
     * Placeholder for end date (defaults to the format prop).
     * @see {@link format}
     * @since v7.25.0
     * @category Native attributes
     **/
    placeholderEnd;
    /** Set the input `autocomplete` attribute. @category Native attributes */
    autocomplete;
    /** Set the input `list` attribute for the first date input. @since v7.6.0 @category Native attributes */
    list;
    /** Set the input `list` attribute for the second date input. @since v7.6.0 @category Native attributes */
    listEnd;
    /** Set the HTML pattern prop on the input elements. Make sure it matches the format. @since v7.6.0 @category Native attributes */
    pattern;
    /** Set the date picker as required. @category Native attributes */
    required = false;
    /** Set the date picker as readonly. @since v7.6.0 @category Native attributes */
    readonly = false;
    /** Set the date picker as disabled. @since v7.6.0 @category Native attributes */
    disabled = false;
    /**
     * Set the date format of the value.
     *
     * While you can set any date value from the Dayjs documentation,
     * we strongly recommend you pick a simple format that you can also type manually.
     *
     * @since v7.6.0
     * @see {@link https://day.js.org/docs/en/display/format Day.js format documentation.}
     * @category Features
     */
    format = 'YYYY-MM-DD';
    /** Disable the automatic insertion of separators when typing in the input. @since v7.6.0 @category Features */
    disableTypeAhead = false;
    /** Remove the option to select dates on weekends. @category Features */
    disableWeekends = false;
    /**
     * Individual dates you want to disable. Use a comma separated string.
     *
     * Remember to use the same format that you have in the `format` prop.
     * @see {@link format}
     * @example "YYYY-MM-DD,YYYY-MM-DD"
     * @category Features
     **/
    disabledDates;
    /** If you use a format with an unknown length, disable the max length. @since 7.11.3 @category Features */
    disableMaxLength = false;
    /** Allow the selection of a date range. @category Features */
    range = false;
    /**
     * Set a limit on how many days one may select.
     * By default, you can select an unlimited range.
     *
     * @todo Create a range limit function.
     * @see {@link range}
     *
     * @category Features
     * @hide true
     **/
    rangeLimit;
    /** Show weekend numbers to the left of the calendar grid. @since v7.6.0 @category Features */
    weekNumbers = false;
    /** Set the date picker label as compact. If used, the `placeholder` will no longer be displayed. @since v7.21.0 @category Features */
    compact = false;
    /** Make the calendar open upwards by default. Opens downwards if there is not enough space. @since v7.6.0 @category Features */
    calendarUp = false;
    /** The calendar grid is shown as default. You can set either `months` or `years` as your first choice. @since v7.6.0 @category Features */
    view = 'calendar';
    /** Trigger the invalid state without an error message. @since v7.6.0 @category Features */
    invalid = false;
    /** Set an error message for the date picker. Overwrites the helpertext if used at the same time. @since v7.6.0 @category Features */
    error;
    /** Set a custom ID for the calendar. If you use `range`, the end input will use `${pn-id}-end`. @since v7.25.0 @category HTML attributes */
    pnId;
    /**
     * Provide the label via an aria attribute.
     * We strongly recommend you use the `label-from` prop instead.
     * @since v7.25.0
     * @category HTML attributes
     */
    pnAriaLabel;
    /**
     * Provide the label for the end input via an aria attribute.
     * We strongly recommend you use the `label-to` prop instead.
     * @since v7.25.0
     * @category HTML attributes
     */
    pnAriaLabelEnd;
    /**
     * Provide the label from another element via its ID.
     * We strongly recommend you use the `label-from` prop instead.
     * @since v7.25.0
     * @category HTML attributes
     */
    pnAriaLabelledby;
    /**
     * Provide the label for the end input from another element via its ID.
     * We strongly recommend you use the `label-to` prop instead.
     * @since v7.25.0
     * @category HTML attributes
     */
    pnAriaLabelledbyEnd;
    /** Set a custom ID for the calendar. @since v7.6.0 @deprecated Use `pn-id` instead. @category HTML attributes */
    dateId;
    /**
     * Earliest date possible, this will determine how many years back the date picker will show.
     *
     * Remember to use the same format that you have in the `format` prop.
     * @see {@link format}
     * @example "2024-05-25"
     * @category Features
     **/
    minDate = null;
    watchMin() {
        if (this.minDate === null)
            return;
        if (!validateDate(this.minDate, this.format))
            this.minDate = null;
    }
    /**
     * Latest date possible, this will determine how many years forward the date picker will show.
     *
     * Remember to use the same format that you have in the `format` prop.
     * @see {@link format}
     * @example "2024-06-25"
     * @category Features
     **/
    maxDate = null;
    watchMax() {
        if (this.maxDate === null)
            return;
        if (!validateDate(this.maxDate, this.format))
            this.maxDate = null;
    }
    watchValue() {
        if (!validateDate(this.start, this.format))
            return this.dateInvalid.emit({ start: this.start });
        const { year, month, date } = getDateObject(this.start, this.format);
        this.setViewYear({ year });
        this.setViewMonth({ month });
        this.setViewDate({ date });
        if (this.range && isAfter(this.start, this.end, this.format, 'date')) {
            this.end = '';
        }
        this.emitSelection();
    }
    watchValueTo() {
        if (!this.range)
            return;
        if (!validateDate(this.end, this.format))
            return this.dateInvalid.emit({ end: this.end });
        const date = getDate(this.end, this.format);
        this.setViewYear({ year: date.year() });
        this.setViewMonth({ month: date.month() });
        this.setViewDate({ date: date.date() });
        if (isAfter(this.start, this.end, this.format, 'date')) {
            const value = this.start;
            this.start = this.end;
            this.end = value;
        }
        this.emitSelection();
    }
    handleFormat() {
        this.separators.length = 0;
        this.format
            .split('')
            .forEach((item, index) => this.separatorRegex.exec(item) && this.separators.push({ name: item, index }));
    }
    watchId() {
        this.idStart = this.getId();
        this.idEnd = `${this.getId()}-end`;
        this.idStartButton = `${this.idStart}-from-button`;
        this.idEndButton = `${this.idEnd}-to-button`;
        this.idHelper = `${this.idStart}-helper`;
        this.idError = `${this.idStart}-error`;
        this.idCalendar = `${this.idStart}-calendar`;
    }
    watchView() {
        const data = this.getCurrentDateObject();
        if (validateDate(data, this.format))
            this.updateGrid();
    }
    watchOpen() {
        this.toggleCalendar.emit(this.open);
        this.dropdownHandler();
        if (this.open)
            this.addGlobalEventListeners();
        else
            return this.removeGlobalEventListeners();
        this.calendarElement.style.removeProperty('--pn-calendar-offset-left');
        this.openUp = this.calendarUp;
        requestAnimationFrame(() => {
            const rectHost = this.getRect(this.hostElement);
            const { scrollHeight } = this.calendarElement;
            const { innerHeight, innerWidth } = window;
            const offsetTop = getTotalHeightOffset();
            const spaceUpwards = rectHost.y - offsetTop;
            const spaceDownwards = innerHeight - rectHost.bottom;
            const fitUpwards = spaceUpwards > scrollHeight;
            const fitDownwards = spaceDownwards > scrollHeight;
            const openTop = (this.openUp && (fitUpwards || spaceUpwards > spaceDownwards)) || (!fitDownwards && fitUpwards);
            this.openUp = openTop;
            // Calc horizontal positioning - center calendar relative to host element
            const rectCal = this.getRect(this.calendarElement);
            const menuWidth = getMenuWidth();
            // Calculate center position: host center minus half of calendar width
            const hostCenterX = rectHost.x + rectHost.width / 2;
            const calendarHalfWidth = rectCal.width / 2;
            const idealCenterOffset = hostCenterX - calendarHalfWidth - rectCal.x;
            // Check boundaries, accounting for menu width on the left
            const calendarLeftEdge = rectCal.x + idealCenterOffset;
            const calendarRightEdge = calendarLeftEdge + rectCal.width;
            const leftBoundary = menuWidth + 16; // Menu width + buffer
            let finalOffset = idealCenterOffset;
            // Adjust if calendar would go beyond left edge of viewport or over the menu
            if (calendarLeftEdge < leftBoundary) {
                finalOffset = leftBoundary - rectCal.x;
            }
            // Adjust if calendar would go beyond right edge of viewport
            else if (calendarRightEdge > innerWidth - 16) {
                finalOffset = innerWidth - 16 - rectCal.width - rectCal.x;
            }
            this.calendarElement.style.setProperty('--pn-calendar-offset-left', `${Math.floor(finalOffset)}px`);
        });
    }
    handleMessage() {
        this.checkSlottedHelper();
        this.checkSlottedError();
    }
    handleView() {
        this.currentView.emit(this.view);
    }
    /**
     * Use the new `dateSelection`. Its here for compatibility. Will be removed in v8.
     * @deprecated Use the new `dateSelection`. Will be removed in v8.
     **/
    dateselection;
    /**
     * Emits on valid date selection. Either if the user selects a date in the calendar or writes it manually.
     * @since v7.6.0
     */
    dateSelection;
    emitSelection() {
        const data = {
            start: this.start,
        };
        if (this.range) {
            const days = getDiff(this.start, this.end, this.format);
            data.end = this.end;
            data.days = typeof days === 'number' ? days + 1 : null;
        }
        this.dateSelection.emit(data);
        this.dateselection.emit(data);
    }
    /** Emitted when an invalid value is set. This can only be done if the user writes in the input itself. @since v7.6.0 */
    dateInvalid;
    /** Emitted when the calendar is toggled. @since v7.6.0 */
    toggleCalendar;
    /** Emmitted when you select a new view. @since v7.6.0 */
    currentView;
    /**
     * If the select is open and you resize the window.
     * Remove all css props and disable the animations entierly.
     **/
    handleResize() {
        if (!this.open)
            return;
        this.toggleGrid(false);
    }
    connectedCallback() {
        this.mo = new MutationObserver(() => {
            forceUpdate(this.hostElement);
            this.handleMessage();
        });
        this.mo.observe(this.hostElement, { childList: true, subtree: true });
    }
    disconnectedCallback() {
        if (this.mo)
            this.mo.disconnect();
    }
    async componentWillLoad() {
        this.handleFormat();
        this.handleMessage();
        const valid = validateDate(this.start || this.end, this.format);
        const data = valid && getDateObject(this.start || this.end, this.format);
        const { year, month, date } = getDateObject(this.today);
        this.setViewDate({ date: data.date || date });
        this.setViewMonth({ month: data.month || month });
        this.setViewYear({ year: data.year || year });
        if (this.language === undefined)
            await awaitTopbar(this.hostElement);
    }
    getId() {
        return this.pnId || this.dateId || this.id;
    }
    getAriaLabel(end) {
        if (end)
            return !this.labelTo && !this.pnAriaLabelledbyEnd ? this.pnAriaLabelEnd : null;
        return !this.labelFrom && !this.pnAriaLabelledby ? this.pnAriaLabel : null;
    }
    getAriaLabelledby(end) {
        if (end)
            return !this.labelTo && !this.pnAriaLabelEnd ? this.pnAriaLabelledbyEnd : null;
        return !this.labelFrom && !this.pnAriaLabel ? this.pnAriaLabelledby : null;
    }
    getPlaceholder(end) {
        if (this.compact)
            return ' ';
        if (end)
            return this.placeholderEnd || this.endPlaceholder || this.format;
        return this.placeholder || this.format;
    }
    dropdownHandler() {
        if (this.open)
            this.openDropdown(this.calendarElement);
        else
            this.closeDropdown(this.calendarElement);
    }
    globalEvents = (event) => {
        const target = event.target;
        const isWithinCalendar = target?.closest(this.hostElement.localName);
        if (!isWithinCalendar)
            this.toggleGrid(false);
    };
    addGlobalEventListeners() {
        const root = this.hostElement.getRootNode();
        root.addEventListener('click', this.globalEvents);
    }
    removeGlobalEventListeners() {
        const root = this.hostElement.getRootNode();
        root.removeEventListener('click', this.globalEvents);
    }
    translate(prop) {
        return translations?.[prop?.toUpperCase()]?.[this.language || en] || prop?.toUpperCase();
    }
    translateDateText(customDate, format) {
        return getReadableDate({ ...this.getCurrentDateObject(), ...customDate }, this.language, format);
    }
    getRect(element) {
        return element.getBoundingClientRect();
    }
    toggleGrid(state, selecting) {
        this.open = state ?? !this.open;
        this.selectingEnd = selecting;
    }
    hasHelperText() {
        return this.helpertext?.length > 0 || this.showHelperSlot;
    }
    /** If any `error` text is present, either via prop/slot. */
    hasErrorMessage() {
        return this.error?.length > 0 || this.showErrorSlot;
    }
    /** If any `error` is active, either via the prop `invalid` or `error` prop/slot. */
    hasError() {
        return this.hasErrorMessage() || this.invalid || this.showErrorSlot;
    }
    checkSlottedHelper() {
        const slottedHelper = this.hostElement.querySelector('[slot=helpertext]')?.textContent;
        this.showHelperSlot = !!slottedHelper?.length;
    }
    checkSlottedError() {
        const slottedError = this.hostElement.querySelector('[slot=error]')?.textContent;
        this.showErrorSlot = !!slottedError?.length;
    }
    hideHelpertext() {
        return this.hasErrorMessage() || !this.hasHelperText();
    }
    hideError() {
        return !this.hasErrorMessage();
    }
    viewingCalendar() {
        return this.view === CALENDAR;
    }
    viewingMonth() {
        return this.view === MONTHS;
    }
    viewingYears() {
        return this.view === YEARS;
    }
    viewType() {
        return this.viewingCalendar() ? 'date' : this.viewingMonth() ? 'month' : 'year';
    }
    isBeforeMax(data) {
        if (this.maxDate)
            return isBefore(data, this.maxDate, this.format, this.viewType());
        return true;
    }
    isAfterMin(data) {
        if (this.minDate)
            return isAfter(data, this.minDate, this.format, this.viewType());
        return true;
    }
    isDisabledWeekend(day) {
        if (!this.viewingCalendar())
            return false;
        return this.disableWeekends ? day >= 6 : false;
    }
    isDisabledDate(data) {
        if (!this.disabledDates?.length || !this.viewingCalendar())
            return false;
        const list = this.disabledDates.split(',');
        return !!list.find(disabledDate => selectedDate(disabledDate, data, this.format, this.viewType()));
    }
    isDisabled(data) {
        const isAfterMaxDate = !this.isBeforeMax(data);
        const isBeforeMinDate = !this.isAfterMin(data);
        const weekendDisable = this.viewingCalendar() && this.isDisabledWeekend(data.day);
        const manualDisable = this.isDisabledDate(data);
        const disabled = isAfterMaxDate || isBeforeMinDate || weekendDisable || manualDisable;
        return {
            disabled,
            manualDisable,
            weekendDisable,
            minMaxDisable: isAfterMaxDate || isBeforeMinDate,
        };
    }
    updateGrid() {
        this.grid = getGrid(this.dateViewYear, this.dateViewMonth);
    }
    getCurrentViewDate(data = this.getCurrentDateObject()) {
        return getReadableDate(data, this.language, 'MMMM YYYY');
    }
    isSelected(data, end = false) {
        const value = end ? this.end : this.start;
        return selectedDate(value, this.getCurrentDateObject(data), this.format, this.viewType());
    }
    isToday(data) {
        return selectedDate(this.today.format(this.format), this.getCurrentDateObject(data), this.format, this.viewType());
    }
    getCurrentDateObject({ year = this.dateViewYear, month = this.dateViewMonth, date = this.dateViewDate, day, } = {}) {
        return {
            year,
            month,
            date,
            day,
        };
    }
    /** Handle keyboard navigation in the calendar grid. */
    calendarKeyboardNavigation(event, data, disabled = false) {
        const validCodes = [
            'Enter',
            'Space',
            'ArrowRight',
            'ArrowLeft',
            'ArrowUp',
            'ArrowDown',
            'Home',
            'End',
            'PageDown',
            'PageUp',
            'Escape',
        ];
        if (!validCodes.includes(event.code))
            return;
        event.preventDefault();
        if (event.code === 'Escape')
            return this.toggleGrid(false);
        const select = !disabled && event.code.match(/^(Enter|Space)$/);
        if (select && this.viewingYears())
            return this.setViewYear({ year: data.year, reset: true });
        if (select && this.viewingMonth())
            return this.setViewMonth({ month: data.month, grid: true, reset: true });
        if (select && this.viewingCalendar())
            return this.setValue(data.date);
        const goToDate = this.navDirection(event, data);
        if (!goToDate)
            return;
        const { year, month, date } = goToDate;
        this.setViewYear({ year });
        this.setViewMonth({ month, grid: true });
        this.setViewDate({ date });
        this.resetFocus();
    }
    navDirection(event, data) {
        const { code } = event;
        const nextDate = navigateGrid(code, data, this.disableWeekends, this.viewType());
        const date = getDateObject(nextDate);
        return date;
    }
    getYearGrid() {
        const list = [];
        let oldestInList = this.viewYearStart - 7;
        for (let i = 0; 15 > i; i++) {
            list.push(oldestInList++);
        }
        return list;
    }
    /** Defaults to the calendar view. */
    setView(view) {
        this.view = view;
        requestAnimationFrame(() => this.focusCalendar());
    }
    setNavView(data) {
        if (this.viewingYears())
            return this.setViewYear({ ...data, grid: true });
        return this.setViewMonth(data);
    }
    setViewYear({ year = this.dateViewYear, minus = false, plus = false, reset = false, grid = false, }) {
        const nextYear = setYear({ year, minus, plus });
        const start = this.viewYearStart;
        const max = start + 7;
        const min = start - 7;
        if (grid) {
            const minusVal = this.viewYearStart - 15;
            const plusVal = this.viewYearStart + 15;
            this.viewYearStart = minus ? minusVal : plusVal;
            this.dateViewYear = this.viewYearStart;
        }
        else
            this.dateViewYear = nextYear;
        if (start === null || nextYear > max || min > nextYear)
            this.viewYearStart = nextYear;
        if (reset)
            this.setView(CALENDAR);
    }
    setViewMonth({ month = this.dateViewMonth, minus = false, plus = false, reset = false, grid = false, }) {
        const nextMonth = setMonth({ month, minus, plus });
        this.dateViewMonth = nextMonth;
        if (!grid && month === 0 && minus)
            this.setViewYear({ minus: true });
        if (!grid && month === 11 && plus)
            this.setViewYear({ plus: true });
        if (reset)
            this.setView(CALENDAR);
    }
    setViewDate({ date }) {
        this.dateViewDate = date;
    }
    handleSeparator(event) {
        let value = event.target.value;
        const foundSeparator = this.separators.find(({ index }) => index === value.length);
        if (foundSeparator?.name) {
            value += foundSeparator.name;
        }
        return value;
    }
    inputHandler(event, end = false) {
        const propName = end ? 'end' : 'start';
        const value = this.disableTypeAhead ? event.target.value : this.handleSeparator(event);
        this[propName] = value;
    }
    setValue(date) {
        const value = getReadableDate(this.getCurrentDateObject({ date }), this.language, this.format);
        if (this.selectingEnd)
            this.end = value;
        else
            this.start = value;
        this.setViewDate({ date });
        if (!this.range || this.selectingEnd) {
            this.toggleGrid(false);
            this.focusToggleCalendarButton();
        }
        if (this.range && !this.selectingEnd)
            this.selectingEnd = true;
    }
    getDayAttributes(dateObject, blank) {
        const data = this.getCurrentDateObject(dateObject);
        const { disabled } = this.isDisabled(data);
        if (blank)
            return { 'data-blank': true };
        function capitalize(text) {
            return text.charAt(0).toUpperCase() + text.slice(1);
        }
        const type = this.viewType();
        const value = data[type];
        const disabledProp = type !== 'date' ? 'disabled' : 'aria-disabled';
        const selectedProp = type !== 'date' ? 'aria-pressed' : 'aria-selected';
        const selectedFrom = this.isSelected(data);
        const selectedTo = this.isSelected(data, true);
        const selected = selectedFrom || selectedTo;
        const after = this.range && isAfter(data, this.start, this.format, this.viewType());
        const before = this.range && isBefore(data, this.end, this.format, this.viewType());
        const isBetween = after && before;
        const isDisabled = disabled && (type === 'date' || !selected);
        const tabbable = this[`dateView${capitalize(type)}`] === value;
        const props = {
            'onKeyDown': (e) => this.calendarKeyboardNavigation(e, data, isDisabled),
            'tabindex': tabbable ? '0' : '-1',
            [selectedProp]: (selected || isBetween)?.toString(),
            'aria-current': this.isToday(data) ? 'date' : null,
            'data-active': isDisabled ? null : selected,
            'data-today': this.isToday(data),
            'data-option': 'true',
            [`data-${type}`]: value,
            [disabledProp]: isDisabled ? 'true' : null,
        };
        const singleDate = selectedDate(this.start, this.end, this.format, 'date');
        if (this.range && !singleDate) {
            props['data-range'] = isBetween;
            props['data-range-from'] = selectedFrom && this.end !== '';
            props['data-range-to'] = selectedTo && this.start !== '';
        }
        else {
            props['data-single'] = true;
        }
        if (this.viewingCalendar())
            props.onClick = () => this.setValue(data.date);
        if (this.viewingMonth())
            props.onClick = () => this.setViewMonth({ month: data.month, reset: true });
        if (this.viewingYears())
            props.onClick = () => this.setViewYear({ year: data.year, reset: true });
        if (isDisabled)
            delete props.onClick;
        return props;
    }
    /** Focus the button toggling the calendar. Handles the start/from date on its own. */
    focusToggleCalendarButton() {
        requestAnimationFrame(() => {
            const id = this.range ? this.idEndButton : this.idStartButton;
            this.hostElement.querySelector(`#${id}`).focus({ preventScroll: true });
        });
    }
    focusCalendar() {
        requestAnimationFrame(() => {
            const element = this.calendarTabElement({ first: true, grid: true });
            element?.focus({ preventScroll: true });
        });
    }
    resetFocus() {
        if (this.open)
            return this.focusCalendar();
        else
            this.focusToggleCalendarButton();
    }
    handleButtonBlur(event) {
        if (event.code === 'Escape') {
            event.preventDefault();
            event.stopImmediatePropagation();
        }
        if (this.open && event.key === 'Tab')
            return this.focusCalendar();
    }
    /**
     * This function queries all tabbable elements inside the calendar popup.
     * Since we allow slotted content it important that we have a function that takes all elements into account.
     * With the `first` and `grid` argument, you can decide which one you want to get.
     * There are fallbacks so you should never get an empty list of elements.
     */
    calendarTabElement({ first, grid }) {
        const focusableElements = ':is(input, select, button:not([tabindex="-1"]), td[tabindex="0"])';
        const elements = this.calendarElement.querySelectorAll(focusableElements);
        const list = Array.from(elements).filter(({ localName, offsetParent }) => focusableElements.includes(localName) && offsetParent !== null);
        const gridEl = list.find(({ dataset, tabIndex }) => dataset.option && tabIndex === 0);
        if (grid && gridEl)
            return gridEl;
        if (first)
            return list.shift();
        else
            return list.pop();
    }
    /**
     * We need to listen to the `Esc` and `Tab` key for the entire calendar popup.
     * Regardless if you focus the grid, the nav buttons or slotted content,
     * the popup will close if you press `Esc`. We also need to reset the focus when the user tabs.
     */
    handleCalendarTabEsc(event) {
        const target = event.target;
        const tabElement = this.calendarTabElement({ first: event.shiftKey });
        event.stopImmediatePropagation();
        if (event.code === 'Escape') {
            event.preventDefault();
            this.toggleGrid(false);
            this.focusToggleCalendarButton();
            return;
        }
        if (event.code === 'Tab' && target.isEqualNode(tabElement)) {
            event.preventDefault();
            this.calendarTabElement({ first: !event.shiftKey }).focus({ preventScroll: true });
        }
    }
    ariaDescribedby() {
        const list = [];
        if (this.hasErrorMessage())
            list.push(this.idError);
        else if (this.hasHelperText())
            list.push(this.idHelper);
        return list.length ? list.join(' ') : null;
    }
    /** Renders the date calendar grid.  */
    renderDateGrid() {
        return (h("table", { role: "grid", class: "pn-date-picker-table", "aria-multiselectable": this.range ? 'true' : null }, h("caption", { class: "pn-date-picker-sr-only", key: this.getCurrentViewDate() }, this.getCurrentViewDate()), h("thead", { class: "pn-date-picker-thead" }, h("tr", { class: "pn-date-picker-tr" }, this.weekNumbers && h("th", { class: "pn-date-picker-th", scope: "col", "aria-hidden": "true" }), this.listWeek.map(index => (h("th", { class: "pn-date-picker-th", scope: "col", abbr: this.translateDateText({ day: index }, 'dddd') }, this.translateDateText({ day: index }, 'ddd')))))), h("tbody", { class: "pn-date-picker-tbody" }, this.grid?.map(({ week, list }) => (h("tr", { key: `${this.dateViewYear}-${week}`, class: "pn-date-picker-tr" }, this.weekNumbers && (h("td", { class: "pn-date-picker-td", "data-blank": true, "data-week": true, title: `${this.translate('WEEK_NAME')} ${week}`, "aria-hidden": "true" }, h("span", { class: "pn-date-picker-td-week" }, week))), list.map(({ day, date, blank }) => (h("td", { key: `${this.dateViewYear}-${this.dateViewMonth}-${date}`, class: "pn-date-picker-td", ...this.getDayAttributes({ date, day }, blank) }, h("span", { class: "pn-date-picker-td-text" }, date))))))))));
    }
    /** Renders the month calendar grid.  */
    renderMonthGrid() {
        return (h("ul", { class: "pn-date-picker-list" }, this.listMonths.map(month => (h("li", { key: month, class: "pn-date-picker-item", "data-item": "month" }, h("button", { type: "button", class: "pn-date-picker-button", ...this.getDayAttributes({ month }, false) }, h("span", { class: "pn-date-picker-month", "data-full": true }, this.translateDateText({ month }, 'MMMM')), h("span", { class: "pn-date-picker-month", "data-abbr": true }, this.translateDateText({ month }, 'MMM'))))))));
    }
    /** Renders the year calendar grid.  */
    renderYearGrid() {
        return (h("ul", { class: "pn-date-picker-list" }, this.getYearGrid()?.map(year => (h("li", { key: year, class: "pn-date-picker-item", "data-item": "year" }, h("button", { type: "button", class: "pn-date-picker-button", ...this.getDayAttributes({ year }, false) }, h("span", null, year)))))));
    }
    renderLabel(end = false) {
        const id = end ? this.idEnd : this.idStart;
        const label = end ? this.labelTo : this.labelFrom;
        if (!label)
            return null;
        return (h("label", { class: "pn-date-picker-label", htmlFor: id, "data-compact": this.compact }, h("span", null, label)));
    }
    renderInput({ end = false } = {}) {
        const id = end ? this.idEnd : this.idStart;
        const idButton = end ? this.idEndButton : this.idStartButton;
        const value = end ? this.end : this.start;
        const list = end ? this.listEnd : this.list;
        const name = end ? this.nameEnd : this.name;
        const editing = this.open ? (this.selectingEnd ? end : !end) : false;
        const defaultText = this.translate('SELECT_DATE');
        const textProp = this.range ? (end ? 'END_' : 'START_') : '';
        const dateText = this.translate(`SELECTED_${textProp}DATE`);
        let textButton = defaultText;
        if (value) {
            textButton += `, ${dateText.replace('{date}', value)}`;
        }
        const showButton = !(this.disabled || this.readonly);
        return (h("div", { class: "pn-date-picker-container", "data-error": this.hasError() }, !this.compact && this.renderLabel(end), h("div", { class: "pn-date-picker-field" }, h("input", { type: "text", id: id, class: "pn-date-picker-input", name: name, placeholder: this.getPlaceholder(end), autocomplete: this.autocomplete, maxlength: this.disableMaxLength ? null : this.format.length, list: list, pattern: this.pattern, value: value, disabled: this.disabled, required: this.required, readonly: this.readonly, "aria-label": this.getAriaLabel(end), "aria-labelledby": this.getAriaLabelledby(end), "aria-describedby": this.ariaDescribedby(), "aria-invalid": this.hasError()?.toString(), "data-active": editing, "data-compact": this.compact, onInput: e => this.inputHandler(e, end) }), this.compact && this.renderLabel(end), showButton && (h("pn-button", { class: "pn-date-picker-toggle", buttonId: idButton, icon: calendar, iconOnly: true, appearance: "light", arialabel: textButton, ariaexpanded: this.open.toString(), ariacontrols: this.idCalendar, "data-active": this.open, "data-input": true, small: true, onPnClick: () => this.toggleGrid(null, end), onKeyDown: e => this.handleButtonBlur(e) })))));
    }
    render() {
        return (h(Host, { key: 'dbe09316ddf6365ad119afe9fd01a363aa3cf9bf' }, h("div", { key: 'b6aa1c922859c282529ff9e1297aacc79111a0f9', class: "pn-date-picker" }, this.renderInput(), this.range && (h("div", { key: '48d050a834a2df16b33759bbe117a5c378dfa069', class: "pn-date-picker-range-icon test" }, h("pn-icon", { key: '6b6507409ba5eaf3de232dff28785d9c7c0a85f0', icon: arrow_right }))), this.range && this.renderInput({ end: this.range })), h("div", { key: '9a9d31f221aabbf0927bcc8ae602d1330d75b4d3', id: this.idCalendar, class: "pn-date-picker-calendar", role: "dialog", "aria-label": this.translate('CALENDAR_NAVIGATION'), "data-open": this.open, "data-direction": this.openUp ? 'top' : 'bottom', "data-range": this.range, style: { height: '0px' }, ref: el => (this.calendarElement = el), onKeyDown: e => this.handleCalendarTabEsc(e) }, h("div", { key: '56137ab966418bda3abd61bbcc12ff004feca5c0', class: "pn-date-picker-wrapper" }, h("nav", { key: '67a2fea072a8e4953fa9803e77d0245760b7195a', class: "pn-date-picker-nav", "aria-labelledby": this.idCalendar }, h("pn-button", { key: '9d9d0aa471baa6d6183a4b3b920cf8d05737e8a1', hidden: this.viewingMonth(), small: true, appearance: "light", arialabel: this.translate(`PREVIOUS_${this.viewType().toUpperCase()}`), icon: arrow_left, iconOnly: true, onPnClick: () => this.setNavView({ minus: true }) }), h("pn-button", { key: '57988169fdd38cb05c18c6d4f8e71ded23f97f5f', hidden: !this.viewingCalendar(), small: true, appearance: "light", onPnClick: () => this.setView(MONTHS) }, h("span", { key: '93c98b9aeabdc4b08e59afdaf8655dfe3c440b13', class: "pn-date-picker-month", "data-full": true }, this.translateDateText({ date: 1 }, 'MMMM')), h("span", { key: '9c0b0c3378f00755ef84e5e87426c1a9bedb0651', class: "pn-date-picker-month", "data-abbr": true }, this.translateDateText({ date: 1 }, 'MMM'))), h("h2", { key: '02d40d1aa03dd69f5b344295713ec9c45431b3e9', hidden: this.viewingCalendar(), class: "pn-date-picker-title" }, this.translate(`SELECT_${this.viewType().toUpperCase()}`)), h("pn-button", { key: '4f953719a89967b10c98472b24f732c42cd61e3c', hidden: !this.viewingCalendar(), small: true, appearance: "light", onPnClick: () => this.setView(YEARS) }, h("span", { key: 'a91a0dd940b94d0f71d887508644d6acfa3ef098' }, this.dateViewYear)), h("pn-button", { key: '3eabe547992de22014f3e229c9e7e17eab395d56', hidden: this.viewingMonth(), small: true, appearance: "light", arialabel: this.translate(`NEXT_${this.viewType().toUpperCase()}`), icon: arrow_right, iconOnly: true, onPnClick: () => this.setNavView({ plus: true }) })), this.viewingYears() && this.renderYearGrid(), this.viewingMonth() && this.renderMonthGrid(), this.viewingCalendar() && this.renderDateGrid(), h("aside", { key: '6eaefead16141908688578834b1e6a2ba87e8161', class: "pn-date-picker-chips" }, h("slot", { key: '43bcfa9bb50d6dbd912ae8cfee339b642b9363a5', name: "chips" })), h("nav", { key: 'b22d7112ba5d3d012f5d2617586bd251547f4ed7', class: "pn-date-picker-bottom", hidden: this.viewingCalendar() }, h("pn-button", { key: '41031640dbac5130b3fb9029b36c5e732068c78f', appearance: "light", variant: "outlined", small: true, icon: pn_return, onPnClick: () => this.setView(CALENDAR) }, h("span", { key: '08568a439547db8728c3f110c00854d49ec7eb77' }, this.translate('GO_CALENDAR')))))), h("p", { key: 'e890351198e9eaa85e9db3bcc55bc8bdd48f3538', id: this.idHelper, class: "pn-date-picker-helpertext", hidden: this.hideHelpertext() }, h("span", { key: '0b776595b33ed64cb73b5060d023eb89421ad758' }, this.helpertext), h("slot", { key: 'e9ef3797e3baae78dca7efc2313e1b6cf9c7efd7', name: "helpertext" })), h("p", { key: 'aa43fb6eaf42251bb7dadab0f724edee0e6d42b2', id: this.idError, class: "pn-date-picker-error", role: "alert", hidden: this.hideError() }, h("span", { key: '556bfbb5e5ba697234734eb601445150b23ddcf2' }, this.error), h("slot", { key: '21dd12fd2c3f1ac814699f4785ece567136cedd2', name: "error" }))));
    }
    static get is() { return "pn-date-picker"; }
    static get originalStyleUrls() {
        return {
            "$": ["pn-date-picker.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pn-date-picker.css"]
        };
    }
    static get properties() {
        return {
            "labelFrom": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Set a label for the from date."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "label-from"
            },
            "labelTo": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link range }"
                        }],
                    "text": "Set a label for the to date."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "label-to"
            },
            "helpertext": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Provide a helpertext for the date input."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "helpertext"
            },
            "language": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "PnLanguages",
                    "resolved": "\"\" | \"da\" | \"en\" | \"fi\" | \"no\" | \"sv\"",
                    "references": {
                        "PnLanguages": {
                            "location": "import",
                            "path": "@/index",
                            "id": "src/index.ts::PnLanguages",
                            "referenceLocation": "PnLanguages"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Manually set language; this will be inherited from the topbar."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "language",
                "defaultValue": "undefined"
            },
            "start": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set a predefined value for the from date (input value)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "start",
                "defaultValue": "''"
            },
            "end": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link range }"
                        }, {
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set a predefined value for the from date. (input value end)"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "end",
                "defaultValue": "''"
            },
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "HTML input name"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "name"
            },
            "nameEnd": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "HTML input name"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "name-end"
            },
            "placeholder": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Placeholder for the input field (defaults to the format prop)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "placeholder"
            },
            "endPlaceholder": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "deprecated",
                            "text": "Use `placeholder-end` instead"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Placeholder for end date (defaults to the format prop)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "end-placeholder"
            },
            "placeholderEnd": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Placeholder for end date (defaults to the format prop)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "placeholder-end"
            },
            "autocomplete": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the input `autocomplete` attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "autocomplete"
            },
            "list": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the input `list` attribute for the first date input."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "list"
            },
            "listEnd": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the input `list` attribute for the second date input."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "list-end"
            },
            "pattern": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the HTML pattern prop on the input elements. Make sure it matches the format."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pattern"
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the date picker as required."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "required",
                "defaultValue": "false"
            },
            "readonly": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the date picker as readonly."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "readonly",
                "defaultValue": "false"
            },
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Native attributes"
                        }],
                    "text": "Set the date picker as disabled."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "format": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "see",
                            "text": "{@link https://day.js.org/docs/en/display/format Day.js format documentation.}"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Set the date format of the value.\n\nWhile you can set any date value from the Dayjs documentation,\nwe strongly recommend you pick a simple format that you can also type manually."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "format",
                "defaultValue": "'YYYY-MM-DD'"
            },
            "disableTypeAhead": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Disable the automatic insertion of separators when typing in the input."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-type-ahead",
                "defaultValue": "false"
            },
            "disableWeekends": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Remove the option to select dates on weekends."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-weekends",
                "defaultValue": "false"
            },
            "disabledDates": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "example",
                            "text": "\"YYYY-MM-DD,YYYY-MM-DD\""
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Individual dates you want to disable. Use a comma separated string.\n\nRemember to use the same format that you have in the `format` prop."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disabled-dates"
            },
            "disableMaxLength": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "7.11.3"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "If you use a format with an unknown length, disable the max length."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-max-length",
                "defaultValue": "false"
            },
            "range": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Allow the selection of a date range."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "range",
                "defaultValue": "false"
            },
            "rangeLimit": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "todo",
                            "text": "Create a range limit function."
                        }, {
                            "name": "see",
                            "text": "{@link range }"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }, {
                            "name": "hide",
                            "text": "true"
                        }],
                    "text": "Set a limit on how many days one may select.\nBy default, you can select an unlimited range."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "range-limit"
            },
            "weekNumbers": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Show weekend numbers to the left of the calendar grid."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "week-numbers",
                "defaultValue": "false"
            },
            "compact": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.21.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Set the date picker label as compact. If used, the `placeholder` will no longer be displayed."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "compact",
                "defaultValue": "false"
            },
            "calendarUp": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Make the calendar open upwards by default. Opens downwards if there is not enough space."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "calendar-up",
                "defaultValue": "false"
            },
            "view": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "CalendarView",
                    "resolved": "\"calendar\" | \"months\" | \"years\"",
                    "references": {
                        "CalendarView": {
                            "location": "import",
                            "path": "@/globals/date",
                            "id": "src/globals/date/index.ts::CalendarView",
                            "referenceLocation": "CalendarView"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "The calendar grid is shown as default. You can set either `months` or `years` as your first choice."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "view",
                "defaultValue": "'calendar'"
            },
            "invalid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Trigger the invalid state without an error message."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "invalid",
                "defaultValue": "false"
            },
            "error": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Set an error message for the date picker. Overwrites the helpertext if used at the same time."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "error"
            },
            "pnId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Set a custom ID for the calendar. If you use `range`, the end input will use `${pn-id}-end`."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pn-id"
            },
            "pnAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Provide the label via an aria attribute.\nWe strongly recommend you use the `label-from` prop instead."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pn-aria-label"
            },
            "pnAriaLabelEnd": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Provide the label for the end input via an aria attribute.\nWe strongly recommend you use the `label-to` prop instead."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pn-aria-label-end"
            },
            "pnAriaLabelledby": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Provide the label from another element via its ID.\nWe strongly recommend you use the `label-from` prop instead."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pn-aria-labelledby"
            },
            "pnAriaLabelledbyEnd": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.25.0"
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Provide the label for the end input from another element via its ID.\nWe strongly recommend you use the `label-to` prop instead."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "pn-aria-labelledby-end"
            },
            "dateId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }, {
                            "name": "deprecated",
                            "text": "Use `pn-id` instead."
                        }, {
                            "name": "category",
                            "text": "HTML attributes"
                        }],
                    "text": "Set a custom ID for the calendar."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "date-id"
            },
            "minDate": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "example",
                            "text": "\"2024-05-25\""
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Earliest date possible, this will determine how many years back the date picker will show.\n\nRemember to use the same format that you have in the `format` prop."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "min-date",
                "defaultValue": "null"
            },
            "maxDate": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "see",
                            "text": "{@link format }"
                        }, {
                            "name": "example",
                            "text": "\"2024-06-25\""
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Latest date possible, this will determine how many years forward the date picker will show.\n\nRemember to use the same format that you have in the `format` prop."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "max-date",
                "defaultValue": "null"
            }
        };
    }
    static get states() {
        return {
            "open": {},
            "openUp": {},
            "selectingEnd": {},
            "grid": {},
            "viewYearStart": {},
            "dateViewYear": {},
            "dateViewMonth": {},
            "dateViewDate": {},
            "showHelperSlot": {},
            "showErrorSlot": {}
        };
    }
    static get events() {
        return [{
                "method": "dateselection",
                "name": "dateselection",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "deprecated",
                            "text": "Use the new `dateSelection`. Will be removed in v8."
                        }],
                    "text": "Use the new `dateSelection`. Its here for compatibility. Will be removed in v8."
                },
                "complexType": {
                    "original": "PnDatePickerSelectEvent",
                    "resolved": "{ start: string; end?: string; days?: number; }",
                    "references": {
                        "PnDatePickerSelectEvent": {
                            "location": "import",
                            "path": "@/globals/date",
                            "id": "src/globals/date/index.ts::PnDatePickerSelectEvent",
                            "referenceLocation": "PnDatePickerSelectEvent"
                        }
                    }
                }
            }, {
                "method": "dateSelection",
                "name": "dateSelection",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }],
                    "text": "Emits on valid date selection. Either if the user selects a date in the calendar or writes it manually."
                },
                "complexType": {
                    "original": "PnDatePickerSelectEvent",
                    "resolved": "{ start: string; end?: string; days?: number; }",
                    "references": {
                        "PnDatePickerSelectEvent": {
                            "location": "import",
                            "path": "@/globals/date",
                            "id": "src/globals/date/index.ts::PnDatePickerSelectEvent",
                            "referenceLocation": "PnDatePickerSelectEvent"
                        }
                    }
                }
            }, {
                "method": "dateInvalid",
                "name": "dateInvalid",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }],
                    "text": "Emitted when an invalid value is set. This can only be done if the user writes in the input itself."
                },
                "complexType": {
                    "original": "{ start?: string; end?: string }",
                    "resolved": "{ start?: string; end?: string; }",
                    "references": {}
                }
            }, {
                "method": "toggleCalendar",
                "name": "toggleCalendar",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }],
                    "text": "Emitted when the calendar is toggled."
                },
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                }
            }, {
                "method": "currentView",
                "name": "currentView",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.6.0"
                        }],
                    "text": "Emmitted when you select a new view."
                },
                "complexType": {
                    "original": "CalendarView",
                    "resolved": "\"calendar\" | \"months\" | \"years\"",
                    "references": {
                        "CalendarView": {
                            "location": "import",
                            "path": "@/globals/date",
                            "id": "src/globals/date/index.ts::CalendarView",
                            "referenceLocation": "CalendarView"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "hostElement"; }
    static get watchers() {
        return [{
                "propName": "minDate",
                "methodName": "watchMin",
                "handlerOptions": {
                    "immediate": true
                }
            }, {
                "propName": "maxDate",
                "methodName": "watchMax",
                "handlerOptions": {
                    "immediate": true
                }
            }, {
                "propName": "start",
                "methodName": "watchValue"
            }, {
                "propName": "end",
                "methodName": "watchValueTo"
            }, {
                "propName": "format",
                "methodName": "handleFormat"
            }, {
                "propName": "dateId",
                "methodName": "watchId"
            }, {
                "propName": "pnId",
                "methodName": "watchId",
                "handlerOptions": {
                    "immediate": true
                }
            }, {
                "propName": "dateViewYear",
                "methodName": "watchView"
            }, {
                "propName": "dateViewMonth",
                "methodName": "watchView"
            }, {
                "propName": "dateViewDate",
                "methodName": "watchView"
            }, {
                "propName": "open",
                "methodName": "watchOpen"
            }, {
                "propName": "helpertext",
                "methodName": "handleMessage"
            }, {
                "propName": "error",
                "methodName": "handleMessage"
            }, {
                "propName": "view",
                "methodName": "handleView"
            }];
    }
    static get listeners() {
        return [{
                "name": "resize",
                "method": "handleResize",
                "target": "window",
                "capture": false,
                "passive": true
            }];
    }
}