primeng
Version:
PrimeNG is an open source UI library for Angular featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeB
1,561 lines (1,500 loc) • 198 kB
JavaScript
import { trigger, state, transition, style, animate } from '@angular/animations';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, forwardRef, EventEmitter, inject, numberAttribute, booleanAttribute, ContentChildren, ViewChild, ContentChild, 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, blockBodyScroll, unblockBodyScroll, setAttribute, isTouchDevice } from '@primeuix/utils';
import * as i1 from 'primeng/api';
import { TranslationKeys, SharedModule, PrimeTemplate } from 'primeng/api';
import { AutoFocus } from 'primeng/autofocus';
import { BaseComponent } from 'primeng/basecomponent';
import { Button } from 'primeng/button';
import { ConnectedOverlayScrollHandler } from 'primeng/dom';
import { ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronDownIcon, TimesIcon, CalendarIcon } from 'primeng/icons';
import { InputText } from 'primeng/inputtext';
import { Ripple } from 'primeng/ripple';
import { ZIndexUtils } from 'primeng/utils';
import { BaseStyle } from 'primeng/base';
const theme = ({ dt }) => `
.p-datepicker {
position: relative;
display: inline-flex;
max-width: 100%;
}
.p-datepicker-input {
flex: 1 1 auto;
width: 1%;
}
.p-datepicker:has(.p-datepicker-dropdown) .p-datepicker-input {
border-start-end-radius: 0;
border-end-end-radius: 0;
}
.p-datepicker-dropdown {
cursor: pointer;
display: inline-flex;
cursor: pointer;
user-select: none;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
width: ${dt('datepicker.dropdown.width')};
border-start-end-radius: ${dt('datepicker.dropdown.border.radius')};
border-end-end-radius: ${dt('datepicker.dropdown.border.radius')};
background: ${dt('datepicker.dropdown.background')};
border: 1px solid ${dt('datepicker.dropdown.border.color')};
border-left: 0 none;
color: ${dt('datepicker.dropdown.color')};
transition: background ${dt('datepicker.transition.duration')}, color ${dt('datepicker.transition.duration')}, border-color ${dt('datepicker.transition.duration')}, outline-color ${dt('datepicker.transition.duration')};
outline-color: transparent;
}
.p-datepicker-dropdown:not(:disabled):hover {
background: ${dt('datepicker.dropdown.hover.background')};
border-color: ${dt('datepicker.dropdown.hover.border.color')};
color: ${dt('datepicker.dropdown.hover.color')};
}
.p-datepicker-dropdown:not(:disabled):active {
background: ${dt('datepicker.dropdown.active.background')};
border-color: ${dt('datepicker.dropdown.active.border.color')};
color: ${dt('datepicker.dropdown.active.color')};
}
.p-datepicker-dropdown:focus-visible {
box-shadow: ${dt('datepicker.dropdown.focus.ring.shadow')};
outline: ${dt('datepicker.dropdown.focus.ring.width')} ${dt('datepicker.dropdown.focus.ring.style')} ${dt('datepicker.dropdown.focus.ring.color')};
outline-offset: ${dt('datepicker.dropdown.focus.ring.offset')};
}
.p-datepicker:has(.p-datepicker-input-icon-container) {
position: relative;
}
.p-datepicker:has(.p-datepicker-input-icon-container) .p-datepicker-input {
padding-right: calc((${dt('form.field.padding.x')} * 2) + ${dt('icon.size')});
}
.p-datepicker-input-icon-container {
cursor: pointer;
position: absolute;
top: 50%;
right: ${dt('form.field.padding.x')};
margin-top: calc(-1 * (${dt('icon.size')} / 2));
color: ${dt('datepicker.input.icon.color')};
}
.p-datepicker-fluid {
display: flex;
}
.p-datepicker-fluid .p-datepicker-input {
width: 1%;
}
.p-datepicker .p-datepicker-panel {
min-width: 100%;
}
.p-datepicker-panel {
position: absolute;
width: auto;
padding: ${dt('datepicker.panel.padding')};
background: ${dt('datepicker.panel.background')};
color: ${dt('datepicker.panel.color')};
border: 1px solid ${dt('datepicker.panel.border.color')};
border-radius: ${dt('datepicker.panel.border.radius')};
box-shadow: ${dt('datepicker.panel.shadow')};
}
.p-datepicker-panel-inline {
display: inline-block;
overflow-x: auto;
box-shadow: none;
}
.p-datepicker-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: ${dt('datepicker.header.padding')};
font-weight: ${dt('datepicker.header.font.weight')};
background: ${dt('datepicker.header.background')};
color: ${dt('datepicker.header.color')};
border-bottom: 1px solid ${dt('datepicker.header.border.color')};
}
.p-datepicker-title {
display: flex;
align-items: center;
justify-content: space-between;
gap: ${dt('datepicker.title.gap')};
font-weight: ${dt('datepicker.title.font.weight')};
}
.p-datepicker-select-year,
.p-datepicker-select-month {
border: none;
background: transparent;
margin: 0;
cursor: pointer;
font-weight: inherit;
transition: background ${dt('datepicker.transition.duration')}, color ${dt('datepicker.transition.duration')}, border-color ${dt('datepicker.transition.duration')}, outline-color ${dt('datepicker.transition.duration')}, box-shadow ${dt('datepicker.transition.duration')};
}
.p-datepicker-select-month {
padding: ${dt('datepicker.select.month.padding')};
color: ${dt('datepicker.select.month.color')};
border-radius: ${dt('datepicker.select.month.border.radius')};
}
.p-datepicker-select-year {
padding: ${dt('datepicker.select.year.padding')};
color: ${dt('datepicker.select.year.color')};
border-radius: ${dt('datepicker.select.year.border.radius')};
}
.p-datepicker-select-month:enabled:hover {
background: ${dt('datepicker.select.month.hover.background')};
color: ${dt('datepicker.select.month.hover.color')};
}
.p-datepicker-select-year:enabled:hover {
background: ${dt('datepicker.select.year.hover.background')};
color: ${dt('datepicker.select.year.hover.color')};
}
.p-datepicker-calendar-container {
display: flex;
}
.p-datepicker-calendar-container .p-datepicker-calendar {
flex: 1 1 auto;
border-left: 1px solid ${dt('datepicker.group.border.color')};
padding-right: ${dt('datepicker.group.gap')};
padding-left: ${dt('datepicker.group.gap')};
}
.p-datepicker-calendar-container .p-datepicker-calendar:first-child {
padding-left: 0;
border-left: 0 none;
}
.p-datepicker-calendar-container .p-datepicker-calendar:last-child {
padding-right: 0;
}
.p-datepicker-day-view {
width: 100%;
border-collapse: collapse;
font-size: 1rem;
margin: ${dt('datepicker.day.view.margin')};
}
.p-datepicker-weekday-cell {
padding: ${dt('datepicker.week.day.padding')};
}
.p-datepicker-weekday {
font-weight: ${dt('datepicker.week.day.font.weight')};
color: ${dt('datepicker.week.day.color')};
}
.p-datepicker-day-cell {
padding: ${dt('datepicker.date.padding')};
}
.p-datepicker-day {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
margin: 0 auto;
overflow: hidden;
position: relative;
width: ${dt('datepicker.date.width')};
height: ${dt('datepicker.date.height')};
border-radius: ${dt('datepicker.date.border.radius')};
transition: background ${dt('datepicker.transition.duration')}, color ${dt('datepicker.transition.duration')}, border-color ${dt('datepicker.transition.duration')},
box-shadow ${dt('datepicker.transition.duration')}, outline-color ${dt('datepicker.transition.duration')};
border: 1px solid transparent;
outline-color: transparent;
color: ${dt('datepicker.date.color')};
}
.p-datepicker-day:not(.p-datepicker-day-selected):not(.p-disabled):hover {
background: ${dt('datepicker.date.hover.background')};
color: ${dt('datepicker.date.hover.color')};
}
.p-datepicker-day:focus-visible {
box-shadow: ${dt('datepicker.date.focus.ring.shadow')};
outline: ${dt('datepicker.date.focus.ring.width')} ${dt('datepicker.date.focus.ring.style')} ${dt('datepicker.date.focus.ring.color')};
outline-offset: ${dt('datepicker.date.focus.ring.offset')};
}
.p-datepicker-day-selected {
background: ${dt('datepicker.date.selected.background')};
color: ${dt('datepicker.date.selected.color')};
}
.p-datepicker-day-selected-range {
background: ${dt('datepicker.date.range.selected.background')};
color: ${dt('datepicker.date.range.selected.color')};
}
.p-datepicker-today > .p-datepicker-day {
background: ${dt('datepicker.today.background')};
color: ${dt('datepicker.today.color')};
}
.p-datepicker-today > .p-datepicker-day-selected {
background: ${dt('datepicker.date.selected.background')};
color: ${dt('datepicker.date.selected.color')};
}
.p-datepicker-today > .p-datepicker-day-selected-range {
background: ${dt('datepicker.date.range.selected.background')};
color: ${dt('datepicker.date.range.selected.color')};
}
.p-datepicker-weeknumber {
text-align: center
}
.p-datepicker-month-view {
margin: ${dt('datepicker.month.view.margin')};
}
.p-datepicker-month {
width: 33.3%;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
position: relative;
padding: ${dt('datepicker.month.padding')};
transition: background ${dt('datepicker.transition.duration')}, color ${dt('datepicker.transition.duration')}, border-color ${dt('datepicker.transition.duration')}, box-shadow ${dt('datepicker.transition.duration')}, outline-color ${dt('datepicker.transition.duration')};
border-radius: ${dt('datepicker.month.border.radius')};
outline-color: transparent;
color: ${dt('datepicker.date.color')};
}
.p-datepicker-month:not(.p-disabled):not(.p-datepicker-month-selected):hover {
color: ${dt('datepicker.date.hover.color')};
background: ${dt('datepicker.date.hover.background')};
}
.p-datepicker-month-selected {
color: ${dt('datepicker.date.selected.color')};
background: ${dt('datepicker.date.selected.background')};
}
.p-datepicker-month:not(.p-disabled):focus-visible {
box-shadow: ${dt('datepicker.date.focus.ring.shadow')};
outline: ${dt('datepicker.date.focus.ring.width')} ${dt('datepicker.date.focus.ring.style')} ${dt('datepicker.date.focus.ring.color')};
outline-offset: ${dt('datepicker.date.focus.ring.offset')};
}
.p-datepicker-year-view {
margin: ${dt('datepicker.year.view.margin')};
}
.p-datepicker-year {
width: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
position: relative;
padding: ${dt('datepicker.year.padding')};
transition: background ${dt('datepicker.transition.duration')}, color ${dt('datepicker.transition.duration')}, border-color ${dt('datepicker.transition.duration')}, box-shadow ${dt('datepicker.transition.duration')}, outline-color ${dt('datepicker.transition.duration')};
border-radius: ${dt('datepicker.year.border.radius')};
outline-color: transparent;
color: ${dt('datepicker.date.color')};
}
.p-datepicker-year:not(.p-disabled):not(.p-datepicker-year-selected):hover {
color: ${dt('datepicker.date.hover.color')};
background: ${dt('datepicker.date.hover.background')};
}
.p-datepicker-year-selected {
color: ${dt('datepicker.date.selected.color')};
background: ${dt('datepicker.date.selected.background')};
}
.p-datepicker-year:not(.p-disabled):focus-visible {
box-shadow: ${dt('datepicker.date.focus.ring.shadow')};
outline: ${dt('datepicker.date.focus.ring.width')} ${dt('datepicker.date.focus.ring.style')} ${dt('datepicker.date.focus.ring.color')};
outline-offset: ${dt('datepicker.date.focus.ring.offset')};
}
.p-datepicker-buttonbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: ${dt('datepicker.buttonbar.padding')};
border-top: 1px solid ${dt('datepicker.buttonbar.border.color')};
}
.p-datepicker-buttonbar .p-button {
width: auto;
}
.p-datepicker-time-picker {
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid ${dt('datepicker.time.picker.border.color')};
padding: 0;
gap: ${dt('datepicker.time.picker.gap')};
}
.p-datepicker-calendar-container + .p-datepicker-time-picker {
padding: ${dt('datepicker.time.picker.padding')};
}
.p-datepicker-time-picker > div {
display: flex;
align-items: center;
flex-direction: column;
gap: ${dt('datepicker.time.picker.button.gap')};
}
.p-datepicker-time-picker span {
font-size: 1rem;
}
.p-datepicker-timeonly .p-datepicker-time-picker {
border-top: 0 none;
}
.p-datepicker-calendar:not(:first-child):not(:last-child) .p-datepicker-header {
justify-content: center;
}
/* For PrimeNG */
p-calendar.ng-invalid.ng-dirty .p-datepicker.p-inputwrapper .p-inputtext{
border-color: ${dt('inputtext.invalid.border.color')};
}
p-datePicker.ng-invalid.ng-dirty .p-datepicker.p-inputwrapper .p-inputtext,
p-date-picker.ng-invalid.ng-dirty .p-datepicker.p-inputwrapper .p-inputtext,
p-datepicker.ng-invalid.ng-dirty .p-datepicker.p-inputwrapper .p-inputtext {
border-color: ${dt('inputtext.invalid.border.color')};
}
`;
const inlineStyles = {
root: ({ props }) => ({ position: props.appendTo === 'self' ? 'relative' : undefined })
};
const classes = {
root: ({ instance }) => ({
'p-datepicker p-component p-inputwrapper': true,
'p-datepicker-fluid': instance.hasFluid,
'p-inputwrapper-filled': instance.filled,
'p-inputwrapper-focus': instance.focus,
'p-focus': instance.focus || instance.overlayVisible
}),
pcInput: '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': 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) {
selectedDayClass = date.day === instance.value[0].getDate() || date.day === instance.value[1].getDate() ? '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, props, month, index }) => [
'p-datepicker-month',
{
'p-datepicker-month-selected': instance.isMonthSelected(index),
'p-disabled': props.disabled || !month.selectable
}
],
yearView: 'p-datepicker-year-view',
year: ({ instance, props, year }) => [
'p-datepicker-year',
{
'p-datepicker-year-selected': instance.isYearSelected(year.value),
'p-disabled': props.disabled || !year.selectable
}
],
timePicker: 'p-datepicker-time-picker',
hourPicker: 'p-datepicker-hour-picker',
pcIncrementButton: 'p-datepicker-increment-button',
pcDecrementButton: 'p-datepicker-decrement-button',
separator: 'p-datepicker-separator',
minutePicker: 'p-datepicker-minute-picker',
secondPicker: 'p-datepicker-second-picker',
ampmPicker: 'p-datepicker-ampm-picker',
buttonbar: 'p-datepicker-buttonbar',
pcTodayButton: 'p-datepicker-today-button',
pcClearButton: 'p-datepicker-clear-button'
};
class CalendarStyle extends BaseStyle {
name = 'datepicker';
theme = theme;
classes = classes;
inlineStyles = inlineStyles;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CalendarStyle, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CalendarStyle });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CalendarStyle, decorators: [{
type: Injectable
}] });
const CALENDAR_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Calendar),
multi: true
};
/**
* Calendar also known as DatePicker, is a form component to work with dates.
* @group Components
*/
class Calendar extends BaseComponent {
zone;
overlayService;
iconDisplay = 'button';
/**
* Inline style of the component.
* @group Props
*/
style;
/**
* Style class of the component.
* @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;
/**
* Name of the input element.
* @group Props
*/
name;
/**
* 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;
/**
* When specified, disables the component.
* @group Props
*/
disabled;
/**
* Format of the date which can also be defined at locale settings.
* @group Props
*/
dateFormat;
/**
* 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 calendar 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;
/**
* Whether the component should span the full width of its parent.
* @group Props
*/
fluid;
/**
* Icon of the calendar button.
* @group Props
*/
icon;
/**
* 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).
* @group Props
*/
appendTo;
/**
* 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';
/**
* Whether the month should be rendered as a dropdown instead of text.
* @group Props
* @deprecated Navigator is always on.
*/
monthNavigator;
/**
* Whether the year should be rendered as a dropdown instead of text.
* @group Props
* @deprecated Navigator is always on.
*/
yearNavigator;
/**
* Specifies 12 or 24 hour format.
* @group Props
*/
hourFormat = '24';
/**
* 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 present, it specifies that an input field must be filled out before submitting the form.
* @group Props
*/
required;
/**
* When disabled, datepicker will not be visible with input focus.
* @group Props
*/
showOnFocus = true;
/**
* When enabled, calendar will show week numbers.
* @group Props
*/
showWeek = false;
/**
* When enabled, calendar 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, calendar 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 calendar.
* @group Props
*/
focusTrap = true;
/**
* Transition options of the show animation.
* @group Props
*/
showTransitionOptions = '.12s cubic-bezier(0, 0, 0.2, 1)';
/**
* Transition options of the hide animation.
* @group Props
*/
hideTransitionOptions = '.1s linear';
/**
* Index of the element in tabbing order.
* @group Props
*/
tabindex;
/**
* Specifies the input variant of the component.
* @group Props
*/
variant;
/**
* 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);
}
}
/**
* The range of years displayed in the year drop-down in (nnnn:nnnn) format such as (2000:2020).
* @group Props
* @deprecated Years are based on decades by default.
*/
get yearRange() {
return this._yearRange;
}
set yearRange(yearRange) {
this._yearRange = yearRange;
if (yearRange) {
const years = yearRange.split(':');
const yearStart = parseInt(years[0]);
const yearEnd = parseInt(years[1]);
this.populateYearOptions(yearStart, yearEnd);
}
}
/**
* 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();
}
/**
* Option to set calendar locale.
* @group Props
* @deprecated Locale property has no effect, use new i18n API instead.
*/
set locale(newLocale) {
console.log('Locale property has no effect, use new i18n API instead.');
}
/**
* 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);
}
}
/**
* 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 {Event} event - Mouse event
* @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 {CalendarMonthChangeEvent} event - custom month change event.
* @group Emits
*/
onMonthChange = new EventEmitter();
/**
* Callback to invoke when a year is changed using the navigators.
* @param {CalendarYearChangeEvent} 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.
* @group Emits
*/
onShow = new EventEmitter();
/**
* Custom template for date cells.
* @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.
* @group Templates
*/
disabledDateTemplate;
/**
* Custom template for decade view.
* @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.
* @group Templates
*/
inputIconTemplate;
containerViewChild;
inputfieldViewChild;
set content(content) {
this.contentViewChild = content;
if (this.contentViewChild) {
if (this.isMonthNavigate) {
Promise.resolve(null).then(() => this.updateFocus());
this.isMonthNavigate = false;
}
else {
if (!this.focus && !this.inline) {
this.initFocusableCell();
}
}
}
}
_dateTemplate;
_headerTemplate;
_footerTemplate;
_disabledDateTemplate;
_decadeTemplate;
_previousIconTemplate;
_nextIconTemplate;
_triggerIconTemplate;
_clearIconTemplate;
_decrementIconTemplate;
_incrementIconTemplate;
_inputIconTemplate;
_componentStyle = inject(CalendarStyle);
contentViewChild;
value;
dates;
months;
weekDays;
currentMonth;
currentYear;
currentHour;
currentMinute;
currentSecond;
pm;
mask;
maskClickListener;
overlay;
responsiveStyleElement;
overlayVisible;
onModelChange = () => { };
onModelTouched = () => { };
calendarElement;
timePickerTimer;
documentClickListener;
animationEndListener;
ticksTo1970;
yearOptions;
focus;
isKeydown;
filled;
inputFieldValue = null;
_minDate;
_maxDate;
_showTime;
_yearRange;
preventDocumentListener;
dayClass(date) {
return this._componentStyle.classes.day({ instance: this, date: date });
}
_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');
}
get rootClass() {
return this._componentStyle.classes.root({ instance: this });
}
get panelClass() {
return this._componentStyle.classes.panel({ instance: this });
}
get hasFluid() {
const nativeElement = this.el.nativeElement;
const fluidComponent = nativeElement.closest('p-fluid');
return this.fluid || !!fluidComponent;
}
constructor(zone, overlayService) {
super();
this.zone = zone;
this.overlayService = overlayService;
}
ngOnInit() {
console.log('Calendar component is deprecated as of v18, use DatePicker component instead.');
super.ngOnInit();
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;
}
ngAfterViewInit() {
super.ngAfterViewInit();
if (this.inline) {
this.contentViewChild && this.contentViewChild.nativeElement.setAttribute(this.attributeSelector, '');
if (!this.disabled && !this.inline) {
this.initFocusableCell();
if (this.numberOfMonths === 1) {
if (this.contentViewChild && this.contentViewChild.nativeElement) {
this.contentViewChild.nativeElement.style.width = getOuterWidth(this.containerViewChild?.nativeElement) + 'px';
}
}
}
}
}
templates;
ngAfterContentInit() {
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 '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);
}
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 % 11) - 1;
y = year + 1;
}
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 = date.getSeconds();
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.yearNavigator && 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.yearNavigator && 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.isSingleSelection() && this.hideOnDateTimeSelect) || (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) {
if (this.view === 'year') {
this.onDateSelect(event, { year: year, month: 0, day: 1, selectable: true });
}
else {
this.currentYear = year;
this.setCurrentView('month');
this.onYearChange.emit({ month: this.currentMonth + 1, year: this.currentYear });
}
}
updateInputfie