primeng-buddhist-year-datepicker
Version:
A PrimeNG v21 compatible Angular datepicker with Buddhist year (BE) calendar support for Thai localization and Buddhist users.
4,537 lines • 210 kB
JavaScript
import * as i3 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, forwardRef, InjectionToken, inject, input, computed, EventEmitter, booleanAttribute, numberAttribute, ContentChildren, ContentChild, ViewChild, Output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { uuid, getOuterWidth, isDate, findSingle, getFocusableElements, hasClass, getIndex, find, isNotEmpty, addStyle, appendChild, absolutePosition, relativePosition, addClass, setAttribute, isTouchDevice } from '@primeuix/utils';
import * as i1 from 'primeng/api';
import { TranslationKeys, SharedModule, PrimeTemplate } from 'primeng/api';
import { AutoFocus } from 'primeng/autofocus';
import { PARENT_INSTANCE } from 'primeng/basecomponent';
import { BaseInput } from 'primeng/baseinput';
import * as i2 from 'primeng/bind';
import { Bind, BindModule } from 'primeng/bind';
import { Button } from 'primeng/button';
import { blockBodyScroll, unblockBodyScroll, ConnectedOverlayScrollHandler } from 'primeng/dom';
import { ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronDownIcon, TimesIcon, CalendarIcon } from 'primeng/icons';
import { InputText } from 'primeng/inputtext';
import * as i4 from 'primeng/motion';
import { MotionModule } from 'primeng/motion';
import { Ripple } from 'primeng/ripple';
import { ZIndexUtils } from 'primeng/utils';
import { style as style$1 } from '@primeuix/styles/datepicker';
import { BaseStyle } from 'primeng/base';
const style = /*css*/ `
${style$1}
/* For PrimeNG */
.p-datepicker.ng-invalid.ng-dirty .p-inputtext {
border-color: dt('inputtext.invalid.border.color');
}
`;
const inlineStyles = {
root: () => ({ position: 'relative' })
};
const classes = {
root: ({ instance }) => [
'p-datepicker p-component p-inputwrapper',
{
'p-invalid': instance.invalid(),
'p-datepicker-fluid': instance.hasFluid,
'p-inputwrapper-filled': instance.$filled(),
'p-variant-filled': instance.$variant() === 'filled',
'p-inputwrapper-focus': instance.focus || instance.overlayVisible,
'p-focus': instance.focus || instance.overlayVisible
}
],
pcInputText: 'p-datepicker-input',
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',
clearIcon: 'p-datepicker-clear-icon'
};
class DatePickerStyle extends BaseStyle {
name = 'datepicker';
style = style;
classes = classes;
inlineStyles = inlineStyles;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePickerStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePickerStyle });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.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 {
zone;
overlayService;
bindDirectiveInstance = inject(Bind, { self: true });
$pcDatePicker = inject(DATEPICKER_INSTANCE, { optional: true, skipSelf: true }) ?? undefined;
iconDisplay = 'button';
/**
* Style class of the component.
* @deprecated since v20.0.0, use `class` instead.
* @group Props
*/
styleClass;
/**
* Inline style of the input field.
* @group Props
*/
inputStyle;
/**
* Identifier of the focus input to match a label defined for the component.
* @group Props
*/
inputId;
/**
* Style class of the input field.
* @group Props
*/
inputStyleClass;
/**
* Placeholder text for the input.
* @group Props
*/
placeholder;
/**
* Establishes relationships between the component and label(s) where its value should be one or more element IDs.
* @group Props
*/
ariaLabelledBy;
/**
* Defines a string that labels the input for accessibility.
* @group Props
*/
ariaLabel;
/**
* Defines a string that labels the icon button for accessibility.
* @group Props
*/
iconAriaLabel;
/**
* Format of the date which can also be defined at locale settings.
* @group Props
*/
get dateFormat() {
return this._dateFormat;
}
set dateFormat(value) {
this._dateFormat = value;
if (this.initialized) {
this.updateInputfield();
}
}
/**
* Separator for multiple selection mode.
* @group Props
*/
multipleSeparator = ',';
/**
* Separator for joining start and end dates on range selection mode.
* @group Props
*/
rangeSeparator = '-';
/**
* When enabled, displays the datepicker as inline. Default is false for popup mode.
* @group Props
*/
inline = false;
/**
* 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 = true;
/**
* 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;
/**
* When enabled, displays a button with icon next to input.
* @group Props
*/
showIcon;
/**
* Icon of the datepicker button.
* @group Props
*/
icon;
/**
* When specified, prevents entering the date manually with keyboard.
* @group Props
*/
readonlyInput;
/**
* The cutoff year for determining the century for a date.
* @group Props
*/
shortYearCutoff = '+10';
/**
* Specifies 12 or 24 hour format.
* @group Props
*/
get hourFormat() {
return this._hourFormat;
}
set hourFormat(value) {
this._hourFormat = value;
if (this.initialized) {
this.updateInputfield();
}
}
/**
* Whether to display timepicker only.
* @group Props
*/
timeOnly;
/**
* Hours to change per step.
* @group Props
*/
stepHour = 1;
/**
* Minutes to change per step.
* @group Props
*/
stepMinute = 1;
/**
* Seconds to change per step.
* @group Props
*/
stepSecond = 1;
/**
* Whether to show the seconds in time picker.
* @group Props
*/
showSeconds = false;
/**
* When disabled, datepicker will not be visible with input focus.
* @group Props
*/
showOnFocus = true;
/**
* When enabled, datepicker will show week numbers.
* @group Props
*/
showWeek = false;
/**
* When enabled, datepicker will start week numbers from first day of the year.
* @group Props
*/
startWeekFromFirstDayOfYear = false;
/**
* When enabled, a clear icon is displayed to clear the value.
* @group Props
*/
showClear = false;
/**
* Type of the value to write back to ngModel, default is date and alternative is string.
* @group Props
*/
dataType = 'date';
/**
* Defines the quantity of the selection, valid values are "single", "multiple" and "range".
* @group Props
*/
selectionMode = 'single';
/**
* Maximum number of selectable dates in multiple mode.
* @group Props
*/
maxDateCount;
/**
* Whether to display today and clear buttons at the footer
* @group Props
*/
showButtonBar;
/**
* Style class of the today button.
* @group Props
*/
todayButtonStyleClass;
/**
* Style class of the clear button.
* @group Props
*/
clearButtonStyleClass;
/**
* When present, it specifies that the component should automatically get focus on load.
* @group Props
*/
autofocus;
/**
* Whether to automatically manage layering.
* @group Props
*/
autoZIndex = true;
/**
* Base zIndex value to use in layering.
* @group Props
*/
baseZIndex = 0;
/**
* Style class of the datetimepicker container element.
* @group Props
*/
panelStyleClass;
/**
* Inline style of the datetimepicker container element.
* @group Props
*/
panelStyle;
/**
* Keep invalid value when input blur.
* @group Props
*/
keepInvalid = false;
/**
* Whether to hide the overlay on date selection.
* @group Props
*/
hideOnDateTimeSelect = true;
/**
* When enabled, datepicker overlay is displayed as optimized for touch devices.
* @group Props
*/
touchUI;
/**
* Separator of time selector.
* @group Props
*/
timeSeparator = ':';
/**
* When enabled, can only focus on elements inside the datepicker.
* @group Props
*/
focusTrap = true;
/**
* Transition options of the show animation.
* @group Props
* @deprecated since v21.0.0, use `motionOptions` instead.
*/
showTransitionOptions = '.12s cubic-bezier(0, 0, 0.2, 1)';
/**
* Transition options of the hide animation.
* @group Props
* @deprecated since v21.0.0, use `motionOptions` instead.
*/
hideTransitionOptions = '.1s linear';
/**
* Index of the element in tabbing order.
* @group Props
*/
tabindex;
/**
* The minimum selectable date.
* @group Props
*/
get minDate() {
return this._minDate;
}
set minDate(date) {
this._minDate = date;
if (this.currentMonth != undefined && this.currentMonth != null && this.currentYear) {
this.createMonths(this.currentMonth, this.currentYear);
}
}
/**
* The maximum selectable date.
* @group Props
*/
get maxDate() {
return this._maxDate;
}
set maxDate(date) {
this._maxDate = date;
if (this.currentMonth != undefined && this.currentMonth != null && this.currentYear) {
this.createMonths(this.currentMonth, this.currentYear);
}
}
/**
* Array with dates that should be disabled (not selectable).
* @group Props
*/
get disabledDates() {
return this._disabledDates;
}
set disabledDates(disabledDates) {
this._disabledDates = disabledDates;
if (this.currentMonth != undefined && this.currentMonth != null && this.currentYear) {
this.createMonths(this.currentMonth, this.currentYear);
}
}
/**
* Array with weekday numbers that should be disabled (not selectable).
* @group Props
*/
get disabledDays() {
return this._disabledDays;
}
set disabledDays(disabledDays) {
this._disabledDays = disabledDays;
if (this.currentMonth != undefined && this.currentMonth != null && this.currentYear) {
this.createMonths(this.currentMonth, this.currentYear);
}
}
/**
* Whether to display timepicker.
* @group Props
*/
get showTime() {
return this._showTime;
}
set showTime(showTime) {
this._showTime = showTime;
if (this.currentHour === undefined) {
this.initTime(this.value || new Date());
}
this.updateInputfield();
}
/**
* An array of options for responsive design.
* @group Props
*/
get responsiveOptions() {
return this._responsiveOptions;
}
set responsiveOptions(responsiveOptions) {
this._responsiveOptions = responsiveOptions;
this.destroyResponsiveStyleElement();
this.createResponsiveStyle();
}
/**
* Number of months to display.
* @group Props
*/
get numberOfMonths() {
return this._numberOfMonths;
}
set numberOfMonths(numberOfMonths) {
this._numberOfMonths = numberOfMonths;
this.destroyResponsiveStyleElement();
this.createResponsiveStyle();
}
/**
* Defines the first of the week for various date calculations.
* @group Props
*/
get firstDayOfWeek() {
return this._firstDayOfWeek;
}
set firstDayOfWeek(firstDayOfWeek) {
this._firstDayOfWeek = firstDayOfWeek;
this.createWeekDays();
}
/**
* Type of view to display, valid values are "date" for datepicker and "month" for month picker.
* @group Props
*/
get view() {
return this._view;
}
set view(view) {
this._view = view;
this.currentView = this._view;
}
/**
* Set the date to highlight on first opening if the field is blank.
* @group Props
*/
get defaultDate() {
return this._defaultDate;
}
set defaultDate(defaultDate) {
this._defaultDate = defaultDate;
if (this.initialized) {
const date = defaultDate || new Date();
this.currentMonth = date.getMonth();
this.currentYear = date.getFullYear();
this.initTime(date);
this.createMonths(this.currentMonth, this.currentYear);
}
}
get isBudhistYear() {
return this._buddhist;
}
set isBudhistYear(isBudhistYear) {
this._buddhist = isBudhistYear;
}
get yearBudhist() {
return this.isBudhistYear ? 543 : 0;
}
/**
* When true, assumes input values are in Buddhist Era (พ.ศ.).
* The component will subtract 543 years for internal processing.
* @group Props
*/
inputBudhistYear = false;
/**
* When true, outputs dates in Buddhist Era (พ.ศ.).
* The component will add 543 years to output values.
* @group Props
*/
outputBudhistYear = false;
/**
* 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, ...(ngDevMode ? [{ debugName: "appendTo" }] : []));
/**
* The motion options.
* @group Props
*/
motionOptions = input(undefined, ...(ngDevMode ? [{ debugName: "motionOptions" }] : []));
computedMotionOptions = computed(() => {
return {
...this.ptm('motion'),
...this.motionOptions()
};
}, ...(ngDevMode ? [{ debugName: "computedMotionOptions" }] : []));
/**
* Callback to invoke on focus of input field.
* @param {Event} event - browser event.
* @group Emits
*/
onFocus = new EventEmitter();
/**
* Callback to invoke on blur of input field.
* @param {Event} event - browser event.
* @group Emits
*/
onBlur = new EventEmitter();
/**
* Callback to invoke when date panel closed.
* @param {HTMLDivElement} element - The element being transitioned/animated.
* @group Emits
*/
onClose = new EventEmitter();
/**
* Callback to invoke on date select.
* @param {Date} date - date value.
* @group Emits
*/
onSelect = new EventEmitter();
/**
* Callback to invoke when input field cleared.
* @group Emits
*/
onClear = new EventEmitter();
/**
* Callback to invoke when input field is being typed.
* @param {Event} event - browser event
* @group Emits
*/
onInput = new EventEmitter();
/**
* Callback to invoke when today button is clicked.
* @param {Date} date - today as a date instance.
* @group Emits
*/
onTodayClick = new EventEmitter();
/**
* Callback to invoke when clear button is clicked.
* @param {Event} event - browser event.
* @group Emits
*/
onClearClick = new EventEmitter();
/**
* Callback to invoke when a month is changed using the navigators.
* @param {DatePickerMonthChangeEvent} event - custom month change event.
* @group Emits
*/
onMonthChange = new EventEmitter();
/**
* Callback to invoke when a year is changed using the navigators.
* @param {DatePickerYearChangeEvent} event - custom year change event.
* @group Emits
*/
onYearChange = new EventEmitter();
/**
* Callback to invoke when clicked outside of the date panel.
* @group Emits
*/
onClickOutside = new EventEmitter();
/**
* Callback to invoke when datepicker panel is shown.
* @param {HTMLDivElement} element - The element being transitioned/animated.
* @group Emits
*/
onShow = new EventEmitter();
inputfieldViewChild;
set content(content) {
this.contentViewChild = content;
if (this.contentViewChild && this.overlay) {
if (this.isMonthNavigate) {
Promise.resolve(null).then(() => this.updateFocus());
this.isMonthNavigate = false;
}
else {
if (!this.focus && !this.inline) {
this.initFocusableCell();
}
}
}
}
_componentStyle = inject(DatePickerStyle);
contentViewChild;
value;
dates;
months;
weekDays;
currentMonth;
currentYear;
currentHour;
currentMinute;
currentSecond;
p;
pm;
mask;
maskClickListener;
overlay;
responsiveStyleElement;
overlayVisible;
overlayMinWidth;
$appendTo = computed(() => this.appendTo() || this.config.overlayAppendTo(), ...(ngDevMode ? [{ debugName: "$appendTo" }] : []));
calendarElement;
timePickerTimer;
documentClickListener;
animationEndListener;
ticksTo1970;
yearOptions;
focus;
isKeydown;
_minDate;
_maxDate;
_dateFormat;
_hourFormat = '24';
_showTime;
_yearRange;
preventDocumentListener;
_buddhist = false;
dayClass(date) {
return this._componentStyle.classes.day({ instance: this, date: date });
}
/**
* Custom template for date cells.
* @param {DatePickerDateTemplateContext} context - date template context.
* @group Templates
*/
dateTemplate;
/**
* Custom template for header section.
* @group Templates
*/
headerTemplate;
/**
* Custom template for footer section.
* @group Templates
*/
footerTemplate;
/**
* Custom template for disabled date cells.
* @param {DatePickerDisabledDateTemplateContext} context - disabled date template context.
* @group Templates
*/
disabledDateTemplate;
/**
* Custom template for decade view.
* @param {DatePickerDecadeTemplateContext} context - decade template context.
* @group Templates
*/
decadeTemplate;
/**
* Custom template for previous month icon.
* @group Templates
*/
previousIconTemplate;
/**
* Custom template for next month icon.
* @group Templates
*/
nextIconTemplate;
/**
* Custom template for trigger icon.
* @group Templates
*/
triggerIconTemplate;
/**
* Custom template for clear icon.
* @group Templates
*/
clearIconTemplate;
/**
* Custom template for decrement icon.
* @group Templates
*/
decrementIconTemplate;
/**
* Custom template for increment icon.
* @group Templates
*/
incrementIconTemplate;
/**
* Custom template for input icon.
* @param {DatePickerInputIconTemplateContext} context - input icon template context.
* @group Templates
*/
inputIconTemplate;
/**
* Custom template for button bar.
* @param {DatePickerButtonBarTemplateContext} context - button bar template context.
* @group Templates
*/
buttonBarTemplate;
_dateTemplate;
_headerTemplate;
_footerTemplate;
_disabledDateTemplate;
_decadeTemplate;
_previousIconTemplate;
_nextIconTemplate;
_triggerIconTemplate;
_clearIconTemplate;
_decrementIconTemplate;
_incrementIconTemplate;
_inputIconTemplate;
_buttonBarTemplate;
_disabledDates;
_disabledDays;
selectElement;
todayElement;
focusElement;
scrollHandler;
documentResizeListener;
navigationState = null;
isMonthNavigate;
initialized;
translationSubscription;
_locale;
_responsiveOptions;
currentView;
attributeSelector;
panelId;
_numberOfMonths = 1;
_firstDayOfWeek;
_view = 'date';
preventFocus;
_defaultDate;
_focusKey = null;
window;
get locale() {
return this._locale;
}
get iconButtonAriaLabel() {
return this.iconAriaLabel ? this.iconAriaLabel : this.getTranslation('chooseDate');
}
get prevIconAriaLabel() {
return this.currentView === 'year' ? this.getTranslation('prevDecade') : this.currentView === 'month' ? this.getTranslation('prevYear') : this.getTranslation('prevMonth');
}
get nextIconAriaLabel() {
return this.currentView === 'year' ? this.getTranslation('nextDecade') : this.currentView === 'month' ? this.getTranslation('nextYear') : this.getTranslation('nextMonth');
}
constructor(zone, overlayService) {
super();
this.zone = zone;
this.overlayService = overlayService;
this.window = this.document.defaultView;
}
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 = 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.cd.markForCheck();
});
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']));
}
templates;
onAfterContentInit() {
this.templates.forEach((item) => {
switch (item.getType()) {
case 'date':
this._dateTemplate = item.template;
break;
case 'decade':
this._decadeTemplate = item.template;
break;
case 'disabledDate':
this._disabledDateTemplate = item.template;
break;
case 'header':
this._headerTemplate = item.template;
break;
case 'inputicon':
this._inputIconTemplate = item.template;
break;
case 'buttonbar':
this._buttonBarTemplate = item.template;
break;
case 'previousicon':
this._previousIconTemplate = item.template;
break;
case 'nexticon':
this._nextIconTemplate = item.template;
break;
case 'triggericon':
this._triggerIconTemplate = item.template;
break;
case 'clearicon':
this._clearIconTemplate = item.template;
break;
case 'decrementicon':
this._decrementIconTemplate = item.template;
break;
case 'incrementicon':
this._incrementIconTemplate = item.template;
break;
case 'footer':
this._footerTemplate = item.template;
break;
default:
this._dateTemplate = item.template;
break;
}
});
}
getTranslation(option) {
return this.config.getTranslation(option);
}
populateYearOptions(start, end) {
this.yearOptions = [];
for (let i = start; i <= end; i++) {
this.yearOptions.push(i);
}
}
createWeekDays() {
this.weekDays = [];
let dayIndex = this.getFirstDateOfWeek();
let dayLabels = this.getTranslation(TranslationKeys.DAY_NAMES_MIN);
for (let i = 0; i < 7; i++) {
this.weekDays.push(dayLabels[dayIndex]);
dayIndex = dayIndex == 6 ? 0 : ++dayIndex;
}
}
monthPickerValues() {
let monthPickerValues = [];
for (let i = 0; i <= 11; i++) {
monthPickerValues.push(this.config.getTranslation('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 + this.yearBudhist);
}
return yearPickerValues;
}
createMonths(month, year) {
this.months = this.months = [];
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);
}
this.months.push(this.createMonth(m, y));
}
}
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++;
}
}
if (this.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
};
}
initTime(date) {
this.pm = date.getHours() > 11;
if (this.showTime) {
this.currentMinute = date.getMinutes();
this.currentSecond = this.showSeconds ? date.getSeconds() : 0;
this.setCurrentHourPM(date.getHours());
}
else if (this.timeOnly) {
this.currentMinute = 0;
this.currentHour = 0;
this.currentSecond = 0;
}
}
navBackward(event) {
if (this.$disabled()) {
event.preventDefault();
return;
}
this.isMonthNavigate = true;
if (this.currentView === 'month') {
this.decrementYear();
setTimeout(() => {
this.updateFocus();
}, 1);
}
else if (this.currentView === 'year') {
this.decrementDecade();
setTimeout(() => {
this.updateFocus();
}, 1);
}
else {
if (this.currentMonth === 0) {
this.currentMonth = 11;
this.decrementYear();
}
else {
this.currentMonth--;
}
this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
this.createMonths(this.currentMonth, this.currentYear);
}
}
navForward(event) {
if (this.$disabled()) {
event.preventDefault();
return;
}
this.isMonthNavigate = true;
if (this.currentView === 'month') {
this.incrementYear();
setTimeout(() => {
this.updateFocus();
}, 1);
}
else if (this.currentView === 'year') {
this.incrementDecade();
setTimeout(() => {
this.updateFocus();
}, 1);
}
else {
if (this.currentMonth === 11) {
this.currentMonth = 0;
this.incrementYear();
}
else {
this.currentMonth++;
}
this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
this.createMonths(this.currentMonth, this.currentYear);
}
}
decrementYear() {
this.currentYear--;
let _yearOptions = this.yearOptions;
if (this.currentYear < _yearOptions[0]) {
let difference = _yearOptions[_yearOptions.length - 1] - _yearOptions[0];
this.populateYearOptions(_yearOptions[0] - difference, _yearOptions[_yearOptions.length - 1] - difference);
}
}
decrementDecade() {
this.currentYear = this.currentYear - 10;
}
incrementDecade() {
this.currentYear = this.currentYear + 10;
}
incrementYear() {
this.currentYear++;
let _yearOptions = this.yearOptions;
if (this.currentYear > _yearOptions[_yearOptions.length - 1]) {
let difference = _yearOptions[_yearOptions.length - 1] - _yearOptions[0];
this.populateYearOptions(_yearOptions[0] + difference, _yearOptions[_yearOptions.length - 1] + difference);
}
}
switchToMonthView(event) {
this.setCurrentView('month');
event.preventDefault();
}
switchToYearView(event) {
this.setCurrentView('year');
event.preventDefault();
}
onDateSelect(event, dateMeta) {
if (this.$disabled() || !dateMeta.selectable) {
event.preventDefault();
return;
}
if (this.isMultipleSelection() && this.isSelected(dateMeta)) {
this.value = this.value.filter((date, i) => {
return !this.isDateEquals(date, dateMeta);
});
if (this.value.length === 0) {
this.value = null;
}
this.updateModel(this.value);
}
else {
if (this.shouldSelectDate(dateMeta)) {
this.selectDate(dateMeta);
}
}
if (this.hideOnDateTimeSelect && (this.isSingleSelection() || (this.isRangeSelection() && this.value[1]))) {
setTimeout(() => {
event.preventDefault();
this.hideOverlay();
if (this.mask) {
this.disableModality();
}
this.cd.markForCheck();
}, 150);
}
this.updateInputfield();
event.preventDefault();
}
shouldSelectDate(dateMeta) {
if (this.isMultipleSelection())
return this.maxDateCount != null ? this.maxDateCount > (this.value ? this.value.length : 0) : true;
else
return true;
}
onMonthSelect(event, index) {
if (this.view === 'month') {
this.onDateSelect(event, { year: this.currentYear, month: index, day: 1, selectable: true });
}
else {
this.currentMonth = index;
this.createMonths(this.currentMonth, this.currentYear);
this.setCurrentView('date');
this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
}
}
onYearSelect(event, year) {
// Subtract yearBudhist offset because yearPickerValues displays Buddhist year
const gregorianYear = year - this.yearBudhist;
if (this.view === 'year') {
this.onDateSelect(event, { year: gregorianYear, month: 0, day: 1, selectable: true });
}
else {
this.currentYear = gregorianYear;
this.setCurrentView('month');
this.onYearChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
}
}
updateInputfield() {
let formattedValue = '';
if (this.value) {
if (this.isSingleSelection()) {
formattedValue = this.formatDateTime(this.value);
}
else if (this.isMultipleSelection()) {
for (let i = 0; i < this.value.length; i++) {
let dateAsString = this.formatDateTime(this.value[i]);
formattedValue += dateAsString;
if (i !== this.value.length - 1) {
formattedValue += this.multipleSeparator + ' ';
}
}
}
else if (this.isRangeSelection()) {
if (this.value && this.value.length) {
let startDate = this.value[0];
let endDate = this.value[1];
formattedValue = this.formatDateTime(startDate);
if (endDate) {
formattedValue += ' ' + this.rangeSeparator + ' ' + this.formatDateTime(endDate);
}
}
}
}
this.writeModelValue(formattedValue);
this.inputFieldValue = formattedValue;
if (this.inputfieldViewChild && this.inputfieldViewChild.nativeElement) {
this.inputfieldViewChild.nativeElement.value = this.inputFieldValue;
}
}
inputFieldValue = null;
formatDateTime(date) {
let formattedValue = this.keepInvalid ? date : null;
const isDateValid = this.isValidDateForTimeConstraints(date);
if (this.isValidDate(date)) {
if (this.timeOnly) {
formattedValue = this.formatTime(date);
}
else {
formattedValue = this.formatDate(date, this.getDateFormat());
if (this.showTime) {
formattedValue += ' ' + this.formatTime(date);
}
}
}
else if (this.dataType === 'string') {
formattedValue = date;
}
formattedValue = isDateValid ? formattedValue : '';
return formattedValue;
}
formatDateMetaToDate(dateMeta) {
return new Date(dateMeta.year, dateMeta.month, dateMeta.day);
}
formatDateKey(date) {
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
}
setCurrentHourPM(hours) {
if (this.hourFormat == '12') {
this.pm = hours > 11;
if (hours >= 12) {
this.currentHour = hours == 12 ? 12 : hours - 12;
}
else {
this.currentHour = hours == 0 ? 12 : hours;
}
}
else {
this.currentHour = hours;
}
}
setCurrentView(currentView) {
this.currentView = currentView;
this.cd.detectChanges();
this.alignOverlay();
}
selectDate(dateMeta) {
let date = this.formatDateMetaToDate(dateMeta);
if (this.showTime) {
if (this.hourFormat == '12') {
if (this.currentHour === 12)
date.setHours(this.pm ? 12 : 0);
else
date.setHours(this.pm ? this.currentHour + 12 : this.currentHour);
}
else {
date.setHours(this.currentHour);
}
date.setMinutes(this.currentMinute);
date.setSeconds(this.currentSecond);
}
if (this.minDate && this.minDate > date) {
date = this.minDate;
this.setCurrentHourPM(date.getHours());
this.currentMinute = date.getMinutes();
this.currentSecond = date.getSeconds();
}
if (this.maxDate && this.maxDate < date) {
date = this.maxDate;
this.setCurrentHourPM(date.getHours());
this.currentMinute = date.getMinutes();
this.currentSecond = date.getSeconds();
}
// When inputBudhistYear is true, convert the selected date to Buddhist year format
// because the stored value should match the input format (Buddhist year)
if (this.inputBudhistYear) {
date = new Date(date.getFullYear() + 543, date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());
}
if (this.isSingleSelection()) {
this.updateModel(date);
}
else if (this.isMultipleSelection()) {
this.updateModel(this.value ? [...this.value, date] : [date]);
}
else if (this.isRangeSelection()) {
if (this.value && this.value.length) {
let startDate = this.value[0];
let endDate = this.value[1];
if (!endDate && date.getTime() >= startDate.getTime()) {
endDate = date;
}
else {
startDate = date;
endDate = null;
}
this.updateModel([startDate, endDate]);
}
else {
this.updateModel([date, null]);
}
}
this.onSelect.emit(date);
}
updateModel(value) {
this.value = value;
// Convert output based on outputBudhistYear setting
const outputValue = this.convertOutputValue(value);
if (this.dataType == 'date') {
this.writeModelValue(outputValue);
this.onModelChange(outputValue);
}
else if (this.dataType == 'string') {
if (this.isSingleSelection()) {
this.onModelChange(this.formatDateTime(this.value));
}
else {
let stringArrValue = null;
if (Array.isArray(this.value)) {
stringArrValue = this.value.map((date) => this.formatDateTime(date));
}
this.writeModelValue(stringArrValue);
this.onModelChange(stringArrValue);
}
}
}
/**
* Convert date from Buddhist Era to Gregorian Era (subtract 543 years)
*/
convertFromBuddhist(date) {
if (!date || !isDate(date))
return date;
const converted = new Date(date.getTime());
converted.setFullYear(date.getFullYear() - 543);
return converted;
}
/**
* Convert date from Gregorian Era to Buddhist Era (add 543 years)
*/
convertToBuddhist(date) {
if (!date || !isDate(date))
return date;
const converted = new Date(date.getTime());
converted.setFullYear(date.getFullYear() + 543);
return converted;
}
/**
* Convert input value from Buddhist Era if inputBudhistYear is true
*/
convertInputValue(value) {
if (!this.inputBudhistYear || !value)
return value;
if (Array.isArray(value)) {
return value.map(d => this.convertFromBuddhist(d));
}
return this.convertFromBuddhist(value);
}
/**
* Convert output value to Buddhist Era if outputBudhistYear is true
* Skip conversion if inputBudhistYear is true since value is already in Buddhist format
*/
convertOutputValue(value) {
// If inputBudhistYear is true, value is already Buddhist, no need to convert again
if (!this.outputBudhistYear || !value || this.inputBudhistYear)
return value;
if (Array.isArray(value)) {
return value.map(d => this.convertToBuddhist(d));
}
return this.convertToBuddhist(value);
}
getFirstDayOfMonthIndex(month, year) {
let day = new Date();
day.setDate(1);
day.setMonth(month);
day.setFullYear(year);
let dayIndex = day.getDay() + this.getSundayIndex();
return dayIndex >= 7 ? dayIndex - 7 : dayIndex;
}
getDaysCountInMonth(month, year) {
return 32 - this.daylightSavingAdjust(new Date(year, month, 32)).getDate();
}
getDaysCountInPrevMonth(month, year) {
let prev = this.getPreviousMonthAndYear(month, year);
return this.getDaysCountInMonth(prev.month, prev.year);
}
getPreviousMonthAndYear(month, year) {
let m, y;
if (month === 0) {
m = 11;
y = year - 1;
}
else {
m = month - 1;
y = year;
}
return { month: m, year: y };
}
getNextMonthAndYear(month, year) {
let m, y;
if (month === 11) {
m = 0;
y = year + 1;
}
else {
m = month + 1;
y = year;
}
return { month: m, year: y };
}
getSundayIndex() {
let firstDayOfWeek = this.getFirstDateOfWeek();
return firstDayOfWeek > 0 ? 7 - firstDayOfWeek : 0;
}
isSelected(dateMeta) {
if (this.value) {
if (this.isSingleSelection()) {
return this.isDateEquals(this.value, dateMeta);
}
else if (this.isMultipleSelection()) {
let selected = false;
for (let date of this.value) {
selected = this.isDateEquals(date, dateMeta);
if (selected) {
break;
}
}
return selected;
}
else if (this.isRangeSelection()) {
if (this.value[1])
return this.isDateEquals(this.value[0], dateMeta) || this.isDateEquals(this.value[1], dateMeta) || this.isDateBetween(this.value[0], this.value[1], dateMeta);
else
return this.isDateEquals(this.value[0], dateMeta);
}
}
else {
return false;
}
}
isComparable() {
return this.value != null && typeof this.value !== 'string';
}
isMonthSelected(month) {
if (!this.isComparable())
return false;
if (this.isMultipleSelection()) {
return this.value.some((currentValue) => currentValue.getMonth() === month && currentValue.getFullYear() === this.currentYear);
}
else if (this.isRangeSelection()) {
if (!this.value[1]) {
return this.value[0]?.getFullYear() === this.currentYear && this.value[0]?.getMonth() === month;
}
else {
const currentDate = new Date(this.currentYear, month, 1);
const startDate = new Date(this.value[0].getFullYear(), this.value[0].getMonth(), 1);
const endDate = new Date(this.value[1].getFullYear(), this.value[1].getMonth(), 1);
return currentDate >= startDate && currentDate <= endDate;
}
}
else {
return this.value.getMonth() === month && this.value.getFullYear() === this.currentYear;
}
}
isMonthDisabled(month, year) {
const yearToCheck = year ?? this.currentYear;
for (let day = 1; day < this.getDaysCountInMonth(month, yearToCheck) + 1; day++) {
if (this.isSelectable(day, month, yearToCheck, false)) {
return false;
}
}
return true;
}
isYearDisabled(year) {
return Array(12)
.fill(0)
.every((v, month) => this.isMonthDisabled(month, year));
}
isYearSelected(year) {
if (this.isComparable()) {
let value = this.isRangeSelection() ? this.value[0] : this.value;
return !this.isMultipleSelection() ? (value.getFullYear() + this.yearBudhist) === year : false;
}
return false;
}
isDateEquals(value, dateMeta) {
if (value && isDate(value))
return value.getDate() === dateMeta.day && value.getMonth() === dateMeta.month && value.getFullYear() === dateMeta.year;
else
return false;
}
isDateBetween(start, end, dateMeta) {
let between = false;
if (isDate(start) && isDate(end)) {
let date = this.formatDateMetaToDate(dateMeta);
return start.getTime() <= date.getTime() && end.getTime() >= date.getTime();
}
return between;
}
isSingleSelection() {
return this.selectionMode === 'single';
}
isRangeSelection() {
return this.selectionMode === 'range';
}
isMultipleSelection() {
return this.selectionMode === 'multiple';
}
isToday(today, day, month, year) {
return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year;
}
isSelectable(day, month, year, otherMonth) {
let validMin = true;
let validMax = true;
let validDate = true;
let validDay = true;
if (otherMonth && !this.selectOtherMonths) {
return false;
}
if (this.minDate) {
if (this.minDate.getFullYear() > year) {
validMin = false;
}
else if (this.minDate.getFullYear() === year && this.currentView != 'year') {
if (this.minDate.getMonth() > month) {
validMin = false;
}
else if (this.minDate.getMonth() === month) {
if (this.minDate.getDate() > day) {
validMin = false;
}
}
}
}
if (this.maxDate) {
if (this.maxDate.getFullYear() < year) {
validMax = false;
}
else if (this.maxDate.getFullYear() === year) {
if (this.maxDate.getMonth() < month) {
validMax = false;
}
else if (this.maxDate.getMonth() === month) {
if (this.maxDate.getDate() < day) {
validMax = false;
}
}
}
}
if (this.disabledDates) {
validDate = !this.isDateDisabled(day, month, year);
}
if (this.disabledDays) {
validDay = !this.isDayDisabled(day, month, year);
}
return validMin && validMax && validDate && validDay;
}
isDateDisabled(day, month, year) {
if (this.disabledDates) {
for (let disabledDate of this.disabledDates) {
if (disabledDate.getFullYear() === year && disabledDate.getMonth() === month && disabledDate.getDate() === day) {
return true;
}
}
}
return false;
}
isDayDisabled(day, month, year) {
if (this.disabledDays) {
let weekday = new Date(year, month, day);
let weekdayNumber = weekday.getDay();
return this.disabledDays.indexOf(weekdayNumber) !== -1;
}
return false;
}
onInputFocus(event) {
this.focus = true;
if (this.showOnFocus) {
this.showOverlay();
}
this.onFocus.emit(event);
}
onInputClick() {
if (this.showOnFocus && !this.overlayVisible) {
this.showOverlay();
}
}
onInputBlur(event) {
this.focus = false;
this.onBlur.emit(event);
if (!this.keepInvalid) {
this.updateInputfield();
}
this.onModelTouched();
}
onButtonClick(event, inputfield = this.inputfieldViewChild?.nativeElement) {
if (this.$disabled()) {
return;
}
if (!this.overlayVisible) {
inputfield.focus();
this.showOverlay();
}
else {
this.hideOverlay();
}
}
clear() {
this.value = null;
this.inputFieldValue = null;
this.writeModelValue(this.value);
this.onModelChange(this.value);
this.updateInputfield();
this.onClear.emit();
}
onOverlayClick(event) {
this.overlayService.add({
originalEvent: event,
target: this.el.nativeElement
});
}
getMonthName(index) {
return this.config.getTranslation('monthNames')[index];
}
getYear(month) {
const year = this.currentView === 'month' ? this.currentYear : month.year;
return year + this.yearBudhist;
}
switchViewButtonDisabled() {
return this.numberOfMonths > 1 || this.$disabled();
}
onPrevButtonClick(event) {
this.navigationState = { backward: true, button: true };
this.navBackward(event);
}
onNextButtonClick(event) {
this.navigationState = { backward: false, button: true };
this.navForward(event);
}
onContainerButtonKeydown(event) {
switch (event.which) {
//tab
case 9:
if (!this.inline) {
this.trapFocus(event);
}
if (this.inline) {
const headerElements = findSingle(this.el?.nativeElement, '.p-datepicker-header');
const element = event.target;
if (this.timeOnly) {
return;
}
else {
if (element == headerElements?.children[headerElements?.children?.length - 1]) {
this.initFocusableCell();
}
}
}
break;
//escape
case 27:
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
event.preventDefault();
break;
default:
//Noop
break;
}
}
onInputKeydown(event) {
this.isKeydown = true;
if (event.keyCode === 40 && this.contentViewChild) {
this.trapFocus(event);
}
else if (event.keyCode === 27) {
if (this.overlayVisible) {
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
event.preventDefault();
}
}
else if (event.keyCode === 13) {
if (this.overlayVisible) {
this.overlayVisible = false;
event.preventDefault();
}
}
else if (event.keyCode === 9 && this.contentViewChild) {
getFocusableElements(this.contentViewChild.nativeElement).forEach((el) => (el.tabIndex = '-1'));
if (this.overlayVisible) {
this.overlayVisible = false;
}
}
}
onDateCellKeydown(event, dateMeta, groupIndex) {
const cellContent = event.currentTarget;
const cell = cellContent.parentElement;
const currentDate = this.formatDateMetaToDate(dateMeta);
switch (event.which) {
//down arrow
case 40: {
cellContent.tabIndex = '-1';
let cellIndex = getIndex(cell);
let nextRow = cell.parentElement.nextElementSibling;
if (nextRow) {
let focusCell = nextRow.children[cellIndex].children[0];
if (hasClass(focusCell, 'p-disabled')) {
this.navigationState = { backward: false };
this.navForward(event);
}
else {
nextRow.children[cellIndex].children[0].tabIndex = '0';
nextRow.children[cellIndex].children[0].focus();
}
}
else {
this.navigationState = { backward: false };
this.navForward(event);
}
event.preventDefault();
break;
}
//up arrow
case 38: {
cellContent.tabIndex = '-1';
let cellIndex = getIndex(cell);
let prevRow = cell.parentElement.previousElementSibling;
if (prevRow) {
let focusCell = prevRow.children[cellIndex].children[0];
if (hasClass(focusCell, 'p-disabled')) {
this.navigationState = { backward: true };
this.navBackward(event);
}
else {
focusCell.tabIndex = '0';
focusCell.focus();
}
}
else {
this.navigationState = { backward: true };
this.navBackward(event);
}
event.preventDefault();
break;
}
//left arrow
case 37: {
cellContent.tabIndex = '-1';
let prevCell = cell.previousElementSibling;
if (prevCell) {
let focusCell = prevCell.children[0];
if (hasClass(focusCell, 'p-disabled') || hasClass(focusCell.parentElement, 'p-datepicker-weeknumber')) {
this.navigateToMonth(true, groupIndex);
}
else {
focusCell.tabIndex = '0';
focusCell.focus();
}
}
else {
this.navigateToMonth(true, groupIndex);
}
event.preventDefault();
break;
}
//right arrow
case 39: {
cellContent.tabIndex = '-1';
let nextCell = cell.nextElementSibling;
if (nextCell) {
let focusCell = nextCell.children[0];
if (hasClass(focusCell, 'p-disabled')) {
this.navigateToMonth(false, groupIndex);
}
else {
focusCell.tabIndex = '0';
focusCell.focus();
}
}
else {
this.navigateToMonth(false, groupIndex);
}
event.preventDefault();
break;
}
//enter
//space
case 13:
case 32: {
this.onDateSelect(event, dateMeta);
event.preventDefault();
break;
}
//escape
case 27: {
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
event.preventDefault();
break;
}
//tab
case 9: {
if (!this.inline) {
this.trapFocus(event);
}
break;
}
// page up
case 33: {
cellContent.tabIndex = '-1';
const dateToFocus = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
const focusKey = this.formatDateKey(dateToFocus);
this.navigateToMonth(true, groupIndex, `span[data-date='${focusKey}']:not(.p-disabled):not(.p-ink)`);
event.preventDefault();
break;
}
// page down
case 34: {
cellContent.tabIndex = '-1';
const dateToFocus = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
const focusKey = this.formatDateKey(dateToFocus);
this.navigateToMonth(false, groupIndex, `span[data-date='${focusKey}']:not(.p-disabled):not(.p-ink)`);
event.preventDefault();
break;
}
//home
case 36:
cellContent.tabIndex = '-1';
const firstDayDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
const firstDayDateKey = this.formatDateKey(firstDayDate);
const firstDayCell = findSingle(cellContent.offsetParent, `span[data-date='${firstDayDateKey}']:not(.p-disabled):not(.p-ink)`);
if (firstDayCell) {
firstDayCell.tabIndex = '0';
firstDayCell.focus();
}
event.preventDefault();
break;
//end
case 35:
cellContent.tabIndex = '-1';
const lastDayDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
const lastDayDateKey = this.formatDateKey(lastDayDate);
const lastDayCell = findSingle(cellContent.offsetParent, `span[data-date='${lastDayDateKey}']:not(.p-disabled):not(.p-ink)`);
if (lastDayDate) {
lastDayCell.tabIndex = '0';
lastDayCell.focus();
}
event.preventDefault();
break;
default:
//no op
break;
}
}
onMonthCellKeydown(event, index) {
const cell = event.currentTarget;
switch (event.which) {
//arrows
case 38:
case 40: {
cell.tabIndex = '-1';
var cells = cell.parentElement.children;
var cellIndex = getIndex(cell);
let nextCell = cells[event.which === 40 ? cellIndex + 3 : cellIndex - 3];
if (nextCell) {
nextCell.tabIndex = '0';
nextCell.focus();
}
event.preventDefault();
break;
}
//left arrow
case 37: {
cell.tabIndex = '-1';
let prevCell = cell.previousElementSibling;
if (prevCell) {
prevCell.tabIndex = '0';
prevCell.focus();
}
else {
this.navigationState = { backward: true };
this.navBackward(event);
}
event.preventDefault();
break;
}
//right arrow
case 39: {
cell.tabIndex = '-1';
let nextCell = cell.nextElementSibling;
if (nextCell) {
nextCell.tabIndex = '0';
nextCell.focus();
}
else {
this.navigationState = { backward: false };
this.navForward(event);
}
event.preventDefault();
break;
}
//enter
//space
case 13:
case 32: {
this.onMonthSelect(event, index);
event.preventDefault();
break;
}
//escape
case 27: {
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
event.preventDefault();
break;
}
//tab
case 9: {
if (!this.inline) {
this.trapFocus(event);
}
break;
}
default:
//no op
break;
}
}
onYearCellKeydown(event, index) {
const cell = event.currentTarget;
switch (event.which) {
//arrows
case 38:
case 40: {
cell.tabIndex = '-1';
var cells = cell.parentElement.children;
var cellIndex = getIndex(cell);
let nextCell = cells[event.which === 40 ? cellIndex + 2 : cellIndex - 2];
if (nextCell) {
nextCell.tabIndex = '0';
nextCell.focus();
}
event.preventDefault();
break;
}
//left arrow
case 37: {
cell.tabIndex = '-1';
let prevCell = cell.previousElementSibling;
if (prevCell) {
prevCell.tabIndex = '0';
prevCell.focus();
}
else {
this.navigationState = { backward: true };
this.navBackward(event);
}
event.preventDefault();
break;
}
//right arrow
case 39: {
cell.tabIndex = '-1';
let nextCell = cell.nextElementSibling;
if (nextCell) {
nextCell.tabIndex = '0';
nextCell.focus();
}
else {
this.navigationState = { backward: false };
this.navForward(event);
}
event.preventDefault();
break;
}
//enter
//space
case 13:
case 32: {
this.onYearSelect(event, index);
event.preventDefault();
break;
}
//escape
case 27: {
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
event.preventDefault();
break;
}
//tab
case 9: {
this.trapFocus(event);
break;
}
default:
//no op
break;
}
}
navigateToMonth(prev, groupIndex, focusKey) {
if (prev) {
if (this.numberOfMonths === 1 || groupIndex === 0) {
this.navigationState = { backward: true };
this._focusKey = focusKey;
this.navBackward(event);
}
else {
let prevMonthContainer = this.contentViewChild.nativeElement.children[groupIndex - 1];
if (focusKey) {
const firstDayCell = findSingle(prevMonthContainer, focusKey);
firstDayCell.tabIndex = '0';
firstDayCell.focus();
}
else {
let cells = find(prevMonthContainer, '.p-datepicker-calendar td span:not(.p-disabled):not(.p-ink)');
let focusCell = cells[cells.length - 1];
focusCell.tabIndex = '0';
focusCell.focus();
}
}
}
else {
if (this.numberOfMonths === 1 || groupIndex === this.numberOfMonths - 1) {
this.navigationState = { backward: false };
this._focusKey = focusKey;
this.navForward(event);
}
else {
let nextMonthContainer = this.contentViewChild.nativeElement.children[groupIndex + 1];
if (focusKey) {
const firstDayCell = findSingle(nextMonthContainer, focusKey);
firstDayCell.tabIndex = '0';
firstDayCell.focus();
}
else {
let focusCell = findSingle(nextMonthContainer, '.p-datepicker-calendar td span:not(.p-disabled):not(.p-ink)');
focusCell.tabIndex = '0';
focusCell.focus();
}
}
}
}
updateFocus() {
let cell;
if (this.navigationState) {
if (this.navigationState.button) {
this.initFocusableCell();
if (this.navigationState.backward)
findSingle(this.contentViewChild.nativeElement, '.p-datepicker-prev-button').focus();
else
findSingle(this.contentViewChild.nativeElement, '.p-datepicker-next-button').focus();
}
else {
if (this.navigationState.backward) {
let cells;
if (this.currentView === 'month') {
cells = find(this.contentViewChild.nativeElement, '.p-datepicker-month-view .p-datepicker-month:not(.p-disabled)');
}
else if (this.currentView === 'year') {
cells = find(this.contentViewChild.nativeElement, '.p-datepicker-year-view .p-datepicker-year:not(.p-disabled)');
}
else {
cells = find(this.contentViewChild.nativeElement, this._focusKey || '.p-datepicker-calendar td span:not(.p-disabled):not(.p-ink)');
}
if (cells && cells.length > 0) {
cell = cells[cells.length - 1];
}
}
else {
if (this.currentView === 'month') {
cell = findSingle(this.contentViewChild.nativeElement, '.p-datepicker-month-view .p-datepicker-month:not(.p-disabled)');
}
else if (this.currentView === 'year') {
cell = findSingle(this.contentViewChild.nativeElement, '.p-datepicker-year-view .p-datepicker-year:not(.p-disabled)');
}
else {
cell = findSingle(this.contentViewChild.nativeElement, this._focusKey || '.p-datepicker-calendar td span:not(.p-disabled):not(.p-ink)');
}
}
if (cell) {
cell.tabIndex = '0';
cell.focus();
}
}
this.navigationState = null;
this._focusKey = null;
}
else {
this.initFocusableCell();
}
}
initFocusableCell() {
const contentEl = this.contentViewChild?.nativeElement;
let cell;
if (this.currentView === 'month') {
let cells = find(contentEl, '.p-datepicker-month-view .p-datepicker-month:not(.p-disabled)');
let selectedCell = findSingle(contentEl, '.p-datepicker-month-view .p-datepicker-month.p-highlight');
cells.forEach((cell) => (cell.tabIndex = -1));
cell = selectedCell || cells[0];
if (cells.length === 0) {
let disabledCells = find(contentEl, '.p-datepicker-month-view .p-datepicker-month.p-disabled[tabindex = "0"]');
disabledCells.forEach((cell) => (cell.tabIndex = -1));
}
}
else if (this.currentView === 'year') {
let cells = find(contentEl, '.p-datepicker-year-view .p-datepicker-year:not(.p-disabled)');
let selectedCell = findSingle(contentEl, '.p-datepicker-year-view .p-datepicker-year.p-highlight');
cells.forEach((cell) => (cell.tabIndex = -1));
cell = selectedCell || cells[0];
if (cells.length === 0) {
let disabledCells = find(contentEl, '.p-datepicker-year-view .p-datepicker-year.p-disabled[tabindex = "0"]');
disabledCells.forEach((cell) => (cell.tabIndex = -1));
}
}
else {
cell = findSingle(contentEl, 'span.p-highlight');
if (!cell) {
let todayCell = findSingle(contentEl, 'td.p-datepicker-today span:not(.p-disabled):not(.p-ink)');
if (todayCell)
cell = todayCell;
else
cell = findSingle(contentEl, '.p-datepicker-calendar td span:not(.p-disabled):not(.p-ink)');
}
}
if (cell) {
cell.tabIndex = '0';
if (!this.preventFocus && (!this.navigationState || !this.navigationState.button)) {
setTimeout(() => {
if (!this.$disabled()) {
cell.focus();
}
}, 1);
}
this.preventFocus = false;
}
}
trapFocus(event) {
let focusableElements = getFocusableElements(this.contentViewChild.nativeElement);
if (focusableElements && focusableElements.length > 0) {
if (!focusableElements[0].ownerDocument.activeElement) {
focusableElements[0].focus();
}
else {
let focusedIndex = focusableElements.indexOf(focusableElements[0].ownerDocument.activeElement);
if (event.shiftKey) {
if (focusedIndex == -1 || focusedIndex === 0) {
if (this.focusTrap) {
focusableElements[focusableElements.length - 1].focus();
}
else {
if (focusedIndex === -1)
return this.hideOverlay();
else if (focusedIndex === 0)
return;
}
}
else {
focusableElements[focusedIndex - 1].focus();
}
}
else {
if (focusedIndex == -1) {
if (this.timeOnly) {
focusableElements[0].focus();
}
else {
let spanIndex = 0;
for (let i = 0; i < focusableElements.length; i++) {
if (focusableElements[i].tagName === 'SPAN')
spanIndex = i;
}
focusableElements[spanIndex].focus();
}
}
else if (focusedIndex === focusableElements.length - 1) {
if (!this.focusTrap && focusedIndex != -1)
return this.hideOverlay();
focusableElements[0].focus();
}
else {
focusableElements[focusedIndex + 1].focus();
}
}
}
}
event.preventDefault();
}
onMonthDropdownChange(m) {
this.currentMonth = parseInt(m);
this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
this.createMonths(this.currentMonth, this.currentYear);
}
onYearDropdownChange(y) {
this.currentYear = parseInt(y);
this.onYearChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
this.createMonths(this.currentMonth, this.currentYear);
}
convertTo24Hour(hours, pm) {
//@ts-ignore
if (this.hourFormat == '12') {
if (hours === 12) {
return pm ? 12 : 0;
}
else {
return pm ? hours + 12 : hours;
}
}
return hours;
}
constrainTime(hour, minute, second, pm) {
let returnTimeTriple = [hour, minute, second];
let minHoursExceeds12 = false;
let value = this.value;
const convertedHour = this.convertTo24Hour(hour, pm);
const isRange = this.isRangeSelection(), isMultiple = this.isMultipleSelection(), isMultiValue = isRange || isMultiple;
if (isMultiValue) {
if (!this.value) {
this.value = [new Date(), new Date()];
}
if (isRange) {
value = this.value[1] || this.value[0];
}
if (isMultiple) {
value = this.value[this.value.length - 1];
}
}
const valueDateString = value ? value.toDateString() : null;
let isMinDate = this.minDate && valueDateString && this.minDate.toDateString() === valueDateString;
let isMaxDate = this.maxDate && valueDateString && this.maxDate.toDateString() === valueDateString;
if (isMinDate) {
minHoursExceeds12 = this.minDate.getHours() >= 12;
}
switch (true // intentional fall through
) {
case isMinDate && minHoursExceeds12 && this.minDate.getHours() === 12 && this.minDate.getHours() > convertedHour:
returnTimeTriple[0] = 11;
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() > minute:
returnTimeTriple[1] = this.minDate.getMinutes();
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() === minute && this.minDate.getSeconds() > second:
returnTimeTriple[2] = this.minDate.getSeconds();
break;
case isMinDate && !minHoursExceeds12 && this.minDate.getHours() - 1 === convertedHour && this.minDate.getHours() > convertedHour:
returnTimeTriple[0] = 11;
this.pm = true;
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() > minute:
returnTimeTriple[1] = this.minDate.getMinutes();
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() === minute && this.minDate.getSeconds() > second:
returnTimeTriple[2] = this.minDate.getSeconds();
break;
case isMinDate && minHoursExceeds12 && this.minDate.getHours() > convertedHour && convertedHour !== 12:
this.setCurrentHourPM(this.minDate.getHours());
returnTimeTriple[0] = this.currentHour || 0;
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() > minute:
returnTimeTriple[1] = this.minDate.getMinutes();
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() === minute && this.minDate.getSeconds() > second:
returnTimeTriple[2] = this.minDate.getSeconds();
break;
case isMinDate && this.minDate.getHours() > convertedHour:
returnTimeTriple[0] = this.minDate.getHours();
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() > minute:
returnTimeTriple[1] = this.minDate.getMinutes();
case isMinDate && this.minDate.getHours() === convertedHour && this.minDate.getMinutes() === minute && this.minDate.getSeconds() > second:
returnTimeTriple[2] = this.minDate.getSeconds();
break;
case isMaxDate && this.maxDate.getHours() < convertedHour:
returnTimeTriple[0] = this.maxDate.getHours();
case isMaxDate && this.maxDate.getHours() === convertedHour && this.maxDate.getMinutes() < minute:
returnTimeTriple[1] = this.maxDate.getMinutes();
case isMaxDate && this.maxDate.getHours() === convertedHour && this.maxDate.getMinutes() === minute && this.maxDate.getSeconds() < second:
returnTimeTriple[2] = this.maxDate.getSeconds();
break;
}
return returnTimeTriple;
}
incrementHour(event) {
const prevHour = this.currentHour ?? 0;
let newHour = (this.currentHour ?? 0) + this.stepHour;
let newPM = this.pm;
if (this.hourFormat == '24')
newHour = newHour >= 24 ? newHour - 24 : newHour;
else if (this.hourFormat == '12') {
// Before the AM/PM break, now after
if (prevHour < 12 && newHour > 11) {
newPM = !this.pm;
}
newHour = newHour >= 13 ? newHour - 12 : newHour;
}
this.toggleAMPMIfNotMinDate(newPM);
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(newHour, this.currentMinute, this.currentSecond, newPM);
event.preventDefault();
}
toggleAMPMIfNotMinDate(newPM) {
let value = this.value;
const valueDateString = value ? value.toDateString() : null;
let isMinDate = this.minDate && valueDateString && this.minDate.toDateString() === valueDateString;
if (isMinDate && this.minDate.getHours() >= 12) {
this.pm = true;
}
else {
this.pm = newPM;
}
}
onTimePickerElementMouseDown(event, type, direction) {
if (!this.$disabled()) {
this.repeat(event, null, type, direction);
event.preventDefault();
}
}
onTimePickerElementMouseUp(event) {
if (!this.$disabled()) {
this.clearTimePickerTimer();
this.updateTime();
}
}
onTimePickerElementMouseLeave() {
if (!this.$disabled() && this.timePickerTimer) {
this.clearTimePickerTimer();
this.updateTime();
}
}
repeat(event, interval, type, direction) {
let i = interval || 500;
this.clearTimePickerTimer();
this.timePickerTimer = setTimeout(() => {
this.repeat(event, 100, type, direction);
this.cd.markForCheck();
}, i);
switch (type) {
case 0:
if (direction === 1)
this.incrementHour(event);
else
this.decrementHour(event);
break;
case 1:
if (direction === 1)
this.incrementMinute(event);
else
this.decrementMinute(event);
break;
case 2:
if (direction === 1)
this.incrementSecond(event);
else
this.decrementSecond(event);
break;
}
this.updateInputfield();
}
clearTimePickerTimer() {
if (this.timePickerTimer) {
clearTimeout(this.timePickerTimer);
this.timePickerTimer = null;
}
}
decrementHour(event) {
let newHour = (this.currentHour ?? 0) - this.stepHour;
let newPM = this.pm;
if (this.hourFormat == '24')
newHour = newHour < 0 ? 24 + newHour : newHour;
else if (this.hourFormat == '12') {
// If we were at noon/midnight, then switch
if (this.currentHour === 12) {
newPM = !this.pm;
}
newHour = newHour <= 0 ? 12 + newHour : newHour;
}
this.toggleAMPMIfNotMinDate(newPM);
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(newHour, this.currentMinute, this.currentSecond, newPM);
event.preventDefault();
}
incrementMinute(event) {
let newMinute = (this.currentMinute ?? 0) + this.stepMinute;
newMinute = newMinute > 59 ? newMinute - 60 : newMinute;
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(this.currentHour || 0, newMinute, this.currentSecond, this.pm);
event.preventDefault();
}
decrementMinute(event) {
let newMinute = (this.currentMinute ?? 0) - this.stepMinute;
newMinute = newMinute < 0 ? 60 + newMinute : newMinute;
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(this.currentHour || 0, newMinute, this.currentSecond || 0, this.pm);
event.preventDefault();
}
incrementSecond(event) {
let newSecond = this.currentSecond + this.stepSecond;
newSecond = newSecond > 59 ? newSecond - 60 : newSecond;
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(this.currentHour || 0, this.currentMinute || 0, newSecond, this.pm);
event.preventDefault();
}
decrementSecond(event) {
let newSecond = this.currentSecond - this.stepSecond;
newSecond = newSecond < 0 ? 60 + newSecond : newSecond;
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(this.currentHour || 0, this.currentMinute || 0, newSecond, this.pm);
event.preventDefault();
}
updateTime() {
let value = this.value;
if (this.isRangeSelection()) {
value = this.value[1] || this.value[0];
}
if (this.isMultipleSelection()) {
value = this.value[this.value.length - 1];
}
value = value ? new Date(value.getTime()) : new Date();
if (this.hourFormat == '12') {
if (this.currentHour === 12)
value.setHours(this.pm ? 12 : 0);
else
value.setHours(this.pm ? this.currentHour + 12 : this.currentHour);
}
else {
value.setHours(this.currentHour);
}
value.setMinutes(this.currentMinute);
value.setSeconds(this.currentSecond);
if (this.isRangeSelection()) {
if (this.value[1])
value = [this.value[0], value];
else
value = [value, null];
}
if (this.isMultipleSelection()) {
value = [...this.value.slice(0, -1), value];
}
this.updateModel(value);
this.onSelect.emit(value);
this.updateInputfield();
}
toggleAMPM(event) {
const newPM = !this.pm;
this.pm = newPM;
[this.currentHour, this.currentMinute, this.currentSecond] = this.constrainTime(this.currentHour || 0, this.currentMinute || 0, this.currentSecond || 0, newPM);
this.updateTime();
event.preventDefault();
}
onUserInput(event) {
// IE 11 Workaround for input placeholder : https://github.com/primefaces/primeng/issues/2026
if (!this.isKeydown) {
return;
}
this.isKeydown = false;
let val = event.target.value;
try {
let value = this.parseValueFromString(val);
if (this.isValidSelection(value)) {
this.updateModel(value);
this.updateUI();
}
else if (this.keepInvalid) {
this.updateModel(value);
}
}
catch (err) {
//invalid date
let value = this.keepInvalid ? val : null;
this.updateModel(value);
}
this.onInput.emit(event);
}
isValidSelection(value) {
if (this.isSingleSelection()) {
return this.isSelectable(value.getDate(), value.getMonth(), value.getFullYear(), false);
}
let isValid = value.every((v) => this.isSelectable(v.getDate(), v.getMonth(), v.getFullYear(), false));
if (isValid && this.isRangeSelection()) {
isValid = value.length === 1 || (value.length > 1 && value[1] >= value[0]);
}
return isValid;
}
parseValueFromString(text) {
if (!text || text.trim().length === 0) {
return null;
}
let value;
if (this.isSingleSelection()) {
value = this.parseDateTime(text);
}
else if (this.isMultipleSelection()) {
let tokens = text.split(this.multipleSeparator);
value = [];
for (let token of tokens) {
value.push(this.parseDateTime(token.trim()));
}
}
else if (this.isRangeSelection()) {
let tokens = text.split(' ' + this.rangeSeparator + ' ');
value = [];
for (let i = 0; i < tokens.length; i++) {
value[i] = this.parseDateTime(tokens[i].trim());
}
}
return value;
}
parseDateTime(text) {
let date;
let parts = text.split(' ');
if (this.timeOnly) {
date = new Date();
this.populateTime(date, parts[0], parts[1]);
}
else {
const dateFormat = this.getDateFormat();
if (this.showTime) {
let ampm = this.hourFormat == '12' ? parts.pop() : null;
let timeString = parts.pop();
date = this.parseDate(parts.join(' '), dateFormat);
this.populateTime(date, timeString, ampm);
}
else {
date = this.parseDate(text, dateFormat);
}
}
// Convert from Buddhist Era if inputBudhistYear is true
if (this.inputBudhistYear && date) {
date.setFullYear(date.getFullYear() - 543);
}
return date;
}
populateTime(value, timeString, ampm) {
if (this.hourFormat == '12' && !ampm) {
throw 'Invalid Time';
}
this.pm = ampm === 'PM' || ampm === 'pm';
let time = this.parseTime(timeString);
value.setHours(time.hour);
value.setMinutes(time.minute);
value.setSeconds(time.second);
}
isValidDate(date) {
return isDate(date) && isNotEmpty(date);
}
updateUI() {
let propValue = this.value;
if (Array.isArray(propValue)) {
propValue = propValue.length === 2 ? propValue[1] : propValue[0];
}
// Determine if we have an actual value or using fallback
const hasValue = propValue && this.isValidDate(propValue);
const hasDefaultDate = this.defaultDate && this.isValidDate(this.defaultDate) && !this.value;
let val = hasDefaultDate ? this.defaultDate : hasValue ? propValue : new Date();
this.currentMonth = val.getMonth();
// Only convert Buddhist year to Gregorian when we have an actual value with inputBudhistYear
// When falling back to new Date(), it's already Gregorian
this.currentYear = (this.inputBudhistYear && (hasValue || hasDefaultDate)) ? val.getFullYear() - 543 : val.getFullYear();
this.createMonths(this.currentMonth, this.currentYear);
if (this.showTime || this.timeOnly) {
this.setCurrentHourPM(val.getHours());
this.currentMinute = val.getMinutes();
this.currentSecond = this.showSeconds ? val.getSeconds() : 0;
}
}
showOverlay() {
if (!this.overlayVisible) {
this.updateUI();
if (!this.touchUI) {
this.preventFocus = true;
}
this.overlayMinWidth = this.el.nativeElement.offsetWidth;
this.overlayVisible = true;
}
}
hideOverlay() {
this.inputfieldViewChild?.nativeElement.focus();
this.overlayVisible = false;
this.clearTimePickerTimer();
if (this.touchUI) {
this.disableModality();
}
this.cd.markForCheck();
}
toggle() {
if (!this.inline) {
if (!this.overlayVisible) {
this.showOverlay();
this.inputfieldViewChild?.nativeElement.focus();
}
else {
this.hideOverlay();
}
}
}
onOverlayBeforeEnter(event) {
this.overlay = event.element;
this.$attrSelector && this.overlay.setAttribute(this.$attrSelector, '');
const styles = !this.inline ? { position: 'absolute', top: '0', minWidth: `${this.overlayMinWidth}px` } : undefined;
addStyle(this.overlay, styles || {});
this.appendOverlay();
this.alignOverlay();
this.setZIndex();
this.updateFocus();
this.bindListeners();
this.onShow.emit(event.element);
}
onOverlayAfterLeave(event) {
if (this.autoZIndex) {
ZIndexUtils.clear(event.element);
}
this.restoreOverlayAppend();
this.onOverlayHide();
this.onClose.emit(event.element);
}
appendOverlay() {
if (this.$appendTo() && this.$appendTo() !== 'self') {
if (this.$appendTo() === 'body')
this.document.body.appendChild(this.overlay);
else
appendChild(this.$appendTo(), this.overlay);
}
}
restoreOverlayAppend() {
if (this.overlay && this.$appendTo() !== 'self') {
this.el.nativeElement.appendChild(this.overlay);
}
}
alignOverlay() {
if (this.touchUI) {
this.enableModality(this.overlay);
}
else if (this.overlay) {
if (this.$appendTo() && this.$appendTo() !== 'self') {
absolutePosition(this.overlay, this.inputfieldViewChild?.nativeElement);
}
else {
relativePosition(this.overlay, this.inputfieldViewChild?.nativeElement);
}
}
}
bindListeners() {
this.bindDocumentClickListener();
this.bindDocumentResizeListener();
this.bindScrollListener();
}
setZIndex() {
if (this.autoZIndex) {
if (this.touchUI)
ZIndexUtils.set('modal', this.overlay, this.baseZIndex || this.config.zIndex.modal);
else
ZIndexUtils.set('overlay', this.overlay, this.baseZIndex || this.config.zIndex.overlay);
}
}
enableModality(element) {
if (!this.mask && this.touchUI) {
this.mask = this.renderer.createElement('div');
this.renderer.setStyle(this.mask, 'zIndex', String(parseInt(element.style.zIndex) - 1));
let maskStyleClass = 'p-overlay-mask p-datepicker-mask p-datepicker-mask-scrollblocker p-overlay-mask p-overlay-mask-enter-active';
addClass(this.mask, maskStyleClass);
this.maskClickListener = this.renderer.listen(this.mask, 'click', (event) => {
this.disableModality();
this.overlayVisible = false;
});
this.renderer.appendChild(this.document.body, this.mask);
blockBodyScroll();
}
}
disableModality() {
if (this.mask) {
addClass(this.mask, 'p-overlay-mask-leave');
if (!this.animationEndListener) {
this.animationEndListener = this.renderer.listen(this.mask, 'animationend', this.destroyMask.bind(this));
}
}
}
destroyMask() {
if (!this.mask) {
return;
}
this.renderer.removeChild(this.document.body, this.mask);
let bodyChildren = this.document.body.children;
let hasBlockerMasks;
for (let i = 0; i < bodyChildren.length; i++) {
let bodyChild = bodyChildren[i];
if (hasClass(bodyChild, 'p-datepicker-mask-scrollblocker')) {
hasBlockerMasks = true;
break;
}
}
if (!hasBlockerMasks) {
unblockBodyScroll();
}
this.unbindAnimationEndListener();
this.unbindMaskClickListener();
this.mask = null;
}
unbindMaskClickListener() {
if (this.maskClickListener) {
this.maskClickListener();
this.maskClickListener = null;
}
}
unbindAnimationEndListener() {
if (this.animationEndListener && this.mask) {
this.animationEndListener();
this.animationEndListener = null;
}
}
getDateFormat() {
return this.dateFormat || this.getTranslation('dateFormat');
}
getFirstDateOfWeek() {
return this._firstDayOfWeek || this.getTranslation(TranslationKeys.FIRST_DAY_OF_WEEK);
}
// Ported from jquery-ui datepicker formatDate
formatDate(date, format) {
if (!date) {
return '';
}
let iFormat;
const lookAhead = (match) => {
const matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match;
if (matches) {
iFormat++;
}
return matches;
}, formatNumber = (match, value, len) => {
let num = '' + value;
if (lookAhead(match)) {
while (num.length < len) {
num = '0' + num;
}
}
return num;
}, formatName = (match, value, shortNames, longNames) => {
return lookAhead(match) ? longNames[value] : shortNames[value];
};
let output = '';
let literal = false;
if (date) {
for (iFormat = 0; iFormat < format.length; iFormat++) {
if (literal) {
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
literal = false;
}
else {
output += format.charAt(iFormat);
}
}
else {
switch (format.charAt(iFormat)) {
case 'd':
output += formatNumber('d', date.getDate(), 2);
break;
case 'D':
output += formatName('D', date.getDay(), this.getTranslation(TranslationKeys.DAY_NAMES_SHORT), this.getTranslation(TranslationKeys.DAY_NAMES));
break;
case 'o':
output += formatNumber('o', Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
break;
case 'm':
output += formatNumber('m', date.getMonth() + 1, 2);
break;
case 'M':
output += formatName('M', date.getMonth(), this.getTranslation(TranslationKeys.MONTH_NAMES_SHORT), this.getTranslation(TranslationKeys.MONTH_NAMES));
break;
case 'y':
// If inputBudhistYear is true, date year is Buddhist (2568), convert to Gregorian first (2025)
// Then add yearBudhist offset based on isBudhistYear for display
const baseYear = this.inputBudhistYear ? date.getFullYear() - 543 : date.getFullYear();
const displayYear = baseYear + this.yearBudhist;
output += lookAhead('y') ? displayYear : ((displayYear % 100 < 10 ? '0' : '') + (displayYear % 100));
break;
case '@':
output += date.getTime();
break;
case '!':
output += date.getTime() * 10000 + this.ticksTo1970;
break;
case "'":
if (lookAhead("'")) {
output += "'";
}
else {
literal = true;
}
break;
default:
output += format.charAt(iFormat);
}
}
}
}
return output;
}
formatTime(date) {
if (!date) {
return '';
}
let output = '';
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
if (this.hourFormat == '12' && hours > 11 && hours != 12) {
hours -= 12;
}
if (this.hourFormat == '12') {
output += hours === 0 ? 12 : hours < 10 ? '0' + hours : hours;
}
else {
output += hours < 10 ? '0' + hours : hours;
}
output += ':';
output += minutes < 10 ? '0' + minutes : minutes;
if (this.showSeconds) {
output += ':';
output += seconds < 10 ? '0' + seconds : seconds;
}
if (this.hourFormat == '12') {
output += date.getHours() > 11 ? ' PM' : ' AM';
}
return output;
}
parseTime(value) {
let tokens = value.split(':');
let validTokenLength = this.showSeconds ? 3 : 2;
if (tokens.length !== validTokenLength) {
throw 'Invalid time';
}
let h = parseInt(tokens[0]);
let m = parseInt(tokens[1]);
let s = this.showSeconds ? parseInt(tokens[2]) : null;
if (isNaN(h) || isNaN(m) || h > 23 || m > 59 || (this.hourFormat == '12' && h > 12) || (this.showSeconds && (isNaN(s) || s > 59))) {
throw 'Invalid time';
}
else {
if (this.hourFormat == '12') {
if (h !== 12 && this.pm) {
h += 12;
}
else if (!this.pm && h === 12) {
h -= 12;
}
}
return { hour: h, minute: m, second: s };
}
}
// Ported from jquery-ui datepicker parseDate
parseDate(value, format) {
if (format == null || value == null) {
throw 'Invalid arguments';
}
value = typeof value === 'object' ? value.toString() : value + '';
if (value === '') {
return null;
}
let iFormat, dim, extra, iValue = 0, shortYearCutoff = typeof this.shortYearCutoff !== 'string' ? this.shortYearCutoff : (new Date().getFullYear() % 100) + parseInt(this.shortYearCutoff, 10), year = -1, month = -1, day = -1, doy = -1, literal = false, date, lookAhead = (match) => {
let matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match;
if (matches) {
iFormat++;
}
return matches;
}, getNumber = (match) => {
let isDoubled = lookAhead(match), size = match === '@' ? 14 : match === '!' ? 20 : match === 'y' && isDoubled ? 4 : match === 'o' ? 3 : 2, minSize = match === 'y' ? size : 1, digits = new RegExp('^\\d{' + minSize + ',' + size + '}'), num = value.substring(iValue).match(digits);
if (!num) {
throw 'Missing number at position ' + iValue;
}
iValue += num[0].length;
return parseInt(num[0], 10);
}, getName = (match, shortNames, longNames) => {
let index = -1;
let arr = lookAhead(match) ? longNames : shortNames;
let names = [];
for (let i = 0; i < arr.length; i++) {
names.push([i, arr[i]]);
}
names.sort((a, b) => {
return -(a[1].length - b[1].length);
});
for (let i = 0; i < names.length; i++) {
let name = names[i][1];
if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
index = names[i][0];
iValue += name.length;
break;
}
}
if (index !== -1) {
return index + 1;
}
else {
throw 'Unknown name at position ' + iValue;
}
}, checkLiteral = () => {
if (value.charAt(iValue) !== format.charAt(iFormat)) {
throw 'Unexpected literal at position ' + iValue;
}
iValue++;
};
if (this.view === 'month') {
day = 1;
}
for (iFormat = 0; iFormat < format.length; iFormat++) {
if (literal) {
if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
literal = false;
}
else {
checkLiteral();
}
}
else {
switch (format.charAt(iFormat)) {
case 'd':
day = getNumber('d');
break;
case 'D':
getName('D', this.getTranslation(TranslationKeys.DAY_NAMES_SHORT), this.getTranslation(TranslationKeys.DAY_NAMES));
break;
case 'o':
doy = getNumber('o');
break;
case 'm':
month = getNumber('m');
break;
case 'M':
month = getName('M', this.getTranslation(TranslationKeys.MONTH_NAMES_SHORT), this.getTranslation(TranslationKeys.MONTH_NAMES));
break;
case 'y':
year = getNumber('y');
break;
case '@':
date = new Date(getNumber('@'));
year = date.getFullYear();
month = date.getMonth() + 1;
day = date.getDate();
break;
case '!':
date = new Date((getNumber('!') - this.ticksTo1970) / 10000);
year = date.getFullYear();
month = date.getMonth() + 1;
day = date.getDate();
break;
case "'":
if (lookAhead("'")) {
checkLiteral();
}
else {
literal = true;
}
break;
default:
checkLiteral();
}
}
}
if (iValue < value.length) {
extra = value.substr(iValue);
if (!/^\s+/.test(extra)) {
throw 'Extra/unparsed characters found in date: ' + extra;
}
}
if (year === -1) {
year = new Date().getFullYear();
}
else if (year < 100) {
year += new Date().getFullYear() - (new Date().getFullYear() % 100) + (year <= shortYearCutoff ? 0 : -100);
}
if (doy > -1) {
month = 1;
day = doy;
do {
dim = this.getDaysCountInMonth(year, month - 1);
if (day <= dim) {
break;
}
month++;
day -= dim;
} while (true);
}
if (this.view === 'year') {
month = month === -1 ? 1 : month;
day = day === -1 ? 1 : day;
}
date = this.daylightSavingAdjust(new Date(year, month - 1, day));
if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
throw 'Invalid date'; // E.g. 31/02/00
}
return date;
}
daylightSavingAdjust(date) {
if (!date) {
return null;
}
date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
return date;
}
isValidDateForTimeConstraints(selectedDate) {
if (this.keepInvalid) {
return true; // If we are keeping invalid dates, we don't need to check for time constraints
}
return (!this.minDate || selectedDate >= this.minDate) && (!this.maxDate || selectedDate <= this.maxDate);
}
onTodayButtonClick(event) {
const date = new Date();
const dateMeta = {
day: date.getDate(),
month: date.getMonth(),
year: date.getFullYear(),
otherMonth: date.getMonth() !== this.currentMonth || date.getFullYear() !== this.currentYear,
today: true,
selectable: true
};
this.createMonths(date.getMonth(), date.getFullYear());
this.onDateSelect(event, dateMeta);
this.onTodayClick.emit(date);
}
onClearButtonClick(event) {
this.updateModel(null);
this.updateInputfield();
this.hideOverlay();
this.onClearClick.emit(event);
}
createResponsiveStyle() {
if (this.numberOfMonths > 1 && this.responsiveOptions) {
if (!this.responsiveStyleElement) {
this.responsiveStyleElement = this.renderer.createElement('style');
this.responsiveStyleElement.type = 'text/css';
setAttribute(this.responsiveStyleElement, 'nonce', this.config?.csp()?.nonce);
this.renderer.appendChild(this.document.body, this.responsiveStyleElement);
}
let innerHTML = '';
if (this.responsiveOptions) {
let responsiveOptions = [...this.responsiveOptions].filter((o) => !!(o.breakpoint && o.numMonths)).sort((o1, o2) => -1 * o1.breakpoint.localeCompare(o2.breakpoint, undefined, { numeric: true }));
for (let i = 0; i < responsiveOptions.length; i++) {
let { breakpoint, numMonths } = responsiveOptions[i];
let styles = `
.p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${numMonths}) .p-datepicker-next {
display: inline-flex !important;
}
`;
for (let j = numMonths; j < this.numberOfMonths; j++) {
styles += `
.p-datepicker[${this.attributeSelector}] .p-datepicker-group:nth-child(${j + 1}) {
display: none !important;
}
`;
}
innerHTML += `
@media screen and (max-width: ${breakpoint}) {
${styles}
}
`;
}
}
this.responsiveStyleElement.innerHTML = innerHTML;
setAttribute(this.responsiveStyleElement, 'nonce', this.config?.csp()?.nonce);
}
}
destroyResponsiveStyleElement() {
if (this.responsiveStyleElement) {
this.responsiveStyleElement.remove();
this.responsiveStyleElement = null;
}
}
bindDocumentClickListener() {
if (!this.documentClickListener) {
this.zone.runOutsideAngular(() => {
const documentTarget = this.el ? this.el.nativeElement.ownerDocument : this.document;
this.documentClickListener = this.renderer.listen(documentTarget, 'mousedown', (event) => {
if (this.isOutsideClicked(event) && this.overlayVisible) {
this.zone.run(() => {
this.hideOverlay();
this.onClickOutside.emit(event);
this.cd.markForCheck();
});
}
});
});
}
}
unbindDocumentClickListener() {
if (this.documentClickListener) {
this.documentClickListener();
this.documentClickListener = null;
}
}
bindDocumentResizeListener() {
if (!this.documentResizeListener && !this.touchUI) {
this.documentResizeListener = this.renderer.listen(this.window, 'resize', this.onWindowResize.bind(this));
}
}
unbindDocumentResizeListener() {
if (this.documentResizeListener) {
this.documentResizeListener();
this.documentResizeListener = null;
}
}
bindScrollListener() {
if (!this.scrollHandler) {
this.scrollHandler = new ConnectedOverlayScrollHandler(this.el?.nativeElement, () => {
if (this.overlayVisible) {
this.hideOverlay();
}
});
}
this.scrollHandler.bindScrollListener();
}
unbindScrollListener() {
if (this.scrollHandler) {
this.scrollHandler.unbindScrollListener();
}
}
isOutsideClicked(event) {
return !(this.el.nativeElement.isSameNode(event.target) || this.isNavIconClicked(event) || this.el.nativeElement.contains(event.target) || (this.overlay && this.overlay.contains(event.target)));
}
isNavIconClicked(event) {
return hasClass(event.target, 'p-datepicker-prev-button') || hasClass(event.target, 'p-datepicker-prev-icon') || hasClass(event.target, 'p-datepicker-next-button') || hasClass(event.target, 'p-datepicker-next-icon');
}
onWindowResize() {
if (this.overlayVisible && !isTouchDevice()) {
this.hideOverlay();
}
}
onOverlayHide() {
this.currentView = this.view;
if (this.mask) {
this.destroyMask();
}
this.unbindDocumentClickListener();
this.unbindDocumentResizeListener();
this.unbindScrollListener();
this.overlay = null;
}
/**
* @override
*
* @see {@link BaseEditableHolder.writeControlValue}
* Writes the value to the control.
*/
writeControlValue(value) {
this.value = value;
if (this.value && typeof this.value === 'string') {
try {
this.value = this.parseValueFromString(this.value);
}
catch {
if (this.keepInvalid) {
this.value = value;
}
}
}
this.updateInputfield();
this.updateUI();
this.cd.markForCheck();
}
onDestroy() {
if (this.scrollHandler) {
this.scrollHandler.destroy();
this.scrollHandler = null;
}
if (this.translationSubscription) {
this.translationSubscription.unsubscribe();
}
if (this.overlay && this.autoZIndex) {
ZIndexUtils.clear(this.overlay);
}
this.destroyResponsiveStyleElement();
this.clearTimePickerTimer();
this.restoreOverlayAppend();
this.onOverlayHide();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePicker, deps: [{ token: i0.NgZone }, { token: i1.OverlayService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: DatePicker, isStandalone: true, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: { iconDisplay: { classPropertyName: "iconDisplay", publicName: "iconDisplay", isSignal: false, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: false, isRequired: false, transformFunction: null }, inputStyle: { classPropertyName: "inputStyle", publicName: "inputStyle", isSignal: false, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: false, isRequired: false, transformFunction: null }, inputStyleClass: { classPropertyName: "inputStyleClass", publicName: "inputStyleClass", isSignal: false, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: false, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: false, isRequired: false, transformFunction: null }, iconAriaLabel: { classPropertyName: "iconAriaLabel", publicName: "iconAriaLabel", isSignal: false, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: false, isRequired: false, transformFunction: null }, multipleSeparator: { classPropertyName: "multipleSeparator", publicName: "multipleSeparator", isSignal: false, isRequired: false, transformFunction: null }, rangeSeparator: { classPropertyName: "rangeSeparator", publicName: "rangeSeparator", isSignal: false, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showOtherMonths: { classPropertyName: "showOtherMonths", publicName: "showOtherMonths", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, selectOtherMonths: { classPropertyName: "selectOtherMonths", publicName: "selectOtherMonths", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: false, isRequired: false, transformFunction: null }, readonlyInput: { classPropertyName: "readonlyInput", publicName: "readonlyInput", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, shortYearCutoff: { classPropertyName: "shortYearCutoff", publicName: "shortYearCutoff", isSignal: false, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: false, isRequired: false, transformFunction: null }, timeOnly: { classPropertyName: "timeOnly", publicName: "timeOnly", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, stepHour: { classPropertyName: "stepHour", publicName: "stepHour", isSignal: false, isRequired: false, transformFunction: numberAttribute }, stepMinute: { classPropertyName: "stepMinute", publicName: "stepMinute", isSignal: false, isRequired: false, transformFunction: numberAttribute }, stepSecond: { classPropertyName: "stepSecond", publicName: "stepSecond", isSignal: false, isRequired: false, transformFunction: numberAttribute }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showOnFocus: { classPropertyName: "showOnFocus", publicName: "showOnFocus", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showWeek: { classPropertyName: "showWeek", publicName: "showWeek", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, startWeekFromFirstDayOfYear: { classPropertyName: "startWeekFromFirstDayOfYear", publicName: "startWeekFromFirstDayOfYear", isSignal: false, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: false, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: false, isRequired: false, transformFunction: null }, maxDateCount: { classPropertyName: "maxDateCount", publicName: "maxDateCount", isSignal: false, isRequired: false, transformFunction: numberAttribute }, showButtonBar: { classPropertyName: "showButtonBar", publicName: "showButtonBar", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, todayButtonStyleClass: { classPropertyName: "todayButtonStyleClass", publicName: "todayButtonStyleClass", isSignal: false, isRequired: false, transformFunction: null }, clearButtonStyleClass: { classPropertyName: "clearButtonStyleClass", publicName: "clearButtonStyleClass", isSignal: false, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, autoZIndex: { classPropertyName: "autoZIndex", publicName: "autoZIndex", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, baseZIndex: { classPropertyName: "baseZIndex", publicName: "baseZIndex", isSignal: false, isRequired: false, transformFunction: numberAttribute }, panelStyleClass: { classPropertyName: "panelStyleClass", publicName: "panelStyleClass", isSignal: false, isRequired: false, transformFunction: null }, panelStyle: { classPropertyName: "panelStyle", publicName: "panelStyle", isSignal: false, isRequired: false, transformFunction: null }, keepInvalid: { classPropertyName: "keepInvalid", publicName: "keepInvalid", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, hideOnDateTimeSelect: { classPropertyName: "hideOnDateTimeSelect", publicName: "hideOnDateTimeSelect", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, touchUI: { classPropertyName: "touchUI", publicName: "touchUI", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, timeSeparator: { classPropertyName: "timeSeparator", publicName: "timeSeparator", isSignal: false, isRequired: false, transformFunction: null }, focusTrap: { classPropertyName: "focusTrap", publicName: "focusTrap", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showTransitionOptions: { classPropertyName: "showTransitionOptions", publicName: "showTransitionOptions", isSignal: false, isRequired: false, transformFunction: null }, hideTransitionOptions: { classPropertyName: "hideTransitionOptions", publicName: "hideTransitionOptions", isSignal: false, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: false, isRequired: false, transformFunction: numberAttribute }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: false, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: false, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: false, isRequired: false, transformFunction: null }, disabledDays: { classPropertyName: "disabledDays", publicName: "disabledDays", isSignal: false, isRequired: false, transformFunction: null }, showTime: { classPropertyName: "showTime", publicName: "showTime", isSignal: false, isRequired: false, transformFunction: null }, responsiveOptions: { classPropertyName: "responsiveOptions", publicName: "responsiveOptions", isSignal: false, isRequired: false, transformFunction: null }, numberOfMonths: { classPropertyName: "numberOfMonths", publicName: "numberOfMonths", isSignal: false, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: false, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: false, isRequired: false, transformFunction: null }, defaultDate: { classPropertyName: "defaultDate", publicName: "defaultDate", isSignal: false, isRequired: false, transformFunction: null }, isBudhistYear: { classPropertyName: "isBudhistYear", publicName: "isBudhistYear", isSignal: false, isRequired: false, transformFunction: null }, inputBudhistYear: { classPropertyName: "inputBudhistYear", publicName: "inputBudhistYear", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, outputBudhistYear: { classPropertyName: "outputBudhistYear", publicName: "outputBudhistYear", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, motionOptions: { classPropertyName: "motionOptions", publicName: "motionOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFocus: "onFocus", onBlur: "onBlur", onClose: "onClose", onSelect: "onSelect", onClear: "onClear", onInput: "onInput", onTodayClick: "onTodayClick", onClearClick: "onClearClick", onMonthChange: "onMonthChange", onYearChange: "onYearChange", onClickOutside: "onClickOutside", onShow: "onShow" }, host: { properties: { "class": "cn(cx('root'), styleClass)", "style": "sx('root')" } }, providers: [DATEPICKER_VALUE_ACCESSOR, DatePickerStyle, { provide: DATEPICKER_INSTANCE, useExisting: DatePicker }, { provide: PARENT_INSTANCE, useExisting: DatePicker }], queries: [{ propertyName: "dateTemplate", first: true, predicate: ["date"] }, { propertyName: "headerTemplate", first: true, predicate: ["header"] }, { propertyName: "footerTemplate", first: true, predicate: ["footer"] }, { propertyName: "disabledDateTemplate", first: true, predicate: ["disabledDate"] }, { propertyName: "decadeTemplate", first: true, predicate: ["decade"] }, { propertyName: "previousIconTemplate", first: true, predicate: ["previousicon"] }, { propertyName: "nextIconTemplate", first: true, predicate: ["nexticon"] }, { propertyName: "triggerIconTemplate", first: true, predicate: ["triggericon"] }, { propertyName: "clearIconTemplate", first: true, predicate: ["clearicon"] }, { propertyName: "decrementIconTemplate", first: true, predicate: ["decrementicon"] }, { propertyName: "incrementIconTemplate", first: true, predicate: ["incrementicon"] }, { propertyName: "inputIconTemplate", first: true, predicate: ["inputicon"] }, { propertyName: "buttonBarTemplate", first: true, predicate: ["buttonbar"] }, { propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "inputfieldViewChild", first: true, predicate: ["inputfield"], descendants: true }, { propertyName: "content", first: true, predicate: ["contentWrapper"], descendants: true }], usesInheritance: true, hostDirectives: [{ directive: i2.Bind }], ngImport: i0, template: `
<ng-template [ngIf]="!inline">
<input
#inputfield
pInputText
[pSize]="size()"
[attr.size]="inputSize()"
type="text"
role="combobox"
[attr.id]="inputId"
[attr.name]="name()"
[attr.aria-required]="required()"
aria-autocomplete="none"
aria-haspopup="dialog"
[attr.aria-expanded]="overlayVisible ?? false"
[attr.aria-controls]="overlayVisible ? panelId : null"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-label]="ariaLabel"
[value]="inputFieldValue"
(focus)="onInputFocus($event)"
(keydown)="onInputKeydown($event)"
(click)="onInputClick()"
(blur)="onInputBlur($event)"
[attr.required]="required() ? '' : undefined"
[attr.readonly]="readonlyInput ? '' : undefined"
[attr.disabled]="$disabled() ? '' : undefined"
(input)="onUserInput($event)"
[ngStyle]="inputStyle"
[class]="cn(cx('pcInputText'), inputStyleClass)"
[attr.placeholder]="placeholder"
[attr.tabindex]="tabindex"
[attr.inputmode]="touchUI ? 'off' : null"
autocomplete="off"
[pAutoFocus]="autofocus"
[variant]="$variant()"
[fluid]="hasFluid"
[invalid]="invalid()"
[pt]="ptm('pcInputText')"
[unstyled]="unstyled()"
/>
<ng-container *ngIf="showClear && !$disabled() && inputfieldViewChild?.nativeElement?.value">
<svg data-p-icon="times" *ngIf="!clearIconTemplate && !_clearIconTemplate" [class]="cx('clearIcon')" [pBind]="ptm('inputIcon')" (click)="clear()" />
<span *ngIf="clearIconTemplate || _clearIconTemplate" [class]="cx('clearIcon')" [pBind]="ptm('inputIcon')" (click)="clear()">
<ng-template *ngTemplateOutlet="clearIconTemplate || _clearIconTemplate"></ng-template>
</span>
</ng-container>
<button
type="button"
[attr.aria-label]="iconButtonAriaLabel"
aria-haspopup="dialog"
[attr.aria-expanded]="overlayVisible ?? false"
[attr.aria-controls]="overlayVisible ? panelId : null"
*ngIf="showIcon && iconDisplay === 'button'"
(click)="onButtonClick($event, inputfield)"
[class]="cx('dropdown')"
[disabled]="$disabled()"
tabindex="0"
[pBind]="ptm('dropdown')"
>
<span *ngIf="icon" [ngClass]="icon" [pBind]="ptm('dropdownIcon')"></span>
<ng-container *ngIf="!icon">
<svg data-p-icon="calendar" *ngIf="!triggerIconTemplate && !_triggerIconTemplate" [pBind]="ptm('dropdownIcon')" />
<ng-template *ngTemplateOutlet="triggerIconTemplate || _triggerIconTemplate"></ng-template>
</ng-container>
</button>
<ng-container *ngIf="iconDisplay === 'input' && showIcon">
<span [class]="cx('inputIconContainer')" [pBind]="ptm('inputIconContainer')" [attr.data-p]="inputIconDataP">
<svg data-p-icon="calendar" (click)="onButtonClick($event)" *ngIf="!inputIconTemplate && !_inputIconTemplate" [class]="cx('inputIcon')" [pBind]="ptm('inputIcon')" />
<ng-container *ngTemplateOutlet="inputIconTemplate || _inputIconTemplate; context: { clickCallBack: onButtonClick.bind(this) }"></ng-container>
</span>
</ng-container>
</ng-template>
<p-motion [visible]="inline || overlayVisible" name="p-anchored-overlay" [appear]="!inline" [options]="computedMotionOptions()" (onBeforeEnter)="onOverlayBeforeEnter($event)" (onAfterLeave)="onOverlayAfterLeave($event)">
<div
#contentWrapper
[attr.id]="panelId"
[ngStyle]="panelStyle"
[class]="cn(cx('panel'), panelStyleClass)"
[attr.aria-label]="getTranslation('chooseDate')"
[attr.role]="inline ? null : 'dialog'"
[attr.aria-modal]="inline ? null : 'true'"
(click)="onOverlayClick($event)"
[pBind]="ptm('panel')"
>
<ng-content select="p-header"></ng-content>
<ng-container *ngTemplateOutlet="headerTemplate || _headerTemplate"></ng-container>
<ng-container *ngIf="!timeOnly">
<div [class]="cx('calendarContainer')" [pBind]="ptm('calendarContainer')">
<div [class]="cx('calendar')" *ngFor="let month of months; let i = index" [pBind]="ptm('calendar')">
<div [class]="cx('header')" [pBind]="ptm('header')">
<p-button
rounded
variant="text"
severity="secondary"
(keydown)="onContainerButtonKeydown($event)"
[styleClass]="cx('pcPrevButton')"
(onClick)="onPrevButtonClick($event)"
[ngStyle]="{ visibility: i === 0 ? 'visible' : 'hidden' }"
type="button"
[ariaLabel]="prevIconAriaLabel"
[pt]="ptm('pcPrevButton')"
[attr.data-pc-group-section]="'navigator'"
>
<ng-template #icon>
<svg data-p-icon="chevron-left" *ngIf="!previousIconTemplate && !_previousIconTemplate" />
<span *ngIf="previousIconTemplate || _previousIconTemplate">
<ng-template *ngTemplateOutlet="previousIconTemplate || _previousIconTemplate"></ng-template>
</span>
</ng-template>
</p-button>
<div [class]="cx('title')" [pBind]="ptm('title')">
<button
*ngIf="currentView === 'date'"
type="button"
(click)="switchToMonthView($event)"
(keydown)="onContainerButtonKeydown($event)"
[class]="cx('selectMonth')"
[attr.disabled]="switchViewButtonDisabled() ? '' : undefined"
[attr.aria-label]="this.getTranslation('chooseMonth')"
pRipple
[pBind]="ptm('selectMonth')"
[attr.data-pc-group-section]="'navigator'"
>
{{ getMonthName(month.month) }}
</button>
<button
*ngIf="currentView !== 'year'"
type="button"
(click)="switchToYearView($event)"
(keydown)="onContainerButtonKeydown($event)"
[class]="cx('selectYear')"
[attr.disabled]="switchViewButtonDisabled() ? '' : undefined"
[attr.aria-label]="getTranslation('chooseYear')"
pRipple
[pBind]="ptm('selectYear')"
[attr.data-pc-group-section]="'navigator'"
>
{{ getYear(month) }}
</button>
<span [class]="cx('decade')" *ngIf="currentView === 'year'" [pBind]="ptm('decade')">
<ng-container *ngIf="!decadeTemplate && !_decadeTemplate">{{ yearPickerValues()[0] }} - {{ yearPickerValues()[yearPickerValues().length - 1] }}</ng-container>
<ng-container *ngTemplateOutlet="decadeTemplate || _decadeTemplate; context: { $implicit: yearPickerValues }"></ng-container>
</span>
</div>
<p-button
rounded
variant="text"
severity="secondary"
(keydown)="onContainerButtonKeydown($event)"
[styleClass]="cx('pcNextButton')"
(onClick)="onNextButtonClick($event)"
[ngStyle]="{ visibility: i === months.length - 1 ? 'visible' : 'hidden' }"
[ariaLabel]="nextIconAriaLabel"
[pt]="ptm('pcNextButton')"
[attr.data-pc-group-section]="'navigator'"
>
<ng-template #icon>
<svg data-p-icon="chevron-right" *ngIf="!nextIconTemplate && !_nextIconTemplate" />
<ng-container *ngIf="nextIconTemplate || _nextIconTemplate">
<ng-template *ngTemplateOutlet="nextIconTemplate || _nextIconTemplate"></ng-template>
</ng-container>
</ng-template>
</p-button>
</div>
<table [class]="cx('dayView')" role="grid" *ngIf="currentView === 'date'" [pBind]="ptm('table')">
<thead [pBind]="ptm('tableHeader')">
<tr [pBind]="ptm('tableHeaderRow')">
<th *ngIf="showWeek" [class]="cx('weekHeader')" [pBind]="ptm('weekHeader')">
<span [pBind]="ptm('weekHeaderLabel')">{{ getTranslation('weekHeader') }}</span>
</th>
<th [class]="cx('weekDayCell')" scope="col" *ngFor="let weekDay of weekDays; let begin = first; let end = last" [pBind]="ptm('weekDayCell')">
<span [class]="cx('weekDay')" [pBind]="ptm('weekDay')">{{ weekDay }}</span>
</th>
</tr>
</thead>
<tbody [pBind]="ptm('tableBody')">
<tr *ngFor="let week of month.dates; let j = index" [pBind]="ptm('tableBodyRow')">
<td *ngIf="showWeek" [class]="cx('weekNumber')" [pBind]="ptm('weekNumber')">
<span [class]="cx('weekLabelContainer')" [pBind]="ptm('weekLabelContainer')">
{{ month.weekNumbers[j] }}
</span>
</td>
<td *ngFor="let date of week" [attr.aria-label]="date.day" [class]="cx('dayCell', { date })" [pBind]="ptm('dayCell')">
<ng-container *ngIf="date.otherMonth ? showOtherMonths : true">
<span
[ngClass]="dayClass(date)"
(click)="onDateSelect($event, date)"
draggable="false"
[attr.data-date]="formatDateKey(formatDateMetaToDate(date))"
(keydown)="onDateCellKeydown($event, date, i)"
pRipple
[pBind]="ptm('day')"
>
<ng-container *ngIf="!dateTemplate && !_dateTemplate && (date.selectable || (!disabledDateTemplate && !_disabledDateTemplate))">{{ date.day }}</ng-container>
<ng-container *ngIf="date.selectable || (!disabledDateTemplate && !_disabledDateTemplate)">
<ng-container *ngTemplateOutlet="dateTemplate || _dateTemplate; context: { $implicit: date }"></ng-container>
</ng-container>
<ng-container *ngIf="!date.selectable">
<ng-container *ngTemplateOutlet="disabledDateTemplate || _disabledDateTemplate; context: { $implicit: date }"></ng-container>
</ng-container>
</span>
<div *ngIf="isSelected(date)" class="p-hidden-accessible" aria-live="polite">
{{ date.day }}
</div>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div [class]="cx('monthView')" *ngIf="currentView === 'month'" [pBind]="ptm('monthView')">
<span *ngFor="let m of monthPickerValues(); let i = index" (click)="onMonthSelect($event, i)" (keydown)="onMonthCellKeydown($event, i)" [class]="cx('month', { month: m, index: i })" pRipple [pBind]="ptm('month')">
{{ m }}
<div *ngIf="isMonthSelected(i)" class="p-hidden-accessible" aria-live="polite">
{{ m }}
</div>
</span>
</div>
<div [class]="cx('yearView')" *ngIf="currentView === 'year'" [pBind]="ptm('yearView')">
<span *ngFor="let y of yearPickerValues()" (click)="onYearSelect($event, y)" (keydown)="onYearCellKeydown($event, y)" [class]="cx('year', { year: y })" pRipple [pBind]="ptm('year')">
{{ y }}
<div *ngIf="isYearSelected(y)" class="p-hidden-accessible" aria-live="polite">
{{ y }}
</div>
</span>
</div>
</ng-container>
<div [class]="cx('timePicker')" *ngIf="(showTime || timeOnly) && currentView === 'date'" [pBind]="ptm('timePicker')">
<div [class]="cx('hourPicker')" [pBind]="ptm('hourPicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementHour($event)"
(keydown.space)="incrementHour($event)"
(mousedown)="onTimePickerElementMouseDown($event, 0, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextHour')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('hour')"><ng-container *ngIf="currentHour < 10">0</ng-container>{{ currentHour }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementHour($event)"
(keydown.space)="decrementHour($event)"
(mousedown)="onTimePickerElementMouseDown($event, 0, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevHour')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div class="p-datepicker-separator" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('minutePicker')" [pBind]="ptm('minutePicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementMinute($event)"
(keydown.space)="incrementMinute($event)"
(mousedown)="onTimePickerElementMouseDown($event, 1, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextMinute')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('minute')"><ng-container *ngIf="currentMinute < 10">0</ng-container>{{ currentMinute }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementMinute($event)"
(keydown.space)="decrementMinute($event)"
(mousedown)="onTimePickerElementMouseDown($event, 1, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevMinute')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div [class]="cx('separator')" *ngIf="showSeconds" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('secondPicker')" *ngIf="showSeconds" [pBind]="ptm('secondPicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementSecond($event)"
(keydown.space)="incrementSecond($event)"
(mousedown)="onTimePickerElementMouseDown($event, 2, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextSecond')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('second')"><ng-container *ngIf="currentSecond < 10">0</ng-container>{{ currentSecond }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementSecond($event)"
(keydown.space)="decrementSecond($event)"
(mousedown)="onTimePickerElementMouseDown($event, 2, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevSecond')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div [class]="cx('separator')" *ngIf="hourFormat == '12'" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('ampmPicker')" *ngIf="hourFormat == '12'" [pBind]="ptm('ampmPicker')">
<p-button
text
rounded
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="toggleAMPM($event)"
(keydown.enter)="toggleAMPM($event)"
[attr.aria-label]="getTranslation('am')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('ampm')">{{ pm ? 'PM' : 'AM' }}</span>
<p-button
text
rounded
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(click)="toggleAMPM($event)"
(keydown.enter)="toggleAMPM($event)"
[attr.aria-label]="getTranslation('pm')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
</div>
<div [class]="cx('buttonbar')" *ngIf="showButtonBar" [pBind]="ptm('buttonbar')">
@if (buttonBarTemplate || _buttonBarTemplate) {
<ng-container *ngTemplateOutlet="buttonBarTemplate || _buttonBarTemplate; context: { todayCallback: onTodayButtonClick.bind(this), clearCallback: onClearButtonClick.bind(this) }"></ng-container>
} @else {
<p-button
size="small"
[styleClass]="cx('pcTodayButton')"
[label]="getTranslation('today')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="onTodayButtonClick($event)"
[ngClass]="todayButtonStyleClass"
severity="secondary"
variant="text"
size="small"
[pt]="ptm('pcTodayButton')"
[attr.data-pc-group-section]="'button'"
/>
<p-button
size="small"
[styleClass]="cx('pcClearButton')"
[label]="getTranslation('clear')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="onClearButtonClick($event)"
[ngClass]="clearButtonStyleClass"
severity="secondary"
variant="text"
size="small"
[pt]="ptm('pcClearButton')"
[attr.data-pc-group-section]="'button'"
/>
}
</div>
<ng-content select="p-footer"></ng-content>
<ng-container *ngTemplateOutlet="footerTemplate || _footerTemplate"></ng-container>
</div>
</p-motion>
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: Ripple, selector: "[pRipple]" }, { kind: "component", type: ChevronLeftIcon, selector: "[data-p-icon=\"chevron-left\"]" }, { kind: "component", type: ChevronRightIcon, selector: "[data-p-icon=\"chevron-right\"]" }, { kind: "component", type: ChevronUpIcon, selector: "[data-p-icon=\"chevron-up\"]" }, { kind: "component", type: ChevronDownIcon, selector: "[data-p-icon=\"chevron-down\"]" }, { kind: "component", type: TimesIcon, selector: "[data-p-icon=\"times\"]" }, { kind: "component", type: CalendarIcon, selector: "[data-p-icon=\"calendar\"]" }, { kind: "directive", type: AutoFocus, selector: "[pAutoFocus]", inputs: ["pAutoFocus"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: BindModule }, { kind: "directive", type: i2.Bind, selector: "[pBind]", inputs: ["pBind"] }, { kind: "ngmodule", type: MotionModule }, { kind: "component", type: i4.Motion, selector: "p-motion", inputs: ["visible", "mountOnEnter", "unmountOnLeave", "name", "type", "safe", "disabled", "appear", "enter", "leave", "duration", "hideStrategy", "enterFromClass", "enterToClass", "enterActiveClass", "leaveFromClass", "leaveToClass", "leaveActiveClass", "options"], outputs: ["onBeforeEnter", "onEnter", "onAfterEnter", "onEnterCancelled", "onBeforeLeave", "onLeave", "onAfterLeave", "onLeaveCancelled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePicker, decorators: [{
type: Component,
args: [{
selector: 'p-datePicker, p-datepicker, p-date-picker',
standalone: true,
imports: [CommonModule, Button, Ripple, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronDownIcon, TimesIcon, CalendarIcon, AutoFocus, InputText, SharedModule, BindModule, MotionModule],
hostDirectives: [Bind],
template: `
<ng-template [ngIf]="!inline">
<input
#inputfield
pInputText
[pSize]="size()"
[attr.size]="inputSize()"
type="text"
role="combobox"
[attr.id]="inputId"
[attr.name]="name()"
[attr.aria-required]="required()"
aria-autocomplete="none"
aria-haspopup="dialog"
[attr.aria-expanded]="overlayVisible ?? false"
[attr.aria-controls]="overlayVisible ? panelId : null"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-label]="ariaLabel"
[value]="inputFieldValue"
(focus)="onInputFocus($event)"
(keydown)="onInputKeydown($event)"
(click)="onInputClick()"
(blur)="onInputBlur($event)"
[attr.required]="required() ? '' : undefined"
[attr.readonly]="readonlyInput ? '' : undefined"
[attr.disabled]="$disabled() ? '' : undefined"
(input)="onUserInput($event)"
[ngStyle]="inputStyle"
[class]="cn(cx('pcInputText'), inputStyleClass)"
[attr.placeholder]="placeholder"
[attr.tabindex]="tabindex"
[attr.inputmode]="touchUI ? 'off' : null"
autocomplete="off"
[pAutoFocus]="autofocus"
[variant]="$variant()"
[fluid]="hasFluid"
[invalid]="invalid()"
[pt]="ptm('pcInputText')"
[unstyled]="unstyled()"
/>
<ng-container *ngIf="showClear && !$disabled() && inputfieldViewChild?.nativeElement?.value">
<svg data-p-icon="times" *ngIf="!clearIconTemplate && !_clearIconTemplate" [class]="cx('clearIcon')" [pBind]="ptm('inputIcon')" (click)="clear()" />
<span *ngIf="clearIconTemplate || _clearIconTemplate" [class]="cx('clearIcon')" [pBind]="ptm('inputIcon')" (click)="clear()">
<ng-template *ngTemplateOutlet="clearIconTemplate || _clearIconTemplate"></ng-template>
</span>
</ng-container>
<button
type="button"
[attr.aria-label]="iconButtonAriaLabel"
aria-haspopup="dialog"
[attr.aria-expanded]="overlayVisible ?? false"
[attr.aria-controls]="overlayVisible ? panelId : null"
*ngIf="showIcon && iconDisplay === 'button'"
(click)="onButtonClick($event, inputfield)"
[class]="cx('dropdown')"
[disabled]="$disabled()"
tabindex="0"
[pBind]="ptm('dropdown')"
>
<span *ngIf="icon" [ngClass]="icon" [pBind]="ptm('dropdownIcon')"></span>
<ng-container *ngIf="!icon">
<svg data-p-icon="calendar" *ngIf="!triggerIconTemplate && !_triggerIconTemplate" [pBind]="ptm('dropdownIcon')" />
<ng-template *ngTemplateOutlet="triggerIconTemplate || _triggerIconTemplate"></ng-template>
</ng-container>
</button>
<ng-container *ngIf="iconDisplay === 'input' && showIcon">
<span [class]="cx('inputIconContainer')" [pBind]="ptm('inputIconContainer')" [attr.data-p]="inputIconDataP">
<svg data-p-icon="calendar" (click)="onButtonClick($event)" *ngIf="!inputIconTemplate && !_inputIconTemplate" [class]="cx('inputIcon')" [pBind]="ptm('inputIcon')" />
<ng-container *ngTemplateOutlet="inputIconTemplate || _inputIconTemplate; context: { clickCallBack: onButtonClick.bind(this) }"></ng-container>
</span>
</ng-container>
</ng-template>
<p-motion [visible]="inline || overlayVisible" name="p-anchored-overlay" [appear]="!inline" [options]="computedMotionOptions()" (onBeforeEnter)="onOverlayBeforeEnter($event)" (onAfterLeave)="onOverlayAfterLeave($event)">
<div
#contentWrapper
[attr.id]="panelId"
[ngStyle]="panelStyle"
[class]="cn(cx('panel'), panelStyleClass)"
[attr.aria-label]="getTranslation('chooseDate')"
[attr.role]="inline ? null : 'dialog'"
[attr.aria-modal]="inline ? null : 'true'"
(click)="onOverlayClick($event)"
[pBind]="ptm('panel')"
>
<ng-content select="p-header"></ng-content>
<ng-container *ngTemplateOutlet="headerTemplate || _headerTemplate"></ng-container>
<ng-container *ngIf="!timeOnly">
<div [class]="cx('calendarContainer')" [pBind]="ptm('calendarContainer')">
<div [class]="cx('calendar')" *ngFor="let month of months; let i = index" [pBind]="ptm('calendar')">
<div [class]="cx('header')" [pBind]="ptm('header')">
<p-button
rounded
variant="text"
severity="secondary"
(keydown)="onContainerButtonKeydown($event)"
[styleClass]="cx('pcPrevButton')"
(onClick)="onPrevButtonClick($event)"
[ngStyle]="{ visibility: i === 0 ? 'visible' : 'hidden' }"
type="button"
[ariaLabel]="prevIconAriaLabel"
[pt]="ptm('pcPrevButton')"
[attr.data-pc-group-section]="'navigator'"
>
<ng-template #icon>
<svg data-p-icon="chevron-left" *ngIf="!previousIconTemplate && !_previousIconTemplate" />
<span *ngIf="previousIconTemplate || _previousIconTemplate">
<ng-template *ngTemplateOutlet="previousIconTemplate || _previousIconTemplate"></ng-template>
</span>
</ng-template>
</p-button>
<div [class]="cx('title')" [pBind]="ptm('title')">
<button
*ngIf="currentView === 'date'"
type="button"
(click)="switchToMonthView($event)"
(keydown)="onContainerButtonKeydown($event)"
[class]="cx('selectMonth')"
[attr.disabled]="switchViewButtonDisabled() ? '' : undefined"
[attr.aria-label]="this.getTranslation('chooseMonth')"
pRipple
[pBind]="ptm('selectMonth')"
[attr.data-pc-group-section]="'navigator'"
>
{{ getMonthName(month.month) }}
</button>
<button
*ngIf="currentView !== 'year'"
type="button"
(click)="switchToYearView($event)"
(keydown)="onContainerButtonKeydown($event)"
[class]="cx('selectYear')"
[attr.disabled]="switchViewButtonDisabled() ? '' : undefined"
[attr.aria-label]="getTranslation('chooseYear')"
pRipple
[pBind]="ptm('selectYear')"
[attr.data-pc-group-section]="'navigator'"
>
{{ getYear(month) }}
</button>
<span [class]="cx('decade')" *ngIf="currentView === 'year'" [pBind]="ptm('decade')">
<ng-container *ngIf="!decadeTemplate && !_decadeTemplate">{{ yearPickerValues()[0] }} - {{ yearPickerValues()[yearPickerValues().length - 1] }}</ng-container>
<ng-container *ngTemplateOutlet="decadeTemplate || _decadeTemplate; context: { $implicit: yearPickerValues }"></ng-container>
</span>
</div>
<p-button
rounded
variant="text"
severity="secondary"
(keydown)="onContainerButtonKeydown($event)"
[styleClass]="cx('pcNextButton')"
(onClick)="onNextButtonClick($event)"
[ngStyle]="{ visibility: i === months.length - 1 ? 'visible' : 'hidden' }"
[ariaLabel]="nextIconAriaLabel"
[pt]="ptm('pcNextButton')"
[attr.data-pc-group-section]="'navigator'"
>
<ng-template #icon>
<svg data-p-icon="chevron-right" *ngIf="!nextIconTemplate && !_nextIconTemplate" />
<ng-container *ngIf="nextIconTemplate || _nextIconTemplate">
<ng-template *ngTemplateOutlet="nextIconTemplate || _nextIconTemplate"></ng-template>
</ng-container>
</ng-template>
</p-button>
</div>
<table [class]="cx('dayView')" role="grid" *ngIf="currentView === 'date'" [pBind]="ptm('table')">
<thead [pBind]="ptm('tableHeader')">
<tr [pBind]="ptm('tableHeaderRow')">
<th *ngIf="showWeek" [class]="cx('weekHeader')" [pBind]="ptm('weekHeader')">
<span [pBind]="ptm('weekHeaderLabel')">{{ getTranslation('weekHeader') }}</span>
</th>
<th [class]="cx('weekDayCell')" scope="col" *ngFor="let weekDay of weekDays; let begin = first; let end = last" [pBind]="ptm('weekDayCell')">
<span [class]="cx('weekDay')" [pBind]="ptm('weekDay')">{{ weekDay }}</span>
</th>
</tr>
</thead>
<tbody [pBind]="ptm('tableBody')">
<tr *ngFor="let week of month.dates; let j = index" [pBind]="ptm('tableBodyRow')">
<td *ngIf="showWeek" [class]="cx('weekNumber')" [pBind]="ptm('weekNumber')">
<span [class]="cx('weekLabelContainer')" [pBind]="ptm('weekLabelContainer')">
{{ month.weekNumbers[j] }}
</span>
</td>
<td *ngFor="let date of week" [attr.aria-label]="date.day" [class]="cx('dayCell', { date })" [pBind]="ptm('dayCell')">
<ng-container *ngIf="date.otherMonth ? showOtherMonths : true">
<span
[ngClass]="dayClass(date)"
(click)="onDateSelect($event, date)"
draggable="false"
[attr.data-date]="formatDateKey(formatDateMetaToDate(date))"
(keydown)="onDateCellKeydown($event, date, i)"
pRipple
[pBind]="ptm('day')"
>
<ng-container *ngIf="!dateTemplate && !_dateTemplate && (date.selectable || (!disabledDateTemplate && !_disabledDateTemplate))">{{ date.day }}</ng-container>
<ng-container *ngIf="date.selectable || (!disabledDateTemplate && !_disabledDateTemplate)">
<ng-container *ngTemplateOutlet="dateTemplate || _dateTemplate; context: { $implicit: date }"></ng-container>
</ng-container>
<ng-container *ngIf="!date.selectable">
<ng-container *ngTemplateOutlet="disabledDateTemplate || _disabledDateTemplate; context: { $implicit: date }"></ng-container>
</ng-container>
</span>
<div *ngIf="isSelected(date)" class="p-hidden-accessible" aria-live="polite">
{{ date.day }}
</div>
</ng-container>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div [class]="cx('monthView')" *ngIf="currentView === 'month'" [pBind]="ptm('monthView')">
<span *ngFor="let m of monthPickerValues(); let i = index" (click)="onMonthSelect($event, i)" (keydown)="onMonthCellKeydown($event, i)" [class]="cx('month', { month: m, index: i })" pRipple [pBind]="ptm('month')">
{{ m }}
<div *ngIf="isMonthSelected(i)" class="p-hidden-accessible" aria-live="polite">
{{ m }}
</div>
</span>
</div>
<div [class]="cx('yearView')" *ngIf="currentView === 'year'" [pBind]="ptm('yearView')">
<span *ngFor="let y of yearPickerValues()" (click)="onYearSelect($event, y)" (keydown)="onYearCellKeydown($event, y)" [class]="cx('year', { year: y })" pRipple [pBind]="ptm('year')">
{{ y }}
<div *ngIf="isYearSelected(y)" class="p-hidden-accessible" aria-live="polite">
{{ y }}
</div>
</span>
</div>
</ng-container>
<div [class]="cx('timePicker')" *ngIf="(showTime || timeOnly) && currentView === 'date'" [pBind]="ptm('timePicker')">
<div [class]="cx('hourPicker')" [pBind]="ptm('hourPicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementHour($event)"
(keydown.space)="incrementHour($event)"
(mousedown)="onTimePickerElementMouseDown($event, 0, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextHour')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('hour')"><ng-container *ngIf="currentHour < 10">0</ng-container>{{ currentHour }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementHour($event)"
(keydown.space)="decrementHour($event)"
(mousedown)="onTimePickerElementMouseDown($event, 0, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevHour')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div class="p-datepicker-separator" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('minutePicker')" [pBind]="ptm('minutePicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementMinute($event)"
(keydown.space)="incrementMinute($event)"
(mousedown)="onTimePickerElementMouseDown($event, 1, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextMinute')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('minute')"><ng-container *ngIf="currentMinute < 10">0</ng-container>{{ currentMinute }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementMinute($event)"
(keydown.space)="decrementMinute($event)"
(mousedown)="onTimePickerElementMouseDown($event, 1, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevMinute')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div [class]="cx('separator')" *ngIf="showSeconds" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('secondPicker')" *ngIf="showSeconds" [pBind]="ptm('secondPicker')">
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="incrementSecond($event)"
(keydown.space)="incrementSecond($event)"
(mousedown)="onTimePickerElementMouseDown($event, 2, 1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('nextSecond')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('second')"><ng-container *ngIf="currentSecond < 10">0</ng-container>{{ currentSecond }}</span>
<p-button
rounded
variant="text"
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(keydown.enter)="decrementSecond($event)"
(keydown.space)="decrementSecond($event)"
(mousedown)="onTimePickerElementMouseDown($event, 2, -1)"
(mouseup)="onTimePickerElementMouseUp($event)"
(keyup.enter)="onTimePickerElementMouseUp($event)"
(keyup.space)="onTimePickerElementMouseUp($event)"
(mouseleave)="onTimePickerElementMouseLeave()"
[attr.aria-label]="getTranslation('prevSecond')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
<div [class]="cx('separator')" *ngIf="hourFormat == '12'" [pBind]="ptm('separatorContainer')">
<span [pBind]="ptm('separator')">{{ timeSeparator }}</span>
</div>
<div [class]="cx('ampmPicker')" *ngIf="hourFormat == '12'" [pBind]="ptm('ampmPicker')">
<p-button
text
rounded
severity="secondary"
[styleClass]="cx('pcIncrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="toggleAMPM($event)"
(keydown.enter)="toggleAMPM($event)"
[attr.aria-label]="getTranslation('am')"
[pt]="ptm('pcIncrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-up" *ngIf="!incrementIconTemplate && !_incrementIconTemplate" [pBind]="ptm('pcIncrementButton')['icon']" />
<ng-template *ngTemplateOutlet="incrementIconTemplate || _incrementIconTemplate"></ng-template>
</ng-template>
</p-button>
<span [pBind]="ptm('ampm')">{{ pm ? 'PM' : 'AM' }}</span>
<p-button
text
rounded
severity="secondary"
[styleClass]="cx('pcDecrementButton')"
(keydown)="onContainerButtonKeydown($event)"
(click)="toggleAMPM($event)"
(keydown.enter)="toggleAMPM($event)"
[attr.aria-label]="getTranslation('pm')"
[pt]="ptm('pcDecrementButton')"
[attr.data-pc-group-section]="'timepickerbutton'"
>
<ng-template #icon>
<svg data-p-icon="chevron-down" *ngIf="!decrementIconTemplate && !_decrementIconTemplate" [pBind]="ptm('pcDecrementButton')['icon']" />
<ng-template *ngTemplateOutlet="decrementIconTemplate || _decrementIconTemplate"></ng-template>
</ng-template>
</p-button>
</div>
</div>
<div [class]="cx('buttonbar')" *ngIf="showButtonBar" [pBind]="ptm('buttonbar')">
@if (buttonBarTemplate || _buttonBarTemplate) {
<ng-container *ngTemplateOutlet="buttonBarTemplate || _buttonBarTemplate; context: { todayCallback: onTodayButtonClick.bind(this), clearCallback: onClearButtonClick.bind(this) }"></ng-container>
} @else {
<p-button
size="small"
[styleClass]="cx('pcTodayButton')"
[label]="getTranslation('today')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="onTodayButtonClick($event)"
[ngClass]="todayButtonStyleClass"
severity="secondary"
variant="text"
size="small"
[pt]="ptm('pcTodayButton')"
[attr.data-pc-group-section]="'button'"
/>
<p-button
size="small"
[styleClass]="cx('pcClearButton')"
[label]="getTranslation('clear')"
(keydown)="onContainerButtonKeydown($event)"
(onClick)="onClearButtonClick($event)"
[ngClass]="clearButtonStyleClass"
severity="secondary"
variant="text"
size="small"
[pt]="ptm('pcClearButton')"
[attr.data-pc-group-section]="'button'"
/>
}
</div>
<ng-content select="p-footer"></ng-content>
<ng-container *ngTemplateOutlet="footerTemplate || _footerTemplate"></ng-container>
</div>
</p-motion>
`,
providers: [DATEPICKER_VALUE_ACCESSOR, DatePickerStyle, { provide: DATEPICKER_INSTANCE, useExisting: DatePicker }, { provide: PARENT_INSTANCE, useExisting: DatePicker }],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: {
'[class]': "cn(cx('root'), styleClass)",
'[style]': "sx('root')"
}
}]
}], ctorParameters: () => [{ type: i0.NgZone }, { type: i1.OverlayService }], propDecorators: { iconDisplay: [{
type: Input
}], styleClass: [{
type: Input
}], inputStyle: [{
type: Input
}], inputId: [{
type: Input
}], inputStyleClass: [{
type: Input
}], placeholder: [{
type: Input
}], ariaLabelledBy: [{
type: Input
}], ariaLabel: [{
type: Input
}], iconAriaLabel: [{
type: Input
}], dateFormat: [{
type: Input
}], multipleSeparator: [{
type: Input
}], rangeSeparator: [{
type: Input
}], inline: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showOtherMonths: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], selectOtherMonths: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showIcon: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], icon: [{
type: Input
}], readonlyInput: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], shortYearCutoff: [{
type: Input
}], hourFormat: [{
type: Input
}], timeOnly: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], stepHour: [{
type: Input,
args: [{ transform: numberAttribute }]
}], stepMinute: [{
type: Input,
args: [{ transform: numberAttribute }]
}], stepSecond: [{
type: Input,
args: [{ transform: numberAttribute }]
}], showSeconds: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showOnFocus: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showWeek: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], startWeekFromFirstDayOfYear: [{
type: Input
}], showClear: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], dataType: [{
type: Input
}], selectionMode: [{
type: Input
}], maxDateCount: [{
type: Input,
args: [{ transform: numberAttribute }]
}], showButtonBar: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], todayButtonStyleClass: [{
type: Input
}], clearButtonStyleClass: [{
type: Input
}], autofocus: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], autoZIndex: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], baseZIndex: [{
type: Input,
args: [{ transform: numberAttribute }]
}], panelStyleClass: [{
type: Input
}], panelStyle: [{
type: Input
}], keepInvalid: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], hideOnDateTimeSelect: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], touchUI: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], timeSeparator: [{
type: Input
}], focusTrap: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], showTransitionOptions: [{
type: Input
}], hideTransitionOptions: [{
type: Input
}], tabindex: [{
type: Input,
args: [{ transform: numberAttribute }]
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], disabledDates: [{
type: Input
}], disabledDays: [{
type: Input
}], showTime: [{
type: Input
}], responsiveOptions: [{
type: Input
}], numberOfMonths: [{
type: Input
}], firstDayOfWeek: [{
type: Input
}], view: [{
type: Input
}], defaultDate: [{
type: Input
}], isBudhistYear: [{
type: Input
}], inputBudhistYear: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], outputBudhistYear: [{
type: Input,
args: [{ transform: booleanAttribute }]
}], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], motionOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "motionOptions", required: false }] }], onFocus: [{
type: Output
}], onBlur: [{
type: Output
}], onClose: [{
type: Output
}], onSelect: [{
type: Output
}], onClear: [{
type: Output
}], onInput: [{
type: Output
}], onTodayClick: [{
type: Output
}], onClearClick: [{
type: Output
}], onMonthChange: [{
type: Output
}], onYearChange: [{
type: Output
}], onClickOutside: [{
type: Output
}], onShow: [{
type: Output
}], inputfieldViewChild: [{
type: ViewChild,
args: ['inputfield', { static: false }]
}], content: [{
type: ViewChild,
args: ['contentWrapper', { static: false }]
}], dateTemplate: [{
type: ContentChild,
args: ['date', { descendants: false }]
}], headerTemplate: [{
type: ContentChild,
args: ['header', { descendants: false }]
}], footerTemplate: [{
type: ContentChild,
args: ['footer', { descendants: false }]
}], disabledDateTemplate: [{
type: ContentChild,
args: ['disabledDate', { descendants: false }]
}], decadeTemplate: [{
type: ContentChild,
args: ['decade', { descendants: false }]
}], previousIconTemplate: [{
type: ContentChild,
args: ['previousicon', { descendants: false }]
}], nextIconTemplate: [{
type: ContentChild,
args: ['nexticon', { descendants: false }]
}], triggerIconTemplate: [{
type: ContentChild,
args: ['triggericon', { descendants: false }]
}], clearIconTemplate: [{
type: ContentChild,
args: ['clearicon', { descendants: false }]
}], decrementIconTemplate: [{
type: ContentChild,
args: ['decrementicon', { descendants: false }]
}], incrementIconTemplate: [{
type: ContentChild,
args: ['incrementicon', { descendants: false }]
}], inputIconTemplate: [{
type: ContentChild,
args: ['inputicon', { descendants: false }]
}], buttonBarTemplate: [{
type: ContentChild,
args: ['buttonbar', { descendants: false }]
}], templates: [{
type: ContentChildren,
args: [PrimeTemplate]
}] } });
class DatePickerModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: DatePickerModule, imports: [DatePicker, SharedModule], exports: [DatePicker, SharedModule] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePickerModule, imports: [DatePicker, SharedModule, SharedModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DatePickerModule, decorators: [{
type: NgModule,
args: [{
imports: [DatePicker, SharedModule],
exports: [DatePicker, SharedModule]
}]
}] });
/*
* Public API Surface of primeng-buddhist-datepicker
*/
/**
* Generated bundle index. Do not edit.
*/
export { DATEPICKER_VALUE_ACCESSOR, DatePicker, DatePickerClasses, DatePickerModule, DatePickerStyle };
//# sourceMappingURL=primeng-buddhist-year-datepicker.mjs.map