import * as i0 from '@angular/core'; import { EventEmitter, ElementRef, AfterViewInit, OnDestroy, TemplateRef, InjectionToken, EffectRef, Signal, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { ControlValueAccessor, NgControl } from '@angular/forms'; import { Subject } from 'rxjs'; declare function getStartOfDay(d: Date): Date; declare function getEndOfDay(d: Date): Date; declare function addMonths(d: Date, months: number): Date; declare function subtractDays(d: Date, days: number): Date; declare function getStartOfMonth(d: Date): Date; declare function getEndOfMonth(d: Date): Date; declare function isSameDay(d1: Date | null, d2: Date | null): boolean; declare function normalizeDate(date: DateInput | null): Date | null; type DateInput = Date | string | { toDate: () => Date; _isAMomentObject?: boolean; $d?: Date; }; interface HolidayProvider { isHoliday(date: Date): boolean; getHolidayLabel?(date: Date): string | null; } interface DateRange { [key: string]: [DateInput, DateInput]; } type DatepickerValue = Date | { start: Date | null; end: Date | null; } | Date[] | null; declare function generateMonthOptions(locale: string, year: number): { label: string; value: number; }[]; /** * Format a number using locale-aware number formatting. * Uses Intl.NumberFormat for proper localization of numeric separators and decimals. * * @param value - The number to format * @param locale - The locale to use for formatting (e.g., 'en-US', 'de-DE', 'fr-FR') * @param options - Optional Intl.NumberFormatOptions for customization * @returns Formatted number string */ declare function formatLocaleNumber(value: number, locale: string, options?: Intl.NumberFormatOptions): string; declare function generateYearOptions(currentYear: number, range?: number): { label: string; value: number; }[]; declare function generateTimeOptions(minuteInterval?: number, secondInterval?: number, includeSeconds?: boolean, use24Hour?: boolean): { hourOptions: { label: string; value: number; }[]; minuteOptions: { label: string; value: number; }[]; secondOptions?: { label: string; value: number; }[]; }; declare function generateWeekDays(locale: string, firstDayOfWeek?: number): string[]; declare function getFirstDayOfWeek(locale: string): number; declare function get24Hour(displayHour: number, isPm: boolean): number; declare function update12HourState(fullHour: number): { isPm: boolean; displayHour: number; }; declare function processDateRanges(ranges: DateRange | null): { [key: string]: [Date, Date]; } | null; declare function generateYearGrid(currentYear: number): number[]; declare function generateDecadeGrid(currentDecade: number): number[]; interface DatepickerClasses { wrapper?: string; inputGroup?: string; input?: string; clearBtn?: string; calendarBtn?: string; popover?: string; container?: string; calendar?: string; header?: string; navPrev?: string; navNext?: string; dayCell?: string; footer?: string; closeBtn?: string; } declare class NgxsmkDatepickerInputComponent { isNative: boolean; disabled: boolean; classes: DatepickerClasses | undefined; nativeInputType: string; formattedValue: string; placeholder: string; id: string; name: string; autocomplete: string; required: boolean; minDateNative: string | null; maxDateNative: string | null; ariaLabel: string; ariaDescribedBy: string; errorState: boolean; clearAriaLabel: string; clearLabel: string; isCalendarOpen: boolean; allowTyping: boolean; typedInputValue: string; displayValue: string; showCalendarButton: boolean; calendarAriaLabel: string; validationErrorMessage: string | null; nativeInputChange: EventEmitter; inputBlur: EventEmitter; clearValue: EventEmitter; toggleCalendar: EventEmitter; pointerDown: EventEmitter; pointerUp: EventEmitter; inputGroupFocus: EventEmitter; inputKeyDown: EventEmitter; inputChange: EventEmitter; inputFocus: EventEmitter; nativeInput?: ElementRef; customInput?: ElementRef; focus(): void; onNativeInputChange(event: Event): void; onInputBlur(event: FocusEvent): void; onClearValue(event: MouseEvent): void; onToggleCalendar(event: Event): void; onPointerDown(event: PointerEvent): void; onPointerUp(event: PointerEvent): void; onInputGroupFocus(): void; onInputKeyDown(event: Event): void; onInputChange(event: Event): void; onInputFocus(event: FocusEvent): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } declare class CustomSelectComponent implements AfterViewInit, OnDestroy { options: { label: string; value: unknown; }[]; value: unknown; disabled: boolean; valueChange: EventEmitter; container: ElementRef; button: ElementRef; panel: ElementRef; isOpen: boolean; private readonly elementRef; private readonly platformId; private readonly document; private readonly isBrowser; private resizeObserver; private scrollListener; ngAfterViewInit(): void; ngOnDestroy(): void; private setupResizeObserver; private setupScrollListener; private updatePanelPosition; onDocumentClick(event: MouseEvent | TouchEvent): void; onDocumentTouchStart(event: TouchEvent): void; get displayValue(): string; toggleDropdown(): void; private scrollToSelected; selectOption(option: { label: string; value: unknown; }): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } declare class CalendarHeaderComponent { monthSelect?: CustomSelectComponent; yearSelect?: CustomSelectComponent; monthOptions: { label: string; value: number; }[]; yearOptions: { label: string; value: number; }[]; currentMonth: number; currentYear: number; disabled: boolean; isBackArrowDisabled: boolean; prevMonthAriaLabel: string; nextMonthAriaLabel: string; headerClass?: string; navPrevClass?: string; navNextClass?: string; currentYearChange: EventEmitter; currentMonthChange: EventEmitter; previousMonth: EventEmitter; nextMonth: EventEmitter; onMonthSelect(value: unknown): void; onYearSelect(value: unknown): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Complete translations interface for the datepicker component */ interface DatepickerTranslations { selectDate: string; selectTime: string; clear: string; close: string; today: string; selectEndDate: string; day: string; days: string; previousMonth: string; nextMonth: string; previousYear: string; nextYear: string; previousYears: string; nextYears: string; previousDecade: string; nextDecade: string; clearSelection: string; closeCalendar: string; closeCalendarOverlay: string; calendarFor: string; selectYear: string; selectDecade: string; datesSelected: string; timesSelected: string; time: string; startTime: string; endTime: string; from: string; to: string; holiday: string; month: string; year: string; decade: string; timeline: string; timeSlider: string; calendarOpened: string; calendarClosed: string; dateSelected: string; rangeSelected: string; monthChanged: string; yearChanged: string; calendarLoading: string; calendarReady: string; keyboardShortcuts: string; invalidDateFormat: string; dateBeforeMin: string; dateAfterMax: string; invalidDate: string; } /** * Partial translations - allows overriding only specific keys */ type PartialDatepickerTranslations = Partial; declare class NgxsmkDatepickerContentComponent { isCalendarVisible: boolean; isCalendarOpen: boolean; isInlineMode: boolean; shouldAppendToBody: boolean; theme: string; popoverId: string; classes: DatepickerClasses | undefined; timeOnly: boolean; showTime: boolean; isMobile: boolean; mobileModalStyle: string; align: string; ariaLabel: string; isCalendarOpening: boolean; loadingMessage: string; showRanges: boolean; rangesArray: { key: string; value: [Date, Date]; }[]; mode: 'single' | 'range' | 'multiple' | 'week' | 'month' | 'quarter' | 'year' | 'timeRange'; disabled: boolean; calendarCount: number; calendarLayout: string; syncScrollEnabled: boolean; calendarMonths: { month: number; year: number; days: (Date | null)[]; }[]; weekDays: string[]; selectedDate: Date | null; startDate: Date | null; endDate: Date | null; focusedDate: Date | null; today: Date; dateTemplate: TemplateRef | null; calendarViewMode: string; monthOptions: { label: string; value: number; }[]; currentMonth: number; yearOptions: { label: string; value: number; }[]; currentYear: number; isBackArrowDisabled: boolean; prevMonthAriaLabel: string; nextMonthAriaLabel: string; yearGrid: number[]; currentDecade: number; decadeGrid: number[]; timelineStartDate: Date | null; timelineEndDate: Date | null; timelineMonths: Date[]; minuteInterval: number; startTimeSlider: number; endTimeSlider: number; timeRangeMode: boolean; hourOptions: { label: string; value: number; }[]; minuteOptions: { label: string; value: number; }[]; secondOptions: { label: string; value: number; }[]; ampmOptions: { label: string; value: boolean; }[]; currentDisplayHour: number; currentMinute: number; currentSecond: number; isPm: boolean; showSeconds: boolean; use24Hour: boolean; startDisplayHour: number; startMinute: number; startSecond: number; startIsPm: boolean; endDisplayHour: number; endMinute: number; endSecond: number; endIsPm: boolean; clearAriaLabel: string; clearLabel: string; closeAriaLabel: string; closeLabel: string; translations: DatepickerTranslations | null; boundIsDateDisabled: (date: Date | null) => boolean; boundIsSameDay: (date1: Date | null, date2: Date | null) => boolean; boundIsHoliday: (date: Date | null) => boolean; boundIsMultipleSelected: (date: Date | null) => boolean; boundIsInRange: (date: Date | null) => boolean; boundIsPreviewInRange: (date: Date | null) => boolean; boundGetAriaLabel: (date: Date | null) => string; boundGetDayCellCustomClasses: (date: Date | null) => string | string[] | Set | { [klass: string]: unknown; }; boundGetDayCellTooltip: (date: Date | null) => string | null; boundFormatDayNumber: (date: Date | null) => string; getMonthYearLabel: (month: number, year: number) => string; getCalendarAriaLabelForMonth: (month: number, year: number) => string; isTimelineMonthSelected: (date: Date) => boolean; formatTimeSliderValue: (value: number) => string; backdropClick: EventEmitter; touchStartContainer: EventEmitter; touchMoveContainer: EventEmitter; touchEndContainer: EventEmitter; rangeSelect: EventEmitter<[Date, Date]>; previousMonth: EventEmitter; nextMonth: EventEmitter; currentMonthChange: EventEmitter; currentYearChange: EventEmitter; dateClick: EventEmitter; dateHover: EventEmitter; dateFocus: EventEmitter; swipeStart: EventEmitter; swipeMove: EventEmitter; swipeEnd: EventEmitter; touchStart: EventEmitter<{ event: TouchEvent; day: Date | null; }>; touchMove: EventEmitter; touchEnd: EventEmitter<{ event: TouchEvent; day: Date | null; }>; viewModeChange: EventEmitter<"year" | "month" | "decade" | "timeline" | "time-slider">; changeYear: EventEmitter; yearClick: EventEmitter; changeDecade: EventEmitter; decadeClick: EventEmitter; timelineZoomOut: EventEmitter; timelineZoomIn: EventEmitter; timelineMonthClick: EventEmitter; startTimeSliderChange: EventEmitter; endTimeSliderChange: EventEmitter; currentDisplayHourChange: EventEmitter; currentMinuteChange: EventEmitter; currentSecondChange: EventEmitter; isPmChange: EventEmitter; timeChange: EventEmitter; startDisplayHourChange: EventEmitter; startMinuteChange: EventEmitter; startSecondChange: EventEmitter; startIsPmChange: EventEmitter; endDisplayHourChange: EventEmitter; endMinuteChange: EventEmitter; endSecondChange: EventEmitter; endIsPmChange: EventEmitter; timeRangeChange: EventEmitter; clearValue: EventEmitter; closeCalendar: EventEmitter; escapeKey: EventEmitter; header?: CalendarHeaderComponent; popoverContainer?: ElementRef; timelineContainer?: ElementRef; closeAllSelects(): void; onTimelineMonthClick(month: Date, event: MouseEvent): void; onTimelineMonthSpace(month: Date, event: Event): void; onPopoverEscape(event: Event): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } interface DayCellRenderHook { getDayCellClasses?(date: Date, isSelected: boolean, isDisabled: boolean, isToday: boolean, isHoliday: boolean): string[]; getDayCellTooltip?(date: Date, holidayLabel: string | null): string | null; formatDayNumber?(date: Date): string; } interface ValidationHook { validateDate?(date: Date, currentValue: DatepickerValue, mode: 'single' | 'range' | 'multiple' | 'week' | 'month' | 'quarter' | 'year' | 'timeRange'): boolean; validateRange?(startDate: Date, endDate: Date): boolean; getValidationError?(date: Date): string | null; } interface KeyboardShortcutHook { handleShortcut?(event: KeyboardEvent, context: KeyboardShortcutContext): boolean; getShortcutHelp?(): KeyboardShortcutHelp[]; } interface KeyboardShortcutContext { currentDate: Date; selectedDate: Date | null; startDate: Date | null; endDate: Date | null; selectedDates: Date[]; mode: 'single' | 'range' | 'multiple' | 'week' | 'month' | 'quarter' | 'year' | 'timeRange'; focusedDate: Date | null; isCalendarOpen: boolean; } interface KeyboardShortcutHelp { key: string; description: string; modifiers?: string[]; } interface DateFormatHook { formatDisplayValue?(value: DatepickerValue, mode: 'single' | 'range' | 'multiple' | 'week' | 'month' | 'quarter' | 'year' | 'timeRange'): string; formatAriaLabel?(date: Date): string; } interface EventHook { beforeDateSelect?(date: Date, currentValue: DatepickerValue): boolean; afterDateSelect?(date: Date, newValue: DatepickerValue): void; onCalendarOpen?(): void; onCalendarClose?(): void; } interface DatepickerHooks extends DayCellRenderHook, ValidationHook, KeyboardShortcutHook, DateFormatHook, EventHook { } /** * Date Adapter Interface * * Allows consumers to swap formatting/parsing logic with external date libraries * like date-fns, dayjs, or Luxon. */ interface DateAdapter { /** * Parse a date from a string or value * @param value - The value to parse (string, Date, or library-specific type) * @param onError - Optional callback for error handling. Called when parsing fails. * @returns A Date object or null if parsing fails */ parse(value: string | Date | number | unknown, onError?: (error: Error) => void): Date | null; /** * Format a date to a string * @param date - The date to format * @param format - Format string (library-specific) * @param locale - Locale string (e.g., 'en-US') * @returns Formatted date string */ format(date: Date, format?: string, locale?: string): string; /** * Check if a value is a valid date * @param value - The value to check * @returns True if the value is a valid date */ isValid(value: string | Date | number | unknown): boolean; /** * Get the start of day for a date * @param date - The date * @returns Date at start of day */ startOfDay(date: Date): Date; /** * Get the end of day for a date * @param date - The date * @returns Date at end of day */ endOfDay(date: Date): Date; /** * Add months to a date * @param date - The date * @param months - Number of months to add * @returns New date with months added */ addMonths(date: Date, months: number): Date; /** * Add days to a date * @param date - The date * @param days - Number of days to add * @returns New date with days added */ addDays(date: Date, days: number): Date; /** * Check if two dates are the same day * @param date1 - First date * @param date2 - Second date * @returns True if dates are the same day */ isSameDay(date1: Date | null, date2: Date | null): boolean; } /** * Default Date Adapter using native JavaScript Date */ declare class NativeDateAdapter implements DateAdapter { parse(value: string | Date | number | unknown, onError?: (error: Error) => void): Date | null; format(date: Date, _format?: string, locale?: string): string; isValid(value: string | Date | number | unknown): boolean; startOfDay(date: Date): Date; endOfDay(date: Date): Date; addMonths(date: Date, months: number): Date; addDays(date: Date, days: number): Date; isSameDay(date1: Date | null, date2: Date | null): boolean; } interface DatepickerConfig { weekStart?: number | null; minuteInterval?: number; holidayProvider?: HolidayProvider | null; yearRange?: number; locale?: string; timezone?: string; minDate?: Date | string | null; maxDate?: Date | string | null; dateAdapter?: DateAdapter; animations?: AnimationConfig; autoDetectMobile?: boolean; mobileModalStyle?: 'bottom-sheet' | 'center' | 'fullscreen'; } interface AnimationConfig { enabled?: boolean; duration?: number; easing?: string; property?: string; respectReducedMotion?: boolean; } declare const DEFAULT_ANIMATION_CONFIG: Required; declare const DATEPICKER_CONFIG: InjectionToken; declare const DEFAULT_DATEPICKER_CONFIG: DatepickerConfig; declare function provideDatepickerConfig(config: DatepickerConfig): { provide: InjectionToken; useValue: { weekStart?: number | null; minuteInterval?: number; holidayProvider?: HolidayProvider | null; yearRange?: number; locale?: string; timezone?: string; minDate?: Date | string | null; maxDate?: Date | string | null; dateAdapter?: DateAdapter; animations?: AnimationConfig; autoDetectMobile?: boolean; mobileModalStyle?: "bottom-sheet" | "center" | "fullscreen"; }; }; interface ValidationError { kind: string; message?: string; } type SignalFormFieldConfig = { value?: DatepickerValue | string | (() => DatepickerValue | string) | { (): DatepickerValue | string; } | Signal; disabled?: boolean | (() => boolean) | { (): boolean; } | Signal; required?: boolean | (() => boolean) | { (): boolean; } | Signal; errors?: ValidationError[] | (() => ValidationError[]) | { (): ValidationError[]; } | Signal; valid?: boolean | (() => boolean) | { (): boolean; } | Signal; invalid?: boolean | (() => boolean) | { (): boolean; } | Signal; touched?: boolean | (() => boolean) | { (): boolean; } | Signal; setValue?: (value: DatepickerValue | string) => void; updateValue?: (updater: () => DatepickerValue | string) => void; markAsDirty?: () => void; markAsTouched?: () => void; }; type SignalFormField = unknown; interface FieldSyncCallbacks { onValueChanged: (value: DatepickerValue) => void; onDisabledChanged: (disabled: boolean) => void; onRequiredChanged?: (required: boolean) => void; onErrorStateChanged?: (hasError: boolean) => void; onSyncError: (error: unknown) => void; normalizeValue: (value: unknown) => DatepickerValue; isValueEqual: (val1: DatepickerValue, val2: DatepickerValue) => boolean; onCalendarGenerated?: () => void; onStateChanged?: () => void; } declare class FieldSyncService { private _fieldEffectRef; private _lastKnownFieldValue; private _isUpdatingFromInternal; private readonly injector; private readFieldValue; private readDisabledState; private readFieldErrors; private readRequiredState; private hasValidationErrors; private resolveField; setupFieldSync(fieldInput: SignalFormField, callbacks: FieldSyncCallbacks): EffectRef | null; syncFieldValue(fieldInput: SignalFormField | Signal | (() => unknown) | unknown, callbacks: FieldSyncCallbacks): boolean; updateFieldFromInternal(value: DatepickerValue, fieldInput: SignalFormField | Signal | (() => unknown) | unknown): void; getLastKnownValue(): DatepickerValue | undefined; markAsTouched(fieldInput: SignalFormField | Signal | (() => unknown) | unknown): void; cleanup(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } interface TranslationService { translate(key: string, params?: Record): string; getCurrentLocale(): string; } declare class DefaultTranslationService implements TranslationService { private translations; private locale; private readonly translationRegistry; constructor(); initialize(translations: DatepickerTranslations, locale?: string): void; initializeFromLocale(locale: string): void; translate(key: string, params?: Record): string; getCurrentLocale(): string; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } interface TouchGestureState { touchStartTime: number; touchStartElement: EventTarget | null; dateCellTouchStartTime: number; dateCellTouchStartDate: Date | null; dateCellTouchStartX: number; dateCellTouchStartY: number; isDateCellTouching: boolean; lastDateCellTouchDate: Date | null; dateCellTouchHandled: boolean; calendarSwipeStartX: number; calendarSwipeStartY: number; calendarSwipeStartTime: number; isCalendarSwiping: boolean; hoveredDate: Date | null; } /** Recurring date pattern configuration for disabled dates. */ type RecurringPatternInput = { pattern: 'daily' | 'weekly' | 'monthly' | 'yearly' | 'weekdays' | 'weekends'; startDate: Date; endDate?: Date; dayOfWeek?: number; dayOfMonth?: number; interval?: number; } | null; /** * Interface for Angular Material Form Field Control compatibility. * We define it here to avoid a direct dependency on @angular/material. */ interface MatFormFieldControlMock { value: T | null; stateChanges: Subject; id: string; placeholder: string; ngControl: NgControl | null; focused: boolean; empty: boolean; shouldLabelFloat: boolean; required: boolean; disabled: boolean; errorState: boolean; controlType?: string; autofilled?: boolean; userAriaDescribedBy?: string; setDescribedByIds(ids: string[]): void; onContainerClick(event: MouseEvent): void; } declare class NgxsmkDatepickerComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit, ControlValueAccessor, MatFormFieldControlMock { private static _idCounter; private static readonly _allInstances; private static _materialSupportRegistered; private static _patchMetadataArrays; static withMaterialSupport(matFormFieldControlToken: any, targetCmp?: any): void; _uniqueId: string; mode: 'single' | 'range' | 'multiple' | 'week' | 'month' | 'quarter' | 'year' | 'timeRange'; calendarViewMode: 'month' | 'year' | 'decade' | 'timeline' | 'time-slider'; isInvalidDate: (date: Date) => boolean; showRanges: boolean; showTime: boolean; timeOnly: boolean; timeRangeMode: boolean; showCalendarButton: boolean; minuteInterval: number; use24Hour: boolean; secondInterval: number; showSeconds: boolean; holidayProvider: HolidayProvider | null; disableHolidays: boolean; disabledDates: (string | Date)[]; disabledRanges: Array<{ start: Date | string; end: Date | string; }>; recurringPattern?: RecurringPatternInput; dateTemplate: TemplateRef | null; private _placeholder; set placeholder(value: string | null); get placeholder(): string; inline: boolean | 'always' | 'auto'; private _inputId; set inputId(value: string); get inputId(): string; private _name; set name(value: string); get name(): string; private _autocomplete; set autocomplete(value: string); get autocomplete(): string; translations?: PartialDatepickerTranslations; translationService?: TranslationService; clearLabel: string; closeLabel: string; prevMonthAriaLabel: string; nextMonthAriaLabel: string; clearAriaLabel: string; closeAriaLabel: string; get _clearLabel(): string; get _closeLabel(): string; get _prevMonthAriaLabel(): string; get _nextMonthAriaLabel(): string; get _clearAriaLabel(): string; get _closeAriaLabel(): string; weekStart: number | null; private readonly _yearRange; set yearRange(value: number); get yearRange(): number; timezone?: string; hooks: DatepickerHooks | null; enableKeyboardShortcuts: boolean; customShortcuts: { [key: string]: (context: KeyboardShortcutContext) => boolean; } | null; autoApplyClose: boolean; /** * Range mode only: allow a one-day range by clicking the same date twice, or by closing the popover * with only a start date selected (start and end will both be that day). */ allowSameDay: boolean; displayFormat?: string; allowTyping: boolean; private _calendarCount; set calendarCount(value: number); get calendarCount(): number; calendarLayout: 'horizontal' | 'vertical' | 'auto'; defaultMonthOffset: number; /** * Configuration for synchronous scrolling in multi-calendar mode. * Keeps calendars in sync by enforcing consistent month offsets across visible calendars. * * @example * ```typescript * // Keep calendars exactly 1 month apart * * * * // Disable sync scroll (independent navigation) * * * ``` */ syncScroll: { enabled?: boolean; monthGap?: number; }; align: 'left' | 'right' | 'center'; useNativePicker: boolean; enableHapticFeedback: boolean; mobileModalStyle: 'bottom-sheet' | 'center' | 'fullscreen'; mobileTimePickerStyle: 'wheel' | 'slider' | 'native'; enablePullToRefresh: boolean; mobileTheme: 'compact' | 'comfortable' | 'spacious'; enableVoiceInput: boolean; autoDetectMobile: boolean; disableFocusTrap: boolean; appendToBody: boolean; private readonly appRef; private readonly document; portalTemplate: TemplateRef; private portalViewRef; get _shouldAppendToBody(): boolean; /** * Detects if the datepicker is rendered inside a modal/dialog so the calendar * can be appended to body and positioned above the modal. */ private isInsideModal; private readonly _isCalendarOpen; get isCalendarOpen(): boolean; set isCalendarOpen(value: boolean); private isOpeningCalendar; /** Public getter for template: true while calendar is opening/generating (loading state). */ get isCalendarOpening(): boolean; /** Returns translated "Loading calendar..." for template and ARIA. */ getCalendarLoadingMessage(): string; private openCalendarTimeoutId; private lastToggleTime; private touchStartTime; private touchStartElement; private pointerDownTime; private isPointerEvent; private previousFocusElement; private _value; set value(val: DatepickerValue); get value(): DatepickerValue; private _field; private _fieldEffectRef; set field(field: SignalFormField); get field(): SignalFormField; private syncFieldValue; private _startAtDate; set startAt(value: DateInput | null); private _locale; set locale(value: string); get locale(): string; theme: 'light' | 'dark'; get isDarkMode(): boolean; private _dateFormatPattern; private customDateFormatService; set dateFormatPattern(value: string | null); get dateFormatPattern(): string | null; private _animationConfig; /** * Animation configuration allowing customization of animation duration, easing, and reduction. * Supports prefers-reduced-motion accessibility preference automatically. * * @example * ```typescript * // Disable all animations * * * // Custom animation duration and easing * * * // Disable specific animation properties * * ``` */ set animationConfig(value: AnimationConfig | null); get animationConfig(): AnimationConfig | null; private _rtl; set rtl(value: boolean | null); get rtl(): boolean | null; get isRtl(): boolean; get rtlClass(): boolean; classes?: DatepickerClasses | undefined; private onChange; private onTouched; disabled: boolean; set disabledState(isDisabled: boolean); /** * Subject used for Material Form Field integration. * Emits when the component's state changes (disabled, required, error state, etc.) * * @remarks * This Subject is required for Angular Material's form field control interface. * It allows Material form fields to track state changes and update their appearance * accordingly (e.g., showing error states, floating labels, etc.). * * The Subject is properly cleaned up in ngOnDestroy() to prevent memory leaks. * It's marked as readonly to prevent external code from reassigning it. */ readonly stateChanges: Subject; private _focused; private _required; private _errorState; get focused(): boolean; get empty(): boolean; get shouldLabelFloat(): boolean; get required(): boolean; set required(value: boolean); get errorState(): boolean; set errorState(value: boolean); get controlType(): string; get autofilled(): boolean; get id(): string; get describedBy(): string; /** * Aria describedby ID provided by the user or the parent form field. * Required for Angular Material form field control interface. */ userAriaDescribedBy: string; setDescribedByIds(ids: string[]): void; onContainerClick(_event: MouseEvent): void; valueChange: EventEmitter; action: EventEmitter<{ type: string; payload?: unknown; }>; /** Emitted when validation fails (e.g. invalid typed date, date before min, after max). Message is translated. */ validationError: EventEmitter<{ code: string; message: string; }>; private _validationErrorMessage; /** User-facing validation error message when set (e.g. from typed input or min/max). */ get validationErrorMessage(): string | null; private setValidationError; private clearValidationError; private _minDate; set minDate(value: DateInput | null); get minDate(): DateInput | null; private _maxDate; set maxDate(value: DateInput | null); get maxDate(): DateInput | null; private _ranges; set ranges(value: DateRange | null); currentDate: Date; daysInMonth: (Date | null)[]; multiCalendarMonths: Array<{ month: number; year: number; days: (Date | null)[]; }>; /** * LRU (Least Recently Used) cache for calendar month generation. * Caches generated month arrays to avoid recalculating the same months. * * @remarks * Performance characteristics: * - Calendar generation: O(1) per month when cached * - Cache lookup: O(1) average case * - Cache eviction: O(n) where n = cache size (only when cache is full) * * The cache automatically evicts the least recently used entry when it reaches * MAX_CACHE_SIZE to prevent unbounded memory growth. This is especially important * for applications with many datepicker instances or long-running sessions. */ /** * Maximum number of months to cache before evicting LRU entries. * Now managed by CalendarGenerationService. */ weekDays: string[]; today: Date; selectedDate: Date | null; selectedDates: Date[]; startDate: Date | null; endDate: Date | null; hoveredDate: Date | null; rangesArray: { key: string; value: [Date, Date]; }[]; protected touchState: TouchGestureState; private dateCellTouchHandledTime; private touchHandledTimeout; private readonly activeTimeouts; private readonly activeAnimationFrames; private fieldSyncTimeoutId; private readonly touchListenersSetup; private readonly touchListenersAttached; private bottomSheetSwipeStartY; private bottomSheetSwipeCurrentY; private isBottomSheetSwiping; private readonly bottomSheetSwipeThreshold; private readonly SWIPE_THRESHOLD; private readonly SWIPE_TIME_THRESHOLD; private _currentMonth; _currentYear: number; _currentDecade: number; monthOptions: i0.Signal<{ label: string; value: number; }[]>; yearOptions: i0.Signal<{ label: string; value: number; }[]>; decadeOptions: { label: string; value: number; }[]; yearGrid: number[]; hourOptions: { label: string; value: number; }[]; minuteOptions: { label: string; value: number; }[]; secondOptions: { label: string; value: number; }[]; decadeGrid: number[]; private firstDayOfWeek; currentHour: number; currentMinute: number; currentSecond: number; currentDisplayHour: number; isPm: boolean; startHour: number; startMinute: number; startSecond: number; startDisplayHour: number; startIsPm: boolean; endHour: number; endMinute: number; endSecond: number; endDisplayHour: number; endIsPm: boolean; ampmOptions: { label: string; value: boolean; }[]; timelineMonths: Date[]; timelineStartDate: Date; timelineEndDate: Date; private timelineZoomLevel; startTimeSlider: number; endTimeSlider: number; private readonly elementRef; private readonly cdr; private readonly platformId; private readonly globalConfig; private readonly fieldSyncService; private readonly localeRegistry; private readonly translationRegistry; private readonly focusTrapService; private readonly ariaLiveService; private readonly hapticFeedbackService; private readonly calendarGenerationService; private readonly parsingService; private readonly touchService; private readonly popoverPositioningService; readonly ngControl: NgControl | null; private readonly isBrowser; private readonly dateComparator; constructor(); typedInputValue: string; private isTyping; popoverContainer?: ElementRef; readonly popoverId: string; datepickerInput?: NgxsmkDatepickerInputComponent; datepickerContent?: NgxsmkDatepickerContentComponent; private focusTrapCleanup; _translations: DatepickerTranslations | null; private _translationService; private _changeDetectionScheduled; /** * Schedules change detection to run in the next microtask. * Prevents multiple change detection cycles from being scheduled simultaneously. * * @remarks * This method is essential for zoneless compatibility. When Zone.js is not present, * Angular's automatic change detection doesn't run, so components using OnPush * strategy must manually trigger change detection when state changes. * * The debouncing mechanism prevents excessive change detection cycles when multiple * state changes occur in rapid succession (e.g., during user interactions or async * operations). Only one change detection cycle is scheduled per microtask queue. * * This pattern is compatible with both Zone.js and zoneless Angular applications. */ private scheduleChangeDetection; /** * Creates a tracked setTimeout that is automatically cleaned up on component destroy. * All timeouts created through this method are stored in activeTimeouts for proper cleanup. * * @param callback - Function to execute after delay * @param delay - Delay in milliseconds * @returns Timeout ID that can be used with clearTimeout */ private trackedSetTimeout; /** * Creates a tracked requestAnimationFrame that is automatically cancelled on component destroy. * All animation frames created through this method are stored in activeAnimationFrames for proper cleanup. * * @param callback - Function to execute on next animation frame * @returns Animation frame ID that can be used with cancelAnimationFrame */ private trackedRequestAnimationFrame; /** * Executes a callback after two animation frames, ensuring DOM updates are complete. * Useful for operations that need to run after Angular's change detection and browser rendering. * * @param callback - Function to execute after double animation frame */ private trackedDoubleRequestAnimationFrame; /** * Clears all active timeouts. Used when locale or weekStart changes * to cancel any pending operations that might be invalidated by the change. */ private clearActiveTimeouts; /** * Debounces field synchronization to prevent race conditions from rapid updates. * Cancels any pending sync operation before scheduling a new one. * * @param delay - Debounce delay in milliseconds (default: 100ms) */ private debouncedFieldSync; private readonly _currentMonthSignal; private readonly _currentYearSignal; private readonly _localeSignal; private readonly _holidayProviderSignal; private readonly _disabledStateSignal; /** * Effect that automatically triggers change detection when key signals change. * This reduces the need for manual markForCheck() calls throughout the codebase. */ private readonly _changeDetectionEffect; /** * Signal tracking which calendar month indices are currently visible in the viewport. * Used for lazy rendering of multi-calendar layouts to improve performance. */ private readonly _visibleCalendarIndicesSignal; /** Bumped when `multiCalendarMonths` is regenerated so `renderedCalendars` invalidates (plain array is not a signal). */ private readonly _multiCalendarDataRevision; /** * Computed signal for rendered calendars - only includes visible calendars + buffer. * This dramatically reduces DOM nodes for multi-calendar layouts. */ renderedCalendars: i0.Signal<{ month: number; year: number; days: (Date | null)[]; }[]>; private _cachedIsCurrentMonthMemo; private _cachedIsDateDisabledMemo; private _cachedIsSameDayMemo; private _cachedIsHolidayMemo; private _cachedGetHolidayLabelMemo; private _memoDependencies; private _updateMemoSignals; private passiveTouchListeners; get isInlineMode(): boolean; private clearTouchHandledFlag; private closeMonthYearDropdowns; private setTouchHandledFlag; isMobileDevice(): boolean; shouldUseNativePicker(): boolean; getNativeInputType(): string; formatValueForNativeInput(value: DatepickerValue): string; formatDateForNativeInput(date: Date): string; getMinDateForNativeInput(): string | null; getMaxDateForNativeInput(): string | null; parseNativeInputValue(value: string): DatepickerValue; onNativeInputChange(event: Event): void; onBottomSheetTouchStart(event: TouchEvent): void; onBottomSheetTouchMove(event: TouchEvent): void; onBottomSheetTouchEnd(event: TouchEvent): void; readonly boundIsDateDisabled: (d: Date | null) => boolean; readonly boundIsSameDay: (d1: Date | null, d2: Date | null) => boolean; readonly boundIsHoliday: (d: Date | null) => boolean; readonly boundIsMultipleSelected: (d: Date | null) => boolean; readonly boundIsInRange: (d: Date | null) => boolean; readonly boundIsPreviewInRange: (d: Date | null) => boolean; readonly boundGetAriaLabel: (d: Date | null) => string; readonly boundGetDayCellCustomClasses: (d: Date | null) => string[]; readonly boundGetDayCellTooltip: (d: Date | null) => string | null; readonly boundFormatDayNumber: (d: Date | null) => string; readonly boundGetMonthYearLabel: (m: number, y: number) => string; readonly boundGetCalendarAriaLabelForMonth: (m: number, y: number) => string; readonly boundIsTimelineMonthSelected: (d: Date) => boolean; readonly boundFormatTimeSliderValue: (v: number) => string; get isCalendarVisible(): boolean; get displayValue(): string; private syncTypedInputIfNotTyping; private getDisplayValueTimeOnly; private getDisplayValueDateDefault; private formatWithCustomFormat; private formatWithAdapter; private formatWithParsingServiceFallback; /** * Format dates using a custom date format pattern * Supports YYYY, MM, DD, HH, mm, ss, etc. */ private formatWithCustomPattern; get isBackArrowDisabled(): boolean; private _invalidateMemoCache; get isCurrentMonthMemo(): (day: Date | null) => boolean; /** * Memoized function for checking if a date is disabled. * Returns a cached function that checks date constraints efficiently. * * @returns A function that checks if a date is disabled * * @remarks * This getter implements memoization to avoid recreating the validation function * on every calendar render. The function is regenerated only when: * - Disabled state constraints change (minDate, maxDate, disabledDates, disabledRanges) * - Current month/year changes * * Performance: O(1) to get the memoized function, O(n) to execute where n = constraints * The memoization significantly improves performance when rendering calendar grids * with many date cells (e.g., multiple calendar months). */ get isDateDisabledMemo(): (day: Date | null) => boolean; /** * Memoized function for comparing if two dates are the same day. * Uses an optimized date comparator for efficient day-level comparisons. * * @returns A function that compares two dates for same-day equality * * @remarks * The date comparator normalizes times to start of day before comparison, * ensuring accurate day-level equality checks regardless of time components. * * Performance: O(1) - Simple date field comparisons after normalization */ get isSameDayMemo(): (d1: Date | null, d2: Date | null) => boolean; /** * Memoized function for checking if a date is a holiday. * Returns a cached function that uses the current holiday provider. * * @returns A function that checks if a date is a holiday * * @remarks * The function is regenerated when the holidayProvider changes. * This ensures the memoized function always uses the current provider * while avoiding recreation on every calendar render. * * Performance: O(1) to get memoized function, O(1) to execute (depends on provider implementation) */ get isHolidayMemo(): (day: Date | null) => boolean; get getHolidayLabelMemo(): (day: Date | null) => string | null; /** * TrackBy function for calendar day cells in *ngFor loops. * Provides stable identity for Angular's change detection optimization. * * @param index - Array index of the day * @param day - The date object (or null for empty cells) * @returns Unique identifier for the day cell * * @remarks * Using timestamp ensures stable identity even when Date objects are recreated. * This significantly improves *ngFor performance by allowing Angular to track * which items have changed, moved, or been removed. */ trackByDay(index: number, day: Date | null): string; /** * TrackBy function for calendar month containers in multi-calendar views. * Provides stable identity for efficient change detection. * * @param _index - Array index (unused, using year-month for identity) * @param calendarMonth - The calendar month object * @returns Unique identifier combining year and month */ /** * Checks if a DOM node is contained within this datepicker instance, * including its input group and any portaled popover content. * * @param target - The node to check * @returns True if the node is inside this datepicker's DOM tree */ containsNode(target: Node | null): boolean; /** Shared logic for closing calendar when user interacts outside (click or touch). */ private tryCloseCalendarOnOutsideInteraction; onDocumentClick(event: MouseEvent | TouchEvent): void; onDocumentTouchStart(event: TouchEvent): void; private handleDocumentOutsideInteraction; onTouchStart(event: TouchEvent): void; onInputGroupFocus(): void; private focusInput; onTouchEnd(event: TouchEvent): void; private closeOtherCalendarInstances; private applyCalendarOpenStateFromTouch; onPointerDown(event: PointerEvent): void; onPointerUp(event: PointerEvent): void; private clearPointerTouchState; private applyCalendarCloseState; private applyCalendarOpenStateFromPointer; onKeyDown(event: KeyboardEvent): void; private handleKeyboardNavigation; private tryCustomShortcuts; private tryHooksHandleShortcut; private handleShortcutKey; private handleShortcutNavigationKeys; private handleShortcutArrowKeys; private handleShortcutPageHomeEndKeys; private handleShortcutLetterAndSpecialKeys; isKeyboardHelpOpen: boolean; toggleKeyboardHelp(): void; private getShortcutKey; focusedDate: Date | null; private navigateDate; private navigateToFirstDay; private navigateToLastDay; private selectToday; private selectYesterday; private selectTomorrow; private selectNextWeek; onDateFocus(day: Date | null): void; private isDateValid; getDayCellCustomClasses(day: Date | null): string[]; getDayCellTooltip(day: Date | null): string | null; formatDayNumber(day: Date | null): string; /** * Generates an accessible label for a date cell. * Provides screen readers with a descriptive label for each selectable date. * * @param day - The date to generate a label for * @returns Localized date label (e.g., "Monday, January 15, 2024") * * @remarks * The label includes weekday, month, day, and year for full context. * Custom formatting can be provided via the formatAriaLabel hook. * This ensures screen reader users have complete information about each date. */ getAriaLabel(day: Date | null): string; /** * ControlValueAccessor implementation: Writes a new value to the form control. * Called by Angular Forms when the form control value changes programmatically. * * @param val - The new value from the form control * * @remarks * This method: * - Normalizes the incoming value to ensure consistent format * - Initializes component state from the value * - Updates memoized signals for change detection * - Regenerates calendar to reflect the new value * - Notifies Material Form Field of state changes * - Syncs with Signal Form field if field input is used * * This is part of the ControlValueAccessor interface, enabling two-way binding * with both Reactive Forms and Template-driven Forms. */ writeValue(val: DatepickerValue): void; /** * ControlValueAccessor implementation: Registers a callback for value changes. * Called by Angular Forms to receive notifications when the user changes the value. * * @param fn - Callback function to call when value changes */ registerOnChange(fn: (value: DatepickerValue) => void): void; /** * ControlValueAccessor implementation: Registers a callback for touched state. * Called by Angular Forms to receive notifications when the user interacts with the control. * * @param fn - Callback function to call when control is touched */ registerOnTouched(fn: () => void): void; setDisabledState(isDisabled: boolean): void; /** * Emits a value change event and updates the internal state. * Handles normalization, form field synchronization, and calendar auto-close behavior. * * @param val - The new datepicker value (Date, Date range, or array of dates) * * @remarks * This method is the central point for value updates and ensures: * - Value normalization for consistent internal representation * - Signal Form field synchronization (if field input is used) * - Event emission for two-way binding * - Touch state tracking for form validation * - Automatic calendar closing for single date and complete range selections * * The calendar auto-closes when: * - Single date mode: After any date selection * - Range mode: After both start and end dates are selected * - Not in inline mode * - Not in time-only mode */ private emitValue; /** * Toggles the calendar popover open/closed state. * Handles focus management, accessibility announcements, and prevents rapid toggling. * * @param event - Optional event that triggered the toggle (used to prevent toggle on clear button clicks) * * @remarks * This method implements several important behaviors: * - Debouncing: Prevents rapid toggling within 300ms * - Focus management: Stores previous focus element for restoration * - Accessibility: Announces calendar state changes to screen readers * - Touch optimization: Sets up passive touch listeners for mobile devices * * When opening: * - Stores the currently focused element for restoration * - Sets up focus trap for keyboard navigation * - Announces calendar opening with current month/year * * When closing: * - Removes focus trap * - Restores focus to previous element * - Announces calendar closing */ toggleCalendar(event?: Event): void; private applyToggleWithNoEvent; private shouldSkipClickToggle; private applyDefaultMonthForOpen; private applySmartViewModeForOpen; private announceAfterOpen; private announceAfterClose; private announceCalendarOpened; private announceCalendarClosed; onBackdropInteract(event: Event): void; onPopoverEscape(event: Event): void; private scrollDebounceTimer; private readonly updatePositionOnScroll; private _startOpeningState; private _startClosingState; private renderInBody; /** Hides the body-appended popover so loading/calendar are not visible at wrong position. */ private hideBodyPopoverUntilPositioned; /** Shows the body-appended popover after positioning has been applied. */ private revealBodyPopover; private destroyBodyView; private closeCalendar; private shouldAutoClose; /** * Clears the selected date value(s) and resets the component state. * Emits null value and closes calendar if open. * * @param event - Optional event that triggered the clear action * * @remarks * This method: * - Clears all selected dates (single, range, multiple modes) * - Emits null value to form controls * - Closes calendar if open * - Provides haptic feedback on mobile if enabled * - Resets touch gesture state * - Announces clearing to screen readers * * Used by the clear button and can be called programmatically. */ clearValue(event?: MouseEvent | TouchEvent): void; get currentMonth(): number; set currentMonth(month: number); get currentYear(): number; set currentYear(year: number); private _updateToday; ngOnInit(): void; private initializeTimeFromNowIfNeeded; private resolveInitialValue; private resolveInitialValueFromField; ngAfterViewInit(): void; private setupInputGroupPassiveListeners; private _touchListenersSetupTimeout; /** * Sets up passive touch event listeners on calendar day cells for improved mobile performance. * Implements retry logic to handle cases where DOM elements aren't immediately available. * All listeners are tracked for proper cleanup on component destroy. */ private setupPassiveTouchListeners; private attachTouchListenersToCells; ngOnChanges(changes: SimpleChanges): void; private handleChangesShowTimeInlineAndLayout; private handleChangesLocaleRtl; private handleChangesWeekStartAndRelated; private applyChangesMinuteAnd24Hour; private handleChangesField; private handleChangesTimeAndMode; private handleChangesDisabledStates; private handleChangesTranslations; private handleChangesMaxDate; private handleChangesValue; private handleChangesStartAt; private handleChangesMinDate; private handleChangesCalendarViewMode; /** * Validates component inputs for conflicts and invalid combinations. * Logs warnings in development mode when invalid configurations are detected. * * @param changes - The SimpleChanges object from ngOnChanges */ private validateInputs; private validateInputsMinMaxDate; private validateInputsTimeOnly; private validateInputsIntervals; private validateInputsYearRange; private initializeTimeSliders; private get24Hour; private update12HourState; private applyCurrentTime; private applyTimeIfNeeded; /** * Initializes the component's internal state from a DatepickerValue. * Sets up selected dates, calendar view position, and time values based on the provided value. * * @param value - The datepicker value to initialize from (Date, range, array, or null) * * @remarks * This method handles initialization for all selection modes: * - Single mode: Sets selectedDate * - Range mode: Sets startDate and endDate * - Multiple mode: Sets selectedDates array * * The method also: * - Determines the calendar view center date (uses value, startAt, or minDate as fallback) * - Extracts and sets time values if the date includes time information * - Normalizes all dates to ensure consistent internal representation * * Performance: O(1) for single/range, O(n) for multiple mode where n = array length */ private initializeValue; private applyValueToSelection; private resolveViewCenterDate; private _normalizeDate; /** * Normalizes various date input formats into a consistent DatepickerValue type. * Handles Date objects, Moment.js objects, date ranges, arrays, and strings. * * @param val - The value to normalize (can be Date, Moment, range object, array, or string) * @returns Normalized DatepickerValue (Date, range object, array, or null) * * @remarks * This method provides flexible input handling to support: * - Native JavaScript Date objects * - Moment.js objects (with timezone preservation) * - Date range objects: { start: Date, end: Date } * - Arrays of dates for multiple selection mode * - String dates with custom format parsing * * Invalid or unparseable values are normalized to null. * This ensures type safety and consistent internal state representation. */ private _normalizeValue; private _normalizeRangeValue; private _normalizeArrayValue; /** * Check if the provided value is a Moment.js object */ private isMomentObject; /** * Convert a Moment.js object to a Date, preserving timezone offset */ private momentToDate; /** * Compares two DatepickerValue objects for equality. * Handles Date objects, range objects, and arrays with proper date comparison. * * @param val1 - First value to compare * @param val2 - Second value to compare * @returns true if values represent the same date(s), false otherwise * * @remarks * This method performs deep equality checks: * - For Date objects: Compares using date comparator (handles time normalization) * - For range objects: Compares both start and end dates * - For arrays: Compares lengths and all elements * - Handles null/undefined values correctly * * Uses the dateComparator utility for efficient date comparisons that * normalize times to start of day for accurate day-level equality. */ private isValueEqual; /** * Parses a date string, optionally using the configured date adapter with error callback. * Falls back to native Date parsing if no adapter is configured. * * @param dateString - The date string to parse * @returns Parsed Date object or null if parsing fails * * @remarks * If a date adapter is configured via globalConfig, it will be used for parsing * with error callbacks. Otherwise, native Date parsing is used. * Error callbacks allow consumers to handle parsing failures gracefully. */ onInputFocus(event: FocusEvent): void; /** * Sanitizes user input to prevent XSS attacks. * Removes potentially dangerous characters while preserving valid date/time input. * * @param input - Raw user input string * @returns Sanitized string safe for template interpolation * * @remarks * This method provides basic XSS protection by removing: * - HTML tag delimiters (< and >) * - Script event handlers (onerror, onclick, etc.) * - JavaScript protocol (javascript:) * - Data URIs that could contain scripts * * Note: Angular's template interpolation provides additional protection, * but this sanitization adds an extra layer of defense for user-provided strings. * For comprehensive sanitization, Angular's DomSanitizer should be used for * any HTML content, but for date/time strings, this level of sanitization is sufficient. */ private sanitizeInput; onInputChange(event: Event): void; onInputBlur(event: FocusEvent): void; private applyValidationErrorForBlur; onInputKeyDown(event: Event): void; private applyInputMask; private isValidDate; private applyTypedDate; private generateTimeOptions; private generateLocaleData; private updateRangesArray; selectRange(range: [Date, Date]): void; isHoliday(date: Date | null): boolean; getHolidayLabel(date: Date | null): string | null; /** * Checks if a date is disabled based on all configured constraints. * * @param date - The date to check * @returns true if the date is disabled, false if it can be selected * * @remarks * A date is considered disabled if it matches any of these conditions: * - Falls before minDate * - Falls after maxDate * - Is in the disabledDates array * - Falls within a disabledRanges entry * - Fails the isInvalidDate custom validation function * - Is a holiday and disableHolidays is true * * Performance: O(n) where n = disabledDates.length + disabledRanges.length * For large constraint lists (>1000), consider optimizing with Set or DateRange tree. */ isDateDisabled(date: Date | null): boolean; private _isInDisabledDates; private _isInDisabledRanges; private _isOutOfMinMaxBounds; /** * Checks if a date is selected in multiple selection mode. * * @param d - The date to check * @returns true if the date is in the selectedDates array * * @remarks * Performance: O(n) where n = selectedDates.length * Uses day-level comparison (ignores time) for accurate matching. */ isMultipleSelected(d: Date | null): boolean; /** * Handles time value changes from time selection controls. * Updates the selected date(s) with the new time values. * * @remarks * This method: * - Applies time changes to selected dates based on current mode * - Emits value changes for form integration * - Handles time-only mode by creating a date with current time * - Updates all selected dates in multiple mode * - Ensures startDate <= endDate in range mode */ timeChange(): void; /** * Handles time range changes in timeRangeMode. * Updates the internal time range state and emits the time range to listeners. * Only creates/updates time-only dates (no calendar dates). */ timeRangeChange(): void; /** * Handles date cell click/tap events. * Processes date selection based on the current mode (single, range, multiple, etc.) * and handles touch gesture debouncing to prevent accidental double selections. * * @param day - The date that was clicked (null for empty cells) * * @remarks * This method implements several important behaviors: * - Touch gesture handling: Debounces rapid touch events to prevent double-clicks * - Date validation: Checks if the date is disabled before processing * - Hook integration: Calls beforeDateSelect hook if provided * - Mode-specific logic: Handles single, range, multiple, week, month, quarter, and year modes * - Calendar navigation: Automatically navigates to different month if date is outside current view * - Accessibility: Announces date selection to screen readers * - Auto-close: Closes calendar after selection in single mode or complete range * * Performance considerations: * - Touch debouncing prevents excessive event processing * - Date normalization happens once per selection * - Calendar regeneration is optimized with caching */ onDateClick(day: Date | null): void; /** * Returns true (and cleans up touch state) when the click event should be * ignored because it was already handled by the touch handler within the * deduplication window (250 ms). */ private _shouldSkipDueToTouchGuard; private _navigateToMonthOfDay; private _handleSingleModeClick; private _handleRangeModeClick; private _handleRangeEndSelection; /** Completes range with end equal to start when `allowSameDay` is enabled. */ private _tryCompleteSameDayRange; private _announceRangeSelected; private _finalizeSameDayRangeOnClose; private _handlePeriodModeClick; private _handleMultipleModeClick; private _applyRecurringPattern; private _syncTimeAfterDateClick; onDateHover(day: Date | null): void; onDateCellTouchStart(event: TouchEvent, day: Date | null): void; onDateCellTouchMove(event: TouchEvent): void; onDateCellTouchEnd(event: TouchEvent, day: Date | null): void; isPreviewInRange(day: Date | null): boolean; private buildCalendarMonths; /** * Generates the calendar view for the current month(s). * Uses LRU caching to optimize performance for frequently accessed months. * * @remarks * Performance characteristics: * - First generation: O(n) where n = number of days in month(s) * - Cached generation: O(1) lookup + O(1) cache access update * - Cache eviction: O(m) where m = cache size (only when cache is full) * * This method: * 1. Generates dropdown options for month/year selection * 2. Generates calendar days for each month in calendarCount * 3. Uses LRU cache to avoid regenerating recently accessed months * 4. Handles month/year rollover when displaying multiple calendars * 5. Updates memoized dependencies for change detection optimization * 6. Supports synchronous scrolling to keep calendars in sync (when enabled) * * The cache key format is `${year}-${month}` to ensure unique identification * of calendar months across different years. * * When syncScroll is enabled, calendars are kept synchronized: * - Calendar 0: currentDate month + (0 * monthGap) * - Calendar 1: currentDate month + (1 * monthGap) * - Calendar 2: currentDate month + (2 * monthGap) */ generateCalendar(): void; /** * Preloads adjacent months (previous and next) into the cache for smoother navigation. * Implements lazy loading optimization to improve performance when users navigate between months. * * @param currentYear - Current calendar year * @param currentMonth - Current calendar month (0-11) */ private preloadAdjacentMonths; private generateDropdownOptions; private generateYearGrid; private generateDecadeGrid; onYearClick(year: number): void; onDecadeClick(decade: number): void; /** * Changes the displayed decade by the specified delta. * Used in decade view mode for navigating between decades. * * @param delta - Number of decades to change (positive for future, negative for past) * * @remarks * Each delta unit represents 10 years. The method updates the decade grid * to show the new range of decades available for selection. */ changeDecade(delta: number): void; /** * Changes the displayed calendar year by the specified delta. * Updates year grid and calendar view, and announces the change to screen readers. * * @param delta - Number of years to change (positive for future, negative for past) * * @remarks * This method: * - Updates currentYear and currentDate * - Regenerates year grid and calendar view * - Announces year change to screen readers for accessibility * - Handles touch listener setup for mobile devices * * Performance: O(1) for year change, O(n) for grid/calendar generation */ changeYear(delta: number): void; onViewModeChange(mode: 'month' | 'year' | 'decade' | 'timeline' | 'time-slider'): void; onYearSelectChange(year: unknown): void; private generateTimeline; timelineZoomIn(): void; timelineZoomOut(): void; isTimelineMonthSelected(month: Date): boolean; onTimelineMonthClick(month: Date): void; formatTimeSliderValue(minutes: number): string; onStartTimeSliderChange(minutes: number): void; onEndTimeSliderChange(minutes: number): void; onCalendarSwipeStart(event: TouchEvent): void; onCalendarSwipeMove(event: TouchEvent): void; onCalendarSwipeEnd(event: TouchEvent): void; changeMonth(delta: number): void; isSameDay(d1: Date | null, d2: Date | null): boolean; isCurrentMonth(day: Date | null): boolean; isInRange(d: Date | null): boolean; private applyGlobalConfig; private applyGlobalConfigDefaults; private applyGlobalConfigLocaleAndDates; private applyGlobalConfigMobile; /** * Apply animation configuration from global config */ private applyAnimationConfig; /** * Initialize translations from service or registry */ private initializeTranslations; /** * Generates an accessible label for the calendar dialog. * Provides screen readers with context about which month/year is being displayed. * * @returns Localized calendar label (e.g., "Calendar for January 2024") */ getCalendarAriaLabel(): string; /** * Generates an accessible label for a specific calendar month in multi-calendar views. * * @param month - Month index (0-11) * @param year - Year number * @returns Localized calendar label for the specified month/year */ getCalendarAriaLabelForMonth(month: number, year: number): string; /** * Sets up IntersectionObserver for lazy loading multi-calendar months. * Only initializes if multi-calendar is enabled (calendarCount > 1). * * @remarks * Uses IntersectionObserver to track which calendar month elements are visible * in the viewport. Updates the visible indices signal to enable/disable rendering. */ private setupLazyLoadingObserver; /** * Formats a month and year into a display label. * * @param month - Month index (0-11) * @param year - Year number * @returns Formatted string like "January 2024" */ getMonthYearLabel(month: number, year: number): string; isCurrentMonthForCalendar(day: Date | null, targetMonth: number, targetYear: number): boolean; getTranslation(key: keyof DatepickerTranslations, fallbackKey?: keyof DatepickerTranslations, params?: Record): string; /** * Closes the calendar and restores focus to the previously focused element. * This improves accessibility by returning focus to the trigger element. */ closeCalendarWithFocusRestore(): void; private updateRtlState; /** * Component lifecycle hook: Cleanup all resources, subscriptions, and event listeners. * Ensures no memory leaks by: * - Removing instance from static registry * - Cleaning up field sync service * - Completing stateChanges subject * - Clearing all tracked timeouts and animation frames * - Removing touch event listeners * - Invalidating month cache */ ngOnDestroy(): void; private getActualPopoverContainer; private setupFocusTrap; /** * Positions the popover relative to the input element dynamically. * - Prioritizes layout below the input. * - Falls back to positioning above if required. * - Defaults to CSS-centered positioning if space is insufficient. * * @remarks * This logic primarily targets mobile/tablet viewports; desktop layout (≥1024px) * is handled via CSS absolute positioning. */ private positionPopoverRelativeToInput; /** * Determines if the component is operating within an Ionic environment. * This detection disables features that may conflict with Ionic's overlay system. */ private isIonicEnvironment; private removeFocusTrap; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Wrapper NgModule for the standalone datepicker component. * Use this in your `imports` array if you see NG1010 ("imports must be an array... * Value could not be determined statically") when using the Angular compiler plugin * or in strict AOT builds. * * @example * ```typescript * import { NgxsmkDatepickerModule } from 'ngxsmk-datepicker'; * * @Component({ * standalone: true, * imports: [NgxsmkDatepickerModule], // single static reference * template: '' * }) * export class MyComponent {} * ``` * * For NgModule-based apps: * ```typescript * @NgModule({ * imports: [NgxsmkDatepickerModule], * exports: [NgxsmkDatepickerModule] * }) * export class MyFeatureModule {} * ``` */ declare class NgxsmkDatepickerModule { static ɵfac: i0.ɵɵFactoryDeclaration; static ɵmod: i0.ɵɵNgModuleDeclaration; static ɵinj: i0.ɵɵInjectorDeclaration; } interface ExportOptions { includeTime?: boolean; dateFormat?: string; timezone?: string; csvHeaders?: string[]; } declare function exportToJson(value: DatepickerValue, options?: ExportOptions): string; declare function importFromJson(jsonString: string): DatepickerValue; declare function exportToCsv(value: DatepickerValue, options?: ExportOptions): string; declare function importFromCsv(csvString: string): DatepickerValue; declare function exportToIcs(value: DatepickerValue, options?: ExportOptions & { summary?: string; description?: string; location?: string; }): string; declare function importFromIcs(icsString: string): DatepickerValue; /** * Format a date with timezone support * @param date The date to format * @param locale The locale for formatting * @param options Intl.DateTimeFormatOptions * @param timezone Optional timezone (IANA timezone name, e.g., 'America/New_York', 'UTC', 'Europe/London') * @returns Formatted date string */ declare function formatDateWithTimezone(date: Date, locale: string, options: Intl.DateTimeFormatOptions, timezone?: string): string; /** * Parse a date string with timezone awareness * @param dateString The date string to parse * @param timezone Optional timezone for parsing (IANA timezone name) * @returns Date object (always in UTC internally) */ declare function parseDateWithTimezone(dateString: string, timezone?: string): Date | null; /** * Convert a date from one timezone to another * @param date The date to convert * @param fromTimezone Source timezone (IANA name) * @param _toTimezone Target timezone (IANA name) - currently unused in simplified implementation * @returns New Date object (still UTC internally, but represents the time in target timezone) */ declare function convertTimezone(date: Date, fromTimezone: string, _toTimezone: string): Date; /** * Get the current timezone offset in minutes for a given timezone * @param timezone IANA timezone name * @param date Optional date to check offset for (defaults to now) * @returns Offset in minutes from UTC */ declare function getTimezoneOffset(timezone: string, date?: Date): number; /** * Check if a timezone string is valid * @param timezone IANA timezone name * @returns true if valid, false otherwise */ declare function isValidTimezone(timezone: string): boolean; /** * Calendar system types supported by the datepicker */ type CalendarSystem = 'gregorian' | 'islamic' | 'buddhist' | 'japanese' | 'hebrew' | 'persian'; /** * Locale data structure for datepicker localization */ interface LocaleData { /** Calendar system used by this locale */ calendar: CalendarSystem; /** First day of the week (0 = Sunday, 1 = Monday, etc.) */ firstDayOfWeek: number; /** Default date format string (e.g., 'MM/DD/YYYY', 'DD/MM/YYYY') */ dateFormat: string; /** Full month names (12 elements) */ monthNames: string[]; /** Short month names (12 elements) */ monthNamesShort: string[]; /** Full weekday names (7 elements, starting with Sunday) */ weekdayNames: string[]; /** Short weekday names (7 elements, starting with Sunday) */ weekdayNamesShort: string[]; /** Whether this locale uses RTL (right-to-left) text direction */ isRtl: boolean; /** Fallback locale if this one is not fully supported */ fallbackLocale?: string; /** Locale-specific date format options */ dateFormatOptions?: { year?: 'numeric' | '2-digit'; month?: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow'; day?: 'numeric' | '2-digit'; hour?: 'numeric' | '2-digit'; minute?: 'numeric' | '2-digit'; hour12?: boolean; }; } /** * Service for managing locale data and providing fallback mechanisms * Supports multiple calendar systems and provides locale-specific formatting */ declare class LocaleRegistryService { private localeData; private readonly defaultLocale; constructor(); /** * Register locale data for a specific locale */ register(locale: string, data: LocaleData): void; /** * Get locale data for a specific locale, with fallback support */ getLocaleData(locale: string): LocaleData; /** * Get fallback locale for an unsupported locale */ getFallbackLocale(unsupportedLocale: string): string | null; /** * Check if a locale is RTL */ isRtlLocale(locale: string): boolean; /** * Get calendar system for a locale */ getCalendarSystem(locale: string): CalendarSystem; /** * Register default locale data for common locales */ private registerDefaultLocales; /** * Get default locale data (English US) */ private getDefaultLocaleData; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Service for managing datepicker translations * Provides default translations for major languages */ declare class TranslationRegistryService { private translations; constructor(); /** * Register translations for a locale */ register(locale: string, translations: DatepickerTranslations): void; /** * Get translations for a locale with fallback support */ getTranslations(locale: string): DatepickerTranslations; /** * Register default translations for major languages */ private registerDefaultTranslations; /** * Get English translations (default) */ private getEnglishTranslations; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Service for custom date formatting patterns. * Supports custom patterns beyond standard Angular DatePipe formats. * * @remarks * Supports the following pattern tokens: * - YYYY: 4-digit year (e.g., 2025) * - YY: 2-digit year (e.g., 25) * - MMMM: Full month name (e.g., January) * - MMM: Abbreviated month name (e.g., Jan) * - MM: 2-digit month (e.g., 01) * - M: 1 or 2-digit month (e.g., 1) * - DDDD: Full weekday name (e.g., Monday) * - DDD: Abbreviated weekday name (e.g., Mon) * - DD: 2-digit day (e.g., 05) * - D: 1 or 2-digit day (e.g., 5) * - HH: 2-digit hour (24-hour format, e.g., 14) * - H: 1 or 2-digit hour (24-hour format, e.g., 14) * - hh: 2-digit hour (12-hour format, e.g., 02) * - h: 1 or 2-digit hour (12-hour format, e.g., 2) * - mm: 2-digit minutes (e.g., 05) * - m: 1 or 2-digit minutes (e.g., 5) * - ss: 2-digit seconds (e.g., 09) * - s: 1 or 2-digit seconds (e.g., 9) * - A/a: AM/PM or am/pm */ declare class CustomDateFormatService { private locale; private readonly monthNames; private readonly weekdayNames; constructor(locale?: string); /** * Set the locale for formatting */ setLocale(locale: string): void; /** * Format a date using a custom pattern * * @param date - The date to format * @param pattern - The custom format pattern * @returns Formatted date string */ format(date: Date, pattern: string): string; /** * Parse a formatted date string back to a Date object * Note: This is a best-effort implementation and may not work for all patterns * * @param dateString - The date string to parse * @param pattern - The format pattern used * @returns Parsed Date object, or null if parsing fails */ parse(dateString: string, _pattern: string): Date | null; private getMonthNames; private initializeLocaleData; private getWeekdayNames; } /** * Theme builder service for generating CSS-in-JS styles and managing themes */ declare class ThemeBuilderService implements OnDestroy { private readonly platformId; private styleElement; private scopedStyleElements; /** * Map theme color keys to actual CSS variable names */ private mapColorKey; /** * Map typography keys to actual CSS variable names */ private mapTypographyKey; /** * Generate CSS variables from a theme object */ generateTheme(theme: DatepickerTheme): string; /** * Apply theme to a specific element or globally * @param theme The theme to apply * @param targetElement Optional specific element to apply theme to. If not provided, applies globally. */ applyTheme(theme: DatepickerTheme, targetElement?: HTMLElement): void; /** * Apply theme variables directly to all datepicker elements (for global theme) * Optimized version with batch DOM operations */ private applyToElements; /** * Generate CSS-in-JS style object (for styled-components, emotion, etc.) */ generateStyleObject(theme: DatepickerTheme): Record; /** * Remove applied theme * @param targetElement Optional specific element to remove theme from. If not provided, removes from all. */ removeTheme(targetElement?: HTMLElement): void; /** * Get current theme from CSS variables */ getCurrentTheme(selector?: string): Partial; /** * Clean up all themes and resources when service is destroyed */ cleanupAllThemes(): void; ngOnDestroy(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Datepicker theme interface */ interface DatepickerTheme { colors?: { primary?: string; secondary?: string; background?: string; surface?: string; text?: string; textSecondary?: string; border?: string; hover?: string; active?: string; disabled?: string; error?: string; [key: string]: string | undefined; }; spacing?: { xs?: string; sm?: string; md?: string; lg?: string; xl?: string; [key: string]: string | undefined; }; typography?: { fontFamily?: string; fontSize?: string; fontWeight?: string; lineHeight?: string; [key: string]: string | undefined; }; borderRadius?: { sm?: string; md?: string; lg?: string; full?: string; [key: string]: string | undefined; }; shadows?: { sm?: string; md?: string; lg?: string; /** Focus ring (e.g. input focus). Use a color-mix or rgba for 15% opacity. Example: 0 0 0 3px color-mix(in srgb, var(--datepicker-primary-color) 15%, transparent) */ focus?: string; [key: string]: string | undefined; }; } /** * Date preset interface */ interface DatePreset { id: string; name: string; value: DatepickerValue; createdAt: Date; updatedAt: Date; category?: string; description?: string; } /** * Service for managing date presets with localStorage persistence */ declare class DatePresetsService { private readonly platformId; private readonly storageKey; private presets; constructor(); /** * Save a date preset */ savePreset(preset: Omit): DatePreset; /** * Update an existing preset */ updatePreset(id: string, updates: Partial>): DatePreset | null; /** * Get a preset by ID */ getPreset(id: string): DatePreset | null; /** * Get all presets */ getAllPresets(): DatePreset[]; /** * Get presets by category */ getPresetsByCategory(category: string): DatePreset[]; /** * Get all categories */ getCategories(): string[]; /** * Delete a preset */ deletePreset(id: string): boolean; /** * Clear all presets */ clearPresets(): void; /** * Apply a preset value (returns the value, not the preset object) */ applyPreset(id: string): DatepickerValue | null; /** * Check if a preset exists */ hasPreset(id: string): boolean; /** * Get preset count */ getPresetCount(): number; /** * Export presets to JSON */ exportPresets(): string; /** * Import presets from JSON */ importPresets(jsonString: string, merge?: boolean): { imported: number; errors: number; }; private loadPresets; private persistPresets; private generateId; private cloneValue; private deserializeValue; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } declare class AriaLiveService implements OnDestroy { private readonly platformId; private readonly isBrowser; private politeRegion; private assertiveRegion; private politeClearTimeoutId; private assertiveClearTimeoutId; private debounceTimeoutId; private announcementQueue; private readonly DEBOUNCE_DELAY; private readonly CLEAR_DELAY; constructor(); /** * Announce a message to screen readers with improved timing and queue management */ announce(message: string, priority?: 'polite' | 'assertive'): void; /** * Process queued announcements, keeping only the most recent for each priority */ private processAnnouncementQueue; /** * Announce to a specific live region */ private announceToRegion; /** * Set announcement text and schedule cleanup */ private setAnnouncement; /** * Create a live region for announcements */ private createLiveRegion; ngOnDestroy(): void; destroy(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } declare class FocusTrapService implements OnDestroy { private activeTraps; private focusableSelectors; /** * Trap focus within an element and restore focus on cleanup */ trapFocus(elementRef: ElementRef): () => void; /** * Remove focus trap and restore previous focus */ private removeFocusTrap; private getFirstFocusable; private getLastFocusable; ngOnDestroy(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } declare class HapticFeedbackService { private readonly platformId; private readonly isBrowser; private readonly isSupported; /** * Trigger light haptic feedback (short vibration) */ light(): void; selection(): void; medium(): void; heavy(): void; /** * Trigger custom vibration pattern * @param pattern Vibration pattern in milliseconds */ custom(pattern: number | number[]): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } export { AriaLiveService, CustomDateFormatService, CustomSelectComponent, DATEPICKER_CONFIG, DEFAULT_ANIMATION_CONFIG, DEFAULT_DATEPICKER_CONFIG, DatePresetsService, DefaultTranslationService, FieldSyncService, FocusTrapService, HapticFeedbackService, LocaleRegistryService, NativeDateAdapter, NgxsmkDatepickerComponent, NgxsmkDatepickerModule, ThemeBuilderService, TranslationRegistryService, addMonths, convertTimezone, exportToCsv, exportToIcs, exportToJson, formatDateWithTimezone, formatLocaleNumber, generateDecadeGrid, generateMonthOptions, generateTimeOptions, generateWeekDays, generateYearGrid, generateYearOptions, get24Hour, getEndOfDay, getEndOfMonth, getFirstDayOfWeek, getStartOfDay, getStartOfMonth, getTimezoneOffset, importFromCsv, importFromIcs, importFromJson, isSameDay, isValidTimezone, normalizeDate, parseDateWithTimezone, processDateRanges, provideDatepickerConfig, subtractDays, update12HourState }; export type { AnimationConfig, CalendarSystem, DateAdapter, DateFormatHook, DateInput, DatePreset, DateRange, DatepickerConfig, DatepickerHooks, DatepickerTheme, DatepickerTranslations, DatepickerValue, DayCellRenderHook, EventHook, ExportOptions, HolidayProvider, KeyboardShortcutContext, KeyboardShortcutHelp, KeyboardShortcutHook, LocaleData, PartialDatepickerTranslations, SignalFormField, SignalFormFieldConfig, TranslationService, ValidationHook };