UNPKG

primeng

Version:

PrimeNG is a premium UI library for Angular featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock,

1,170 lines (1,167 loc) 227 kB
export * from 'primeng/types/datepicker'; import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common'; import * as i0 from '@angular/core'; import { Injectable, forwardRef, InjectionToken, inject, input, booleanAttribute, numberAttribute, computed, output, viewChild, signal, contentChild, effect, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Calendar } from '@primeicons/angular/calendar'; import { ChevronDown } from '@primeicons/angular/chevron-down'; import { ChevronLeft } from '@primeicons/angular/chevron-left'; import { ChevronRight } from '@primeicons/angular/chevron-right'; import { ChevronUp } from '@primeicons/angular/chevron-up'; import { Times } from '@primeicons/angular/times'; import { uuid, getOuterWidth, isDate, hasClass, findSingle, getFocusableElements, getIndex, find, isNotEmpty, addStyle, appendChild, absolutePosition, relativePosition, addClass, setAttribute, isTouchDevice } from '@primeuix/utils'; import { OverlayService, TranslationKeys, SharedModule } from 'primeng/api'; import { AutoFocus } from 'primeng/autofocus'; import { PARENT_INSTANCE } from 'primeng/basecomponent'; import { BaseInput } from 'primeng/baseinput'; import * as i1 from 'primeng/bind'; import { Bind, BindModule } from 'primeng/bind'; import { ButtonDirective } from 'primeng/button'; import { blockBodyScroll, unblockBodyScroll, ConnectedOverlayScrollHandler } from 'primeng/dom'; import { InputText } from 'primeng/inputtext'; import * as i2 from 'primeng/motion'; import { MotionModule } from 'primeng/motion'; import { Ripple } from 'primeng/ripple'; import { ZIndexUtils } from 'primeng/utils'; import { style } from '@primeuix/styles/datepicker'; import { BaseStyle } from 'primeng/base'; const inlineStyles = { root: () => ({ position: 'relative' }) }; const classes = { root: ({ instance }) => [ 'p-datepicker p-component p-inputwrapper', { 'p-invalid': instance.invalid(), 'p-inputwrapper-filled': instance.$filled(), 'p-inputwrapper-focus': instance.focus() || instance.overlayVisible(), 'p-focus': instance.focus() || instance.overlayVisible(), 'p-datepicker-fluid': instance.hasFluid } ], pcInputText: 'p-datepicker-input', clearIcon: 'p-datepicker-clear-icon', dropdown: 'p-datepicker-dropdown', inputIconContainer: 'p-datepicker-input-icon-container', inputIcon: 'p-datepicker-input-icon', panel: ({ instance }) => [ 'p-datepicker-panel p-component', { 'p-datepicker-panel p-component': true, 'p-datepicker-panel-inline': instance.inline(), 'p-disabled': instance.$disabled(), 'p-datepicker-timeonly': instance.timeOnly() } ], calendarContainer: 'p-datepicker-calendar-container', calendar: 'p-datepicker-calendar', header: 'p-datepicker-header', pcPrevButton: 'p-datepicker-prev-button', title: 'p-datepicker-title', selectMonth: 'p-datepicker-select-month', selectYear: 'p-datepicker-select-year', decade: 'p-datepicker-decade', pcNextButton: 'p-datepicker-next-button', dayView: 'p-datepicker-day-view', weekHeader: 'p-datepicker-weekheader p-disabled', weekNumber: 'p-datepicker-weeknumber', weekLabelContainer: 'p-datepicker-weeklabel-container p-disabled', weekDayCell: 'p-datepicker-weekday-cell', weekDay: 'p-datepicker-weekday', dayCell: ({ date }) => [ 'p-datepicker-day-cell', { 'p-datepicker-other-month': date.otherMonth, 'p-datepicker-today': date.today } ], day: ({ instance, date }) => { let selectedDayClass = ''; if (instance.isRangeSelection() && instance.isSelected(date) && date.selectable) { const startDate = instance.value[0]; const endDate = instance.value[1]; const isStart = startDate && date.year === startDate.getFullYear() && date.month === startDate.getMonth() && date.day === startDate.getDate(); const isEnd = endDate && date.year === endDate.getFullYear() && date.month === endDate.getMonth() && date.day === endDate.getDate(); selectedDayClass = isStart || isEnd ? 'p-datepicker-day-selected' : 'p-datepicker-day-selected-range'; } return { 'p-datepicker-day': true, 'p-datepicker-day-selected': !instance.isRangeSelection() && instance.isSelected(date) && date.selectable, 'p-disabled': instance.$disabled() || !date.selectable, [selectedDayClass]: true }; }, monthView: 'p-datepicker-month-view', month: ({ instance, index }) => [ 'p-datepicker-month', { 'p-datepicker-month-selected': instance.isMonthSelected(index), 'p-disabled': instance.isMonthDisabled(index) } ], yearView: 'p-datepicker-year-view', year: ({ instance, year }) => [ 'p-datepicker-year', { 'p-datepicker-year-selected': instance.isYearSelected(year), 'p-disabled': instance.isYearDisabled(year) } ], timePicker: 'p-datepicker-time-picker', hourPicker: 'p-datepicker-hour-picker', pcIncrementButton: 'p-datepicker-increment-button', pcDecrementButton: 'p-datepicker-decrement-button', separator: 'p-datepicker-separator', minutePicker: 'p-datepicker-minute-picker', secondPicker: 'p-datepicker-second-picker', ampmPicker: 'p-datepicker-ampm-picker', buttonbar: 'p-datepicker-buttonbar', pcTodayButton: 'p-datepicker-today-button', pcClearButton: 'p-datepicker-clear-button' }; class DatePickerStyle extends BaseStyle { name = 'datepicker'; style = style; classes = classes; inlineStyles = inlineStyles; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DatePickerStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DatePickerStyle }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DatePickerStyle, decorators: [{ type: Injectable }] }); /** * * DatePicker is a form component to work with dates. * * [Live Demo](https://www.primeng.org/datepicker/) * * @module datepickerstyle * */ var DatePickerClasses; (function (DatePickerClasses) { /** * Class name of the root element */ DatePickerClasses["root"] = "p-datepicker"; /** * Class name of the input element */ DatePickerClasses["pcInputText"] = "p-datepicker-input"; /** * Class name of the dropdown element */ DatePickerClasses["dropdown"] = "p-datepicker-dropdown"; /** * Class name of the input icon container element */ DatePickerClasses["inputIconContainer"] = "p-datepicker-input-icon-container"; /** * Class name of the input icon element */ DatePickerClasses["inputIcon"] = "p-datepicker-input-icon"; /** * Class name of the panel element */ DatePickerClasses["panel"] = "p-datepicker-panel"; /** * Class name of the calendar container element */ DatePickerClasses["calendarContainer"] = "p-datepicker-calendar-container"; /** * Class name of the calendar element */ DatePickerClasses["calendar"] = "p-datepicker-calendar"; /** * Class name of the header element */ DatePickerClasses["header"] = "p-datepicker-header"; /** * Class name of the previous button element */ DatePickerClasses["pcPrevButton"] = "p-datepicker-prev-button"; /** * Class name of the title element */ DatePickerClasses["title"] = "p-datepicker-title"; /** * Class name of the select month element */ DatePickerClasses["selectMonth"] = "p-datepicker-select-month"; /** * Class name of the select year element */ DatePickerClasses["selectYear"] = "p-datepicker-select-year"; /** * Class name of the decade element */ DatePickerClasses["decade"] = "p-datepicker-decade"; /** * Class name of the next button element */ DatePickerClasses["pcNextButton"] = "p-datepicker-next-button"; /** * Class name of the day view element */ DatePickerClasses["dayView"] = "p-datepicker-day-view"; /** * Class name of the week header element */ DatePickerClasses["weekHeader"] = "p-datepicker-weekheader"; /** * Class name of the week number element */ DatePickerClasses["weekNumber"] = "p-datepicker-weeknumber"; /** * Class name of the week label container element */ DatePickerClasses["weekLabelContainer"] = "p-datepicker-weeklabel-container"; /** * Class name of the week day cell element */ DatePickerClasses["weekDayCell"] = "p-datepicker-weekday-cell"; /** * Class name of the week day element */ DatePickerClasses["weekDay"] = "p-datepicker-weekday"; /** * Class name of the day cell element */ DatePickerClasses["dayCell"] = "p-datepicker-day-cell"; /** * Class name of the day element */ DatePickerClasses["day"] = "p-datepicker-day"; /** * Class name of the month view element */ DatePickerClasses["monthView"] = "p-datepicker-month-view"; /** * Class name of the month element */ DatePickerClasses["month"] = "p-datepicker-month"; /** * Class name of the year view element */ DatePickerClasses["yearView"] = "p-datepicker-year-view"; /** * Class name of the year element */ DatePickerClasses["year"] = "p-datepicker-year"; /** * Class name of the time picker element */ DatePickerClasses["timePicker"] = "p-datepicker-time-picker"; /** * Class name of the hour picker element */ DatePickerClasses["hourPicker"] = "p-datepicker-hour-picker"; /** * Class name of the increment button element */ DatePickerClasses["pcIncrementButton"] = "p-datepicker-increment-button"; /** * Class name of the decrement button element */ DatePickerClasses["pcDecrementButton"] = "p-datepicker-decrement-button"; /** * Class name of the separator element */ DatePickerClasses["separator"] = "p-datepicker-separator"; /** * Class name of the minute picker element */ DatePickerClasses["minutePicker"] = "p-datepicker-minute-picker"; /** * Class name of the second picker element */ DatePickerClasses["secondPicker"] = "p-datepicker-second-picker"; /** * Class name of the ampm picker element */ DatePickerClasses["ampmPicker"] = "p-datepicker-ampm-picker"; /** * Class name of the buttonbar element */ DatePickerClasses["buttonbar"] = "p-datepicker-buttonbar"; /** * Class name of the today button element */ DatePickerClasses["pcTodayButton"] = "p-datepicker-today-button"; /** * Class name of the clear button element */ DatePickerClasses["pcClearButton"] = "p-datepicker-clear-button"; /** * Class name of the clear icon */ DatePickerClasses["clearIcon"] = "p-datepicker-clear-icon"; })(DatePickerClasses || (DatePickerClasses = {})); const DATEPICKER_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DatePicker), multi: true }; const DATEPICKER_INSTANCE = new InjectionToken('DATEPICKER_INSTANCE'); /** * DatePicker is a form component to work with dates. * @group Components */ class DatePicker extends BaseInput { componentName = 'DatePicker'; bindDirectiveInstance = inject(Bind, { self: true }); $pcDatePicker = inject(DATEPICKER_INSTANCE, { optional: true, skipSelf: true }) ?? undefined; /** * Icon display mode. * @group Props */ iconDisplay = input('button', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "iconDisplay" }] : /* istanbul ignore next */ [])); /** * Inline style of the input field. * @group Props */ inputStyle = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputStyle" }] : /* istanbul ignore next */ [])); /** * Identifier of the focus input to match a label defined for the component. * @group Props */ inputId = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputId" }] : /* istanbul ignore next */ [])); /** * Style class of the input field. * @group Props */ inputStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "inputStyleClass" }] : /* istanbul ignore next */ [])); /** * Placeholder text for the input. * @group Props */ placeholder = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ [])); /** * Establishes relationships between the component and label(s) where its value should be one or more element IDs. * @group Props */ ariaLabelledBy = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ [])); /** * Defines a string that labels the input for accessibility. * @group Props */ ariaLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ [])); /** * Defines a string that labels the icon button for accessibility. * @group Props */ iconAriaLabel = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "iconAriaLabel" }] : /* istanbul ignore next */ [])); /** * Format of the date which can also be defined at locale settings. * @group Props */ dateFormat = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "dateFormat" }] : /* istanbul ignore next */ [])); /** * Separator for multiple selection mode. * @group Props */ multipleSeparator = input(',', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "multipleSeparator" }] : /* istanbul ignore next */ [])); /** * Separator for joining start and end dates on range selection mode. * @group Props */ rangeSeparator = input('-', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "rangeSeparator" }] : /* istanbul ignore next */ [])); /** * When enabled, displays the datepicker as inline. Default is false for popup mode. * @group Props */ inline = input(false, { ...(ngDevMode ? { debugName: "inline" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether to display dates in other months (non-selectable) at the start or end of the current month. To make these days selectable use the selectOtherMonths option. * @group Props */ showOtherMonths = input(true, { ...(ngDevMode ? { debugName: "showOtherMonths" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether days in other months shown before or after the current month are selectable. This only applies if the showOtherMonths option is set to true. * @group Props */ selectOtherMonths = input(undefined, { ...(ngDevMode ? { debugName: "selectOtherMonths" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, displays a button with icon next to input. * @group Props */ showIcon = input(undefined, { ...(ngDevMode ? { debugName: "showIcon" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Icon of the datepicker button. * @group Props */ icon = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ [])); /** * When specified, prevents entering the date manually with keyboard. * @group Props */ readonlyInput = input(undefined, { ...(ngDevMode ? { debugName: "readonlyInput" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * The cutoff year for determining the century for a date. * @group Props */ shortYearCutoff = input('+10', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "shortYearCutoff" }] : /* istanbul ignore next */ [])); /** * Specifies 12 or 24 hour format. * @group Props */ hourFormat = input('24', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "hourFormat" }] : /* istanbul ignore next */ [])); /** * Whether to display timepicker only. * @group Props */ timeOnly = input(undefined, { ...(ngDevMode ? { debugName: "timeOnly" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Hours to change per step. * @group Props */ stepHour = input(1, { ...(ngDevMode ? { debugName: "stepHour" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Minutes to change per step. * @group Props */ stepMinute = input(1, { ...(ngDevMode ? { debugName: "stepMinute" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Seconds to change per step. * @group Props */ stepSecond = input(1, { ...(ngDevMode ? { debugName: "stepSecond" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Whether to show the seconds in time picker. * @group Props */ showSeconds = input(false, { ...(ngDevMode ? { debugName: "showSeconds" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When disabled, datepicker will not be visible with input focus. * @group Props */ showOnFocus = input(true, { ...(ngDevMode ? { debugName: "showOnFocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, datepicker will show week numbers. * @group Props */ showWeek = input(false, { ...(ngDevMode ? { debugName: "showWeek" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, datepicker will start week numbers from first day of the year. * @group Props */ startWeekFromFirstDayOfYear = input(false, { ...(ngDevMode ? { debugName: "startWeekFromFirstDayOfYear" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, a clear icon is displayed to clear the value. * @group Props */ showClear = input(false, { ...(ngDevMode ? { debugName: "showClear" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Type of the value to write back to ngModel, default is date and alternative is string. * @group Props */ dataType = input('date', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "dataType" }] : /* istanbul ignore next */ [])); /** * Defines the quantity of the selection, valid values are "single", "multiple" and "range". * @group Props */ selectionMode = input('single', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "selectionMode" }] : /* istanbul ignore next */ [])); /** * Maximum number of selectable dates in multiple mode. * @group Props */ maxDateCount = input(undefined, { ...(ngDevMode ? { debugName: "maxDateCount" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Whether to display today and clear buttons at the footer * @group Props */ showButtonBar = input(undefined, { ...(ngDevMode ? { debugName: "showButtonBar" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Style class of the today button. * @group Props */ todayButtonStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "todayButtonStyleClass" }] : /* istanbul ignore next */ [])); /** * Style class of the clear button. * @group Props */ clearButtonStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "clearButtonStyleClass" }] : /* istanbul ignore next */ [])); /** * When present, it specifies that the component should automatically get focus on load. * @group Props */ autofocus = input(undefined, { ...(ngDevMode ? { debugName: "autofocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether to automatically manage layering. * @group Props */ autoZIndex = input(true, { ...(ngDevMode ? { debugName: "autoZIndex" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Base zIndex value to use in layering. * @group Props */ baseZIndex = input(0, { ...(ngDevMode ? { debugName: "baseZIndex" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Style class of the datetimepicker container element. * @group Props */ panelStyleClass = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "panelStyleClass" }] : /* istanbul ignore next */ [])); /** * Inline style of the datetimepicker container element. * @group Props */ panelStyle = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "panelStyle" }] : /* istanbul ignore next */ [])); /** * Keep invalid value when input blur. * @group Props */ keepInvalid = input(false, { ...(ngDevMode ? { debugName: "keepInvalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Whether to hide the overlay on date selection. * @group Props */ hideOnDateTimeSelect = input(true, { ...(ngDevMode ? { debugName: "hideOnDateTimeSelect" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * When enabled, datepicker overlay is displayed as optimized for touch devices. * @group Props */ touchUI = input(undefined, { ...(ngDevMode ? { debugName: "touchUI" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Separator of time selector. * @group Props */ timeSeparator = input(':', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "timeSeparator" }] : /* istanbul ignore next */ [])); /** * When enabled, can only focus on elements inside the datepicker. * @group Props */ focusTrap = input(true, { ...(ngDevMode ? { debugName: "focusTrap" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * Index of the element in tabbing order. * @group Props */ tabindex = input(undefined, { ...(ngDevMode ? { debugName: "tabindex" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * The minimum selectable date. * @group Props */ minDate = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "minDate" }] : /* istanbul ignore next */ [])); /** * The maximum selectable date. * @group Props */ maxDate = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "maxDate" }] : /* istanbul ignore next */ [])); /** * Array with dates that should be disabled (not selectable). * @group Props */ disabledDates = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "disabledDates" }] : /* istanbul ignore next */ [])); /** * Array with weekday numbers that should be disabled (not selectable). * @group Props */ disabledDays = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "disabledDays" }] : /* istanbul ignore next */ [])); /** * Whether to display timepicker. * @group Props */ showTime = input(false, { ...(ngDevMode ? { debugName: "showTime" } : /* istanbul ignore next */ {}), transform: booleanAttribute }); /** * An array of options for responsive design. * @group Props */ responsiveOptions = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "responsiveOptions" }] : /* istanbul ignore next */ [])); /** * Number of months to display. * @group Props */ numberOfMonths = input(1, { ...(ngDevMode ? { debugName: "numberOfMonths" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Defines the first of the week for various date calculations. * @group Props */ firstDayOfWeek = input(undefined, { ...(ngDevMode ? { debugName: "firstDayOfWeek" } : /* istanbul ignore next */ {}), transform: numberAttribute }); /** * Type of view to display, valid values are "date" for datepicker and "month" for month picker. * @group Props */ view = input('date', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ [])); /** * Set the date to highlight on first opening if the field is blank. * @group Props */ defaultDate = input(/* @ts-ignore */ ...(ngDevMode ? [undefined, { debugName: "defaultDate" }] : /* istanbul ignore next */ [])); /** * Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]="mydiv" for a div element having #mydiv as variable name). * @defaultValue 'self' * @group Props */ appendTo = input(undefined, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ [])); /** * The motion options. * @group Props */ motionOptions = input(undefined, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "motionOptions" }] : /* istanbul ignore next */ [])); computedMotionOptions = computed(() => { return { ...this.ptm('motion'), ...this.motionOptions() }; }, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "computedMotionOptions" }] : /* istanbul ignore next */ [])); /** * Callback to invoke on focus of input field. * @param {Event} event - browser event. * @group Emits */ onFocus = output(); /** * Callback to invoke on blur of input field. * @param {Event} event - browser event. * @group Emits */ onBlur = output(); /** * Callback to invoke when date panel closed. * @param {HTMLDivElement} element - The element being transitioned/animated. * @group Emits */ onClose = output(); /** * Callback to invoke on date select. * @param {Date} date - date value. * @group Emits */ onSelect = output(); /** * Callback to invoke when input field cleared. * @group Emits */ onClear = output(); /** * Callback to invoke when input field is being typed. * @param {Event} event - browser event * @group Emits */ onInput = output(); /** * Callback to invoke when today button is clicked. * @param {Date} date - today as a date instance. * @group Emits */ onTodayClick = output(); /** * Callback to invoke when clear button is clicked. * @param {Event} event - browser event. * @group Emits */ onClearClick = output(); /** * Callback to invoke when a month is changed using the navigators. * @param {DatePickerMonthChangeEvent} event - custom month change event. * @group Emits */ onMonthChange = output(); /** * Callback to invoke when a year is changed using the navigators. * @param {DatePickerYearChangeEvent} event - custom year change event. * @group Emits */ onYearChange = output(); /** * Callback to invoke when clicked outside of the date panel. * @group Emits */ onClickOutside = output(); /** * Callback to invoke when datepicker panel is shown. * @param {HTMLDivElement} element - The element being transitioned/animated. * @group Emits */ onShow = output(); inputfieldViewChild = viewChild('inputfield', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "inputfieldViewChild" }] : /* istanbul ignore next */ [])); contentWrapperViewChild = viewChild('contentWrapper', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "contentWrapperViewChild" }] : /* istanbul ignore next */ [])); _componentStyle = inject(DatePickerStyle); contentViewChild = computed(() => this.contentWrapperViewChild(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "contentViewChild" }] : /* istanbul ignore next */ [])); value; dates; months = signal([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "months" }] : /* istanbul ignore next */ [])); weekDays = signal([], /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "weekDays" }] : /* istanbul ignore next */ [])); currentMonth; currentYear; currentHour = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "currentHour" }] : /* istanbul ignore next */ [])); currentMinute = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "currentMinute" }] : /* istanbul ignore next */ [])); currentSecond = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "currentSecond" }] : /* istanbul ignore next */ [])); formattedHour = computed(() => String(this.currentHour() ?? 0).padStart(2, '0'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "formattedHour" }] : /* istanbul ignore next */ [])); formattedMinute = computed(() => String(this.currentMinute() ?? 0).padStart(2, '0'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "formattedMinute" }] : /* istanbul ignore next */ [])); formattedSecond = computed(() => String(this.currentSecond() ?? 0).padStart(2, '0'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "formattedSecond" }] : /* istanbul ignore next */ [])); onButtonClickCallback = this.onButtonClick.bind(this); onTodayButtonClickCallback = this.onTodayButtonClick.bind(this); onClearButtonClickCallback = this.onClearButtonClick.bind(this); inputIconTemplateContext = computed(() => ({ clickCallBack: this.onButtonClickCallback }), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "inputIconTemplateContext" }] : /* istanbul ignore next */ [])); decadeTemplateContext = computed(() => ({ $implicit: this.yearPickerValues }), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "decadeTemplateContext" }] : /* istanbul ignore next */ [])); buttonBarTemplateContext = computed(() => ({ todayCallback: this.onTodayButtonClickCallback, clearCallback: this.onClearButtonClickCallback }), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "buttonBarTemplateContext" }] : /* istanbul ignore next */ [])); getDateTemplateContext(date) { return { $implicit: date, selected: !!this.isSelected(date) }; } pm = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "pm" }] : /* istanbul ignore next */ [])); mask; maskClickListener; overlay; responsiveStyleElement; overlayVisible = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "overlayVisible" }] : /* istanbul ignore next */ [])); overlayRendered = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "overlayRendered" }] : /* istanbul ignore next */ [])); overlayMinWidth; $appendTo = computed(() => this.appendTo() || this.config.overlayAppendTo(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "$appendTo" }] : /* istanbul ignore next */ [])); calendarElement; timePickerTimer; documentClickListener; animationEndListener; ticksTo1970; yearOptions; focus = signal(false, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "focus" }] : /* istanbul ignore next */ [])); isKeydown; preventDocumentListener; requiredAttr = computed(() => (this.required() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "requiredAttr" }] : /* istanbul ignore next */ [])); readonlyAttr = computed(() => (this.readonlyInput() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "readonlyAttr" }] : /* istanbul ignore next */ [])); disabledAttr = computed(() => (this.$disabled() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "disabledAttr" }] : /* istanbul ignore next */ [])); switchViewButtonDisabledAttr = computed(() => (this.switchViewButtonDisabled() ? '' : undefined), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "switchViewButtonDisabledAttr" }] : /* istanbul ignore next */ [])); inputModeAttr = computed(() => (this.touchUI() ? 'off' : null), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "inputModeAttr" }] : /* istanbul ignore next */ [])); /** * The clear icon stays in the DOM whenever clearing is enabled — hidden via * `visibility` while there is no value — so the base `:has(.p-datepicker-clear-icon)` * rules reserve its footprint constantly and the control width does not jump * when the icon appears (#6). */ clearIconEnabled = computed(() => this.showClear() && !this.$disabled(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "clearIconEnabled" }] : /* istanbul ignore next */ [])); showClearIcon = computed(() => this.showClear() && !this.$disabled() && !!this.inputFieldValue(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showClearIcon" }] : /* istanbul ignore next */ [])); showIconButton = computed(() => this.showIcon() && this.iconDisplay() === 'button', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showIconButton" }] : /* istanbul ignore next */ [])); showInputIcon = computed(() => this.iconDisplay() === 'input' && this.showIcon(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showInputIcon" }] : /* istanbul ignore next */ [])); showTimePicker = computed(() => (this.showTime() || this.timeOnly()) && this.currentView() === 'date', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "showTimePicker" }] : /* istanbul ignore next */ [])); isHourFormat12 = computed(() => this.hourFormat() == '12', /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isHourFormat12" }] : /* istanbul ignore next */ [])); ariaControlsAttr = computed(() => (this.overlayVisible() ? this.panelId : null), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "ariaControlsAttr" }] : /* istanbul ignore next */ [])); isOverlayVisible = computed(() => this.inline() || this.overlayVisible(), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "isOverlayVisible" }] : /* istanbul ignore next */ [])); roleAttr = computed(() => (this.inline() ? null : 'dialog'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "roleAttr" }] : /* istanbul ignore next */ [])); ariaModalAttr = computed(() => (this.inline() ? null : 'true'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "ariaModalAttr" }] : /* istanbul ignore next */ [])); ampmLabel = computed(() => (this.pm() ? 'PM' : 'AM'), /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "ampmLabel" }] : /* istanbul ignore next */ [])); dayClass(date) { return this._componentStyle.classes.day({ instance: this, date: date }); } getPrevButtonStyle(index) { return { visibility: index === 0 ? 'visible' : 'hidden' }; } getNextButtonStyle(index) { return { visibility: index === this.months().length - 1 ? 'visible' : 'hidden' }; } /** * Custom template for date cells. * @param {DatePickerDateTemplateContext} context - date template context. * @group Templates */ dateTemplate = contentChild('date', { ...(ngDevMode ? { debugName: "dateTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for header section. * @group Templates */ headerTemplate = contentChild('header', { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for footer section. * @group Templates */ footerTemplate = contentChild('footer', { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for disabled date cells. * @param {DatePickerDisabledDateTemplateContext} context - disabled date template context. * @group Templates */ disabledDateTemplate = contentChild('disabledDate', { ...(ngDevMode ? { debugName: "disabledDateTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for decade view. * @param {DatePickerDecadeTemplateContext} context - decade template context. * @group Templates */ decadeTemplate = contentChild('decade', { ...(ngDevMode ? { debugName: "decadeTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for previous month icon. * @group Templates */ previousIconTemplate = contentChild('previousicon', { ...(ngDevMode ? { debugName: "previousIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for next month icon. * @group Templates */ nextIconTemplate = contentChild('nexticon', { ...(ngDevMode ? { debugName: "nextIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for trigger icon. * @group Templates */ triggerIconTemplate = contentChild('triggericon', { ...(ngDevMode ? { debugName: "triggerIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for clear icon. * @group Templates */ clearIconTemplate = contentChild('clearicon', { ...(ngDevMode ? { debugName: "clearIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for decrement icon. * @group Templates */ decrementIconTemplate = contentChild('decrementicon', { ...(ngDevMode ? { debugName: "decrementIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for increment icon. * @group Templates */ incrementIconTemplate = contentChild('incrementicon', { ...(ngDevMode ? { debugName: "incrementIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for input icon. * @param {DatePickerInputIconTemplateContext} context - input icon template context. * @group Templates */ inputIconTemplate = contentChild('inputicon', { ...(ngDevMode ? { debugName: "inputIconTemplate" } : /* istanbul ignore next */ {}), descendants: false }); /** * Custom template for button bar. * @param {DatePickerButtonBarTemplateContext} context - button bar template context. * @group Templates */ buttonBarTemplate = contentChild('buttonbar', { ...(ngDevMode ? { debugName: "buttonBarTemplate" } : /* istanbul ignore next */ {}), descendants: false }); selectElement; todayElement; focusElement; scrollHandler; documentResizeListener; navigationState = null; isMonthNavigate; initialized; translationSubscription; _locale; currentView = signal(null, /* @ts-ignore */ ...(ngDevMode ? [{ debugName: "currentView" }] : /* istanbul ignore next */ [])); attributeSelector; panelId; preventFocus; _focusKey = null; window; get locale() { return this._locale; } get iconButtonAriaLabel() { return this.iconAriaLabel() ? this.iconAriaLabel() : this.translate('chooseDate'); } get prevIconAriaLabel() { return this.currentView() === 'year' ? this.translate('prevDecade') : this.currentView() === 'month' ? this.translate('prevYear') : this.translate('prevMonth'); } get nextIconAriaLabel() { return this.currentView() === 'year' ? this.translate('nextDecade') : this.currentView() === 'month' ? this.translate('nextYear') : this.translate('nextMonth'); } overlayService = inject(OverlayService); constructor() { super(); this.window = this.document.defaultView; // Effect for dateFormat changes effect(() => { this.dateFormat(); if (this.initialized) { this.updateInputfield(); } }); // Effect for hourFormat changes effect(() => { this.hourFormat(); if (this.initialized) { this.updateInputfield(); } }); // Effect for minDate/maxDate/disabledDates/disabledDays changes effect(() => { this.minDate(); this.maxDate(); this.disabledDates(); this.disabledDays(); if (this.currentMonth != undefined && this.currentMonth != null && this.currentYear) { this.createMonths(this.currentMonth, this.currentYear); } }); // Effect for showTime changes effect(() => { const showTime = this.showTime(); if (showTime) { if (untracked(() => this.currentHour()) === null) { this.initTime(this.value || new Date()); } this.updateInputfield(); } }); // Effect for responsiveOptions/numberOfMonths changes effect(() => { this.responsiveOptions(); this.numberOfMonths(); this.destroyResponsiveStyleElement(); this.createResponsiveStyle(); }); // Effect for firstDayOfWeek changes effect(() => { this.firstDayOfWeek(); if (this.initialized) { this.createWeekDays(); } }); // Effect for view changes effect(() => { const view = this.view(); this.currentView.set(view); }); // Effect for defaultDate changes effect(() => { const defaultDate = this.defaultDate(); if (this.initialized && defaultDate !== undefined) { const date = defaultDate || new Date(); this.currentMonth = date.getMonth(); this.currentYear = date.getFullYear(); this.initTime(date); this.createMonths(this.currentMonth, this.currentYear); } }); // Effect for contentViewChild changes effect(() => { const content = this.contentWrapperViewChild(); if (content && this.overlay) { if (this.isMonthNavigate) { Promise.resolve(null).then(() => this.updateFocus()); this.isMonthNavigate = false; } else { if (!untracked(() => this.focus()) && !untracked(() => this.inline())) { this.initFocusableCell(); } } } }); } onInit() { this.attributeSelector = uuid('pn_id_'); this.panelId = this.attributeSelector + '_panel'; const date = this.defaultDate() || new Date(); this.createResponsiveStyle(); this.currentMonth = date.getMonth(); this.currentYear = date.getFullYear(); this.yearOptions = []; this.currentView.set(this.view()); if (this.view() === 'date') { this.createWeekDays(); this.initTime(date); this.createMonths(this.currentMonth, this.currentYear); this.ticksTo1970 = ((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000; } this.translationSubscription = this.config.translationObserver.subscribe(() => { this.createWeekDays(); }); this.initialized = true; } onAfterViewInit() { if (this.inline()) { this.contentViewChild() && this.contentViewChild().nativeElement.setAttribute(this.attributeSelector, ''); } else { if (!this.$disabled() && this.overlay) { this.initFocusableCell(); if (this.numberOfMonths() === 1) { if (this.contentViewChild() && this.contentViewChild().nativeElement) { this.contentViewChild().nativeElement.style.width = getOuterWidth(this.el?.nativeElement) + 'px'; } } } } } onAfterViewChecked() { this.bindDirectiveInstance.setAttrs(this.ptms(['host', 'root'])); } populateYearOptions(start, end) { this.yearOptions = []; for (let i = start; i <= end; i++) { this.yearOptions.push(i); } } createWeekDays() { const days = []; let dayIndex = this.getFirstDateOfWeek(); let dayLabels = this.translate(TranslationKeys.DAY_NAMES_MIN); for (let i = 0; i < 7; i++) { days.push(dayLabels[dayIndex]); dayIndex = dayIndex == 6 ? 0 : ++dayIndex; } this.weekDays.set(days); } monthPickerValues() { let monthPickerValues = []; for (let i = 0; i <= 11; i++) { monthPickerValues.push(this.translate('monthNamesShort')[i]); } return monthPickerValues; } yearPickerValues() { let yearPickerValues = []; let base = this.currentYear - (this.currentYear % 10); for (let i = 0; i < 10; i++) { yearPickerValues.push(base + i); } return yearPickerValues; } createMonths(month, year) { const newMonths = []; for (let i = 0; i < this.numberOfMonths(); i++) { let m = month + i; let y = year; if (m > 11) { m = m % 12; y = year + Math.floor((month + i) / 12); } newMonths.push(this.createMonth(m, y)); } this.months.set(newMonths); } getWeekNumber(date) { let checkDate = new Date(date.getTime()); if (this.startWeekFromFirstDayOfYear()) { let firstDayOfWeek = +this.getFirstDateOfWeek(); checkDate.setDate(checkDate.getDate() + 6 + firstDayOfWeek - checkDate.getDay()); } else { checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); } let time = checkDate.getTime(); checkDate.setMonth(0); checkDate.setDate(1); return Math.floor(Math.round((time - checkDate.getTime()) / 86400000) / 7) + 1; } createMonth(month, year) { let dates = []; let firstDay = this.getFirstDayOfMonthIndex(month, year); let daysLength = this.getDaysCountInMonth(month, year); let prevMonthDaysLength = this.getDaysCountInPrevMonth(month, year); let dayNo = 1; let today = new Date(); let weekNumbers = []; let monthRows = Math.ceil((daysLength + firstDay) / 7); for (let i = 0; i < monthRows; i++) { let week = []; if (i == 0) { for (let j = prevMonthDaysLength - firstDay + 1; j <= prevMonthDaysLength; j++) { let prev = this.getPreviousMonthAndYear(month, year); week.push({ day: j, month: prev.month, year: prev.year, otherMonth: true, today: this.isToday(today, j, prev.month, prev.year), selectable: this.isSelectable(j, prev.month, prev.year, true) }); } let remainingDaysLength = 7 - week.length; for (let j = 0; j < remainingDaysLength; j++) { week.push({ day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), selectable: this.isSelectable(dayNo, month, year, false) }); dayNo++; } } else { for (let j = 0; j < 7; j++) { if (dayNo > daysLength) { let next = this.getNextMonthAndYear(month, year); week.push({ day: dayNo - daysLength, month: next.month, year: next.year, otherMonth: true, today: this.isToday(today, dayNo - daysLength, next.month, next.year), selectable: this.isSelectable(dayNo - daysLength, next.month, next.year, true) }); } else { week.push({ day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), selectable: this.isSelectable(dayNo, month, year, false) }); } dayNo++; } } // Always compute week numbers so toggling `showWeek` after init works without rebuilding // months — the template gates their display with `@if (showWeek())`. weekNumbers.push(this.getWeekNumber(new Date(week[0].year, week[0].month, week[0].day))); dates.push(week); } return { month: month, year: year, dates: dates, weekNumbers: weekNumbers }; }