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
JavaScript
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
};
}