ng-material-date-range-picker
Version:
This library provides the date range selection with two views.
587 lines (577 loc) • 25.2 kB
TypeScript
import * as i0 from '@angular/core';
import { AfterViewInit, EventEmitter, OnInit, Signal } from '@angular/core';
import * as i4 from '@angular/forms';
import { FormGroup, FormControl } from '@angular/forms';
import * as i5 from '@angular/material/datepicker';
import { DateRange, MatCalendar } from '@angular/material/datepicker';
import * as i3 from '@angular/common';
import * as i6 from '@angular/material/core';
import * as i7 from '@angular/material/input';
import * as i8 from '@angular/material/autocomplete';
import * as i9 from '@angular/cdk/overlay';
import * as i10 from '@angular/material/icon';
import * as i11 from '@angular/material/button';
import * as i12 from '@angular/material/list';
import * as i13 from '@angular/material/form-field';
import * as i14 from '@angular/material/tooltip';
declare class CalendarComponent implements AfterViewInit {
firstViewStartDate: i0.WritableSignal<Date>;
secondViewStartDate: i0.WritableSignal<Date>;
secondViewMinDate: i0.WritableSignal<Date>;
minDate: Date;
maxDate: Date;
/** Emits when the user changes the selection by clicking dates in the views. */
selectedDatesChange: EventEmitter<DateRange<Date>>;
firstCalendarView: MatCalendar<Date>;
secondCalendarView: MatCalendar<Date>;
private _selectedDates;
private isAllowHoverEvent;
private cdref;
private el;
private renderer;
/**
* Updates the selected date range and synchronizes both calendar views.
*/
set selectedDates(selectedDates: DateRange<Date> | null);
get selectedDates(): DateRange<Date> | null;
/**
* Lifecycle hook that is called after Angular has fully initialized
* the component's view (and child views).
*
* Used here to attach hover events and register active date change
* listeners once the calendar views are available in the DOM.
*/
ngAfterViewInit(): void;
/**
* Handles month selection in the first view.
*
* @param event - Selected month date
*/
monthSelected(viewName: string): void;
/**
* Updates the selected date range when a date is clicked.
*
* @param date - Date clicked by the user
*/
updateDateRangeSelection(date: Date | null): void;
/**
* Registers event handlers for active date changes on both calendar views.
*
* This method overrides the default `activeDate` property setter of each
* calendar view to ensure custom handlers are executed whenever the
* active date changes.
*/
private registerActiveDateChangeEvents;
/**
* Handles the event when the active date of the first calendar view changes.
*
* @param activeDate - Object containing `previous` and `current` date values.
*/
private onFirstViewActiveDateChange;
/**
* Handles the event when the active date of the second calendar view changes.
*
* @param activeDate - Object containing `previous` and `current` date values.
*/
private onSecondViewActiveDateChange;
/**
* Handles the "next" navigation event for the first calendar view.
*
* @param currDate - The currently active date in the first calendar view.
* @param force - Optional flag that can be used to enforce updates (not used in current logic).
*/
private handleFirstViewNextEvent;
/**
* Handles the "previous" navigation event for the first calendar view.
*
* @param activeDate - Object containing `previous` and `current` date values.
*/
private handleFirstViewPrevEvent;
/**
* Checks whether the previous date is greater than the current date.
*
* @param activeDate - Object containing `previous` and `current` date values.
* @returns `true` if the previous date is later than the current date, otherwise `false`.
*/
private isPrevious;
/**
* Attaches hover events to all date cells in the first view.
*/
private attachHoverEvent;
/**
* Removes active focus from the second view.
*
* @param classRef - Reference to this component
*/
private removeDefaultFocus;
/**
* Updates the selection range dynamically on hover.
*
* @param date - Hovered date
*/
private updateSelectionOnMouseHover;
/**
* Attaches hover events to given nodes to update range selection.
*
* @param nodes - Date cell nodes
*/
private addHoverEvents;
static ɵfac: i0.ɵɵFactoryDeclaration<CalendarComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<CalendarComponent, "lib-calendar", never, { "minDate": { "alias": "minDate"; "required": false; }; "maxDate": { "alias": "maxDate"; "required": false; }; "selectedDates": { "alias": "selectedDates"; "required": false; }; }, { "selectedDatesChange": "selectedDatesChange"; }, never, never, false, never>;
}
/**
* @(#)date-filter-enum.ts Sept 08, 2023
*
* @author Aakash Kumar
*/
declare const ACTIVE_DATE_DEBOUNCE = 100;
declare enum DATE_OPTION_TYPE {
DATE_DIFF = 1,
LAST_MONTH = 2,
THIS_MONTH = 3,
YEAR_TO_DATE = 4,
CUSTOM = 5,
MONTH_TO_DATE = 6,
WEEK_TO_DATE = 7
}
/**
* @(#)select-date-option.ts Sept 08, 2023
*
* Defines the structure and behavior of a selectable date option,
* used in date filtering components.
*
* @author Aakash Kumar
*/
interface ISelectDateOption {
/**
* Label displayed in the drop-down list for this option.
* Example: "Last 7 Days", "Today", "Custom".
*/
optionLabel: string;
/**
* Type of the option, indicating how the date is determined.
* Defaults to DATE_DIFF if not provided.
*/
optionType?: DATE_OPTION_TYPE;
/**
* Number of days offset from today.
*
* - Positive numbers indicate future dates.
* - Negative numbers indicate past dates.
* - Used only when optionType is DATE_DIFF and no callback is provided.
*
* Example: -7 → "Last 7 Days"
*/
dateDiff?: number;
/**
* Whether this option is currently selected.
*/
isSelected: boolean;
/**
* Whether this option should be shown in the drop-down list.
*/
isVisible: boolean;
/**
* Custom function to calculate and return a DateRange.
* Used when optionType requires special handling beyond dateDiff.
*/
callBackFunction?: () => DateRange<Date>;
/**
* Optional date-math/relative expression shown for the range start when
* editable inputs are enabled (e.g. `now-7d`). Overrides the value derived
* from `dateDiff`. Must be paired with {@link endExpr}.
*/
startExpr?: string;
/**
* Optional date-math/relative expression shown for the range end when
* editable inputs are enabled (e.g. `now`). Must be paired with
* {@link startExpr}.
*/
endExpr?: string;
}
/**
* Default implementation of a selectable date option.
* Provides default values for all fields.
*/
declare class SelectDateOption implements ISelectDateOption {
optionLabel: string;
optionType: DATE_OPTION_TYPE;
dateDiff: number;
isSelected: boolean;
isVisible: boolean;
callBackFunction: () => DateRange<Date>;
}
/**
* @(#)ng-date-picker.component.ts Sept 05, 2023
*
* @author Aakash Kumar
*/
declare class NgDatePickerComponent implements OnInit, AfterViewInit {
isDateOptionList: boolean;
isCustomRange: boolean;
inputLabel: string;
staticOptionId: string;
dynamicOptionId: string;
calendarId: string;
enableDefaultOptions: boolean;
selectedDates: DateRange<Date> | null;
dateFormat: string;
isShowStaticDefaultOptions: boolean;
hideDefaultOptions: boolean;
cdkConnectedOverlayOffsetX: number;
cdkConnectedOverlayOffsetY: number;
listCdkConnectedOverlayOffsetY: number;
listCdkConnectedOverlayOffsetX: number;
selectedOptionIndex: number;
displaySelectedLabel: boolean;
/**
* When true, the main input shows the human-readable expressions
* (e.g. `now-7d - now`) instead of the absolute date range. If
* `displaySelectedLabel` is also true, the label takes priority.
*/
displaySelectedExpression: boolean;
/**
* When true, the custom-range footer shows two editable Material inputs
* (start / end) that accept dates in `dateFormat`, ISO 8601 durations
* (`p7d`), or date math (`now-7d`). When false, a read-only label is shown.
*/
enableEditableDates: boolean;
cdkConnectedOverlayPush: boolean;
cdkConnectedOverlayPositions: never[];
allowSingleDateSelection: boolean;
/**
* When true, automatically selects the preset option whose computed date range
* matches the provided selectedDates (works with both default and custom options).
* Falls back to "Custom Range" if no option matches.
*/
autoSelectOption: boolean;
minDate: Date;
maxDate: Date;
onDateSelectionChanged: EventEmitter<SelectedDateEvent>;
dateListOptions: EventEmitter<ISelectDateOption[]>;
private cdref;
private el;
private _dateOptions;
visibleOptions: Signal<ISelectDateOption[]>;
/**
* Reactive form backing the editable start/end inputs. Each control accepts
* a `dateFormat` date, an ISO 8601 duration, or a date-math expression; the
* group is invalid when either value is unparseable or start is after end.
*/
editableForm: FormGroup<{
start: FormControl<string>;
end: FormControl<string>;
}>;
private editableExpr;
constructor();
set dateDropDownOptions(defaultDateList: ISelectDateOption[]);
get dateDropDownOptions(): ISelectDateOption[];
ngOnInit(): void;
ngAfterViewInit(): void;
/**
* Toggles the visibility of the default date option list.
* If the custom range panel is open, closes it instead.
*
* @param event Optional MouseEvent triggering the toggle.
*/
toggleDateOptionSelectionList(event?: MouseEvent): void;
/**
* Updates the custom date range selection from the input.
*
* @param input The HTML input element associated with the date picker.
* @param selectedDates The selected date range.
*/
updateCustomRange(input: HTMLInputElement, selectedDates: DateRange<Date> | null): void;
/**
* Updates the selection when a specific date option is clicked.
*
* @param option The selected date option.
* @param input The HTML input element to update with selected dates.
*/
updateSelection(option: ISelectDateOption, input: HTMLInputElement): void;
/**
* Re-emits the options signal after an in-place selection change so the
* OnPush views (bound to the `visibleOptions` computed) reliably reflect the
* new `isSelected` state - the same notification the initial signal `set`
* provides.
*/
private syncOptionSelection;
/**
* Toggles the custom date range selection view visibility.
*/
toggleCustomDateRangeView(): void;
/**
* Parses a single editable input value, accepting either a `dateFormat`
* date or one of the human formats (ISO 8601 duration, date math).
*
* @param value - The raw input string.
* @returns The parsed Date, or `null` if it cannot be parsed.
*/
private parseInputValue;
/**
* Validator for a single editable date control: valid when the value parses
* to a date. Empty values are left to the `required` validator.
*/
private validateDateControl;
/**
* Group validator ensuring the parsed start date is not after the end date.
*/
private validateRange;
/**
* Commits the editable inputs to the calendar so the views and the Apply
* action reflect the typed values. No-op when editing is disabled or the
* form is invalid.
*
* @param calendar - The calendar component instance from the template.
*/
commitEditableDates(calendar: CalendarComponent): void;
/**
* Reflects a calendar (date-click) selection in the editable inputs as
* absolute dates. A calendar pick is an explicit absolute selection, so any
* remembered expression is cleared and the inputs show formatted dates.
*
* @param range - The range emitted by the calendar.
*/
onCalendarSelectionChange(range: DateRange<Date>): void;
/**
* Commits the editable inputs and applies the range, closing the panel -
* the same as clicking Apply. Used for the Enter key. No-op when editing is
* disabled or the form is invalid, so Enter never closes with bad input.
*
* @param input - The main date input element to update.
* @param calendar - The calendar component instance from the template.
*/
applyEditableDates(input: HTMLInputElement, calendar: CalendarComponent): void;
/**
* Pre-fills the editable inputs from the current selection: relative
* expressions for a day-diff option (e.g. `now-7d` .. `now`), otherwise the
* absolute formatted dates.
*/
private populateEditableForm;
/**
* Resolves the human-readable start/end expressions for a range. Prefers the
* user's own committed expression (when it still resolves to this range),
* then the relative form of a day-diff option, and finally the absolute
* formatted dates. Shared by the editable inputs and the emitted event.
*
* @param start - Range start date.
* @param end - Range end date.
* @param opt - The associated date option, if any.
* @returns The start and end expression strings.
*/
private resolveDisplayExpr;
/**
* Checks whether a saved expression still resolves (to day precision) to the
* given dates, so a stale expression is not reused after the range changed
* by other means.
*/
private exprMatchesDates;
/**
* Clears the currently selected dates and resets all related properties.
*
* @param event The MouseEvent triggering the clear action.
*/
clearSelection(event: MouseEvent): void;
/**
* Clears the input field value for the date picker.
*/
private clearDateInput;
/**
* Updates selected dates based on a selected option and input element.
*
* @param option The selected date option.
* @param input The HTML input element to update.
*/
private updateDateOnOptionSelect;
/**
* Calculates and updates the start and end dates based on the selected option.
*
* @param option The selected date option.
* @param input The HTML input element to update.
*/
private updateDateWithSelectedOption;
/**
* Updates the date range and input display.
*
* @param input The HTML input element.
* @param start Start date of the range.
* @param end End date of the range.
* @param opt Optional selected date option.
*/
private updateSelectedDates;
/**
* Updates the input and internal state with default dates on initialization.
* When autoSelectOption is true and selectedDates is provided, attempts to
* match against existing options before falling back to Custom Range.
*/
private updateDefaultDatesValues;
/**
* Iterates over all non-custom options and returns the first one whose
* computed date range matches the provided selectedDates (day-level comparison).
* Works for both default options and consumer-provided options with callBackFunction.
*
* @param selectedDates The date range to match against
* @returns The matching ISelectDateOption, or null if none found
*/
private findMatchingOption;
/**
* Updates the input and selected dates based on a selected option from the list.
*
* @param selectedOption The selected date option.
* @param input The HTML input element to update.
*/
private updatedFromListValueSelection;
/**
* Checks whether default initialization of options is required.
*
* @returns True if default options need to be initialized, otherwise false.
*/
private isDefaultInitRequired;
/**
* Initializes the default date options with the selected index.
*/
private initDefaultOptions;
static ɵfac: i0.ɵɵFactoryDeclaration<NgDatePickerComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<NgDatePickerComponent, "ng-date-range-picker", never, { "inputLabel": { "alias": "inputLabel"; "required": false; }; "staticOptionId": { "alias": "staticOptionId"; "required": false; }; "dynamicOptionId": { "alias": "dynamicOptionId"; "required": false; }; "calendarId": { "alias": "calendarId"; "required": false; }; "enableDefaultOptions": { "alias": "enableDefaultOptions"; "required": false; }; "selectedDates": { "alias": "selectedDates"; "required": false; }; "dateFormat": { "alias": "dateFormat"; "required": false; }; "isShowStaticDefaultOptions": { "alias": "isShowStaticDefaultOptions"; "required": false; }; "hideDefaultOptions": { "alias": "hideDefaultOptions"; "required": false; }; "cdkConnectedOverlayOffsetX": { "alias": "cdkConnectedOverlayOffsetX"; "required": false; }; "cdkConnectedOverlayOffsetY": { "alias": "cdkConnectedOverlayOffsetY"; "required": false; }; "listCdkConnectedOverlayOffsetY": { "alias": "listCdkConnectedOverlayOffsetY"; "required": false; }; "listCdkConnectedOverlayOffsetX": { "alias": "listCdkConnectedOverlayOffsetX"; "required": false; }; "selectedOptionIndex": { "alias": "selectedOptionIndex"; "required": false; }; "displaySelectedLabel": { "alias": "displaySelectedLabel"; "required": false; }; "displaySelectedExpression": { "alias": "displaySelectedExpression"; "required": false; }; "enableEditableDates": { "alias": "enableEditableDates"; "required": false; }; "cdkConnectedOverlayPush": { "alias": "cdkConnectedOverlayPush"; "required": false; }; "cdkConnectedOverlayPositions": { "alias": "cdkConnectedOverlayPositions"; "required": false; }; "allowSingleDateSelection": { "alias": "allowSingleDateSelection"; "required": false; }; "autoSelectOption": { "alias": "autoSelectOption"; "required": false; }; "minDate": { "alias": "minDate"; "required": false; }; "maxDate": { "alias": "maxDate"; "required": false; }; "dateDropDownOptions": { "alias": "dateDropDownOptions"; "required": false; }; }, { "onDateSelectionChanged": "onDateSelectionChanged"; "dateListOptions": "dateListOptions"; }, never, never, false, never>;
}
declare class NgDatePickerModule {
static ɵfac: i0.ɵɵFactoryDeclaration<NgDatePickerModule, never>;
static ɵmod: i0.ɵɵNgModuleDeclaration<NgDatePickerModule, [typeof NgDatePickerComponent, typeof CalendarComponent], [typeof i3.CommonModule, typeof i4.FormsModule, typeof i4.ReactiveFormsModule, typeof i5.MatDatepickerModule, typeof i6.MatNativeDateModule, typeof i7.MatInputModule, typeof i8.MatAutocompleteModule, typeof i9.OverlayModule, typeof i10.MatIconModule, typeof i11.MatButtonModule, typeof i12.MatListModule, typeof i13.MatFormFieldModule, typeof i14.MatTooltipModule], [typeof NgDatePickerComponent]>;
static ɵinj: i0.ɵɵInjectorDeclaration<NgDatePickerModule>;
}
interface SelectedDateEvent {
range: DateRange<Date> | null;
selectedOption: ISelectDateOption | null;
/**
* Human-readable expression for the range start: the user's own input (e.g.
* `now-7d`) when editing, the relative form of a day-diff option, otherwise
* the absolute formatted date. `null` when the selection is cleared.
*/
startExpr: string | null;
/** Human-readable expression for the range end. See {@link startExpr}. */
endExpr: string | null;
}
/**
* Human-readable timedelta / date parsing utilities.
*
* Three independent parsers plus a public entry point that combines them:
* 1. {@link parseIso8601Duration} - ISO 8601 durations (`P7D`, `PT1H30M`),
* strict uppercase as required by the spec.
* 2. {@link parseDateMath} - Grafana/Elasticsearch style date math (`now-7d`).
* 3. {@link parseNaturalLanguage} - natural language (`7 days ago`) via a
* parser the host app registers with {@link setNaturalLanguageParser}
* (typically `chrono-node`). No parser registered means this step is a
* no-op, so the library never depends on `chrono-node` directly.
*
* {@link parseHumanDate} tries all three and accepts lowercase ISO durations.
*/
/**
* A calendar duration parsed from an ISO 8601 duration string.
* Each field defaults to 0 when its component is absent.
*/
interface Duration {
years: number;
months: number;
weeks: number;
days: number;
hours: number;
minutes: number;
seconds: number;
}
/**
* Options for {@link parseHumanDate}.
*/
interface ParseHumanDateOptions {
/** Reference "now" used to resolve relative expressions. Defaults to `new Date()`. */
base?: Date;
/**
* Direction applied to a bare ISO 8601 duration: `-1` resolves it to the
* past (`base - duration`, e.g. "last 7 days"), `1` to the future.
* Defaults to `-1` to match this picker's "Last N days" vocabulary.
*/
durationSign?: 1 | -1;
/**
* Whether to fall back to the registered natural-language parser.
* Defaults to `true`. Has no effect if no parser was registered.
*/
useNaturalLanguage?: boolean;
}
/**
* Parses a strict, uppercase ISO 8601 duration string into a {@link Duration}.
*
* Spec-compliant: designators must be uppercase, so `P7D` parses but `p7d`
* does not. Use {@link parseHumanDate} if you need lenient (lowercase) input.
*
* @param input - Candidate ISO 8601 duration, e.g. `P1Y2M10DT2H30M`.
* @returns The parsed duration, or `null` if the string is not a valid duration.
*/
declare function parseIso8601Duration(input: string): Duration | null;
/**
* Applies a {@link Duration} to a base date, returning a new Date.
*
* Calendar units (years, months, weeks, days) use Date setters and are
* therefore truncated to integers; sub-day units (hours, minutes, seconds)
* are applied as milliseconds and preserve fractional values.
*
* @param base - The date to offset from.
* @param duration - The duration to apply.
* @param sign - `1` to add (future), `-1` to subtract (past). Defaults to `1`.
* @returns A new Date offset from `base`.
*/
declare function addDuration(base: Date, duration: Duration, sign?: 1 | -1): Date;
/**
* Parses a Grafana/Elasticsearch style date-math expression into a Date.
*
* Supports `now` optionally followed by `±N<unit>` operations applied left to
* right, e.g. `now`, `now-7d`, `now-1M+15d`. Units: `y M w d h m s`
* (note `M` = month, `m` = minute). Snapping (`/d`) is not supported.
*
* @param input - The date-math expression.
* @param base - Reference "now". Defaults to `new Date()`.
* @returns The resolved Date, or `null` if the expression is not date math.
*/
declare function parseDateMath(input: string, base?: Date): Date | null;
/**
* Signature of a natural-language date parser, matching `chrono-node`'s
* `parseDate(text, ref)` export.
*/
type NaturalLanguageParser = (text: string, ref?: Date) => Date | null;
/**
* Registers a natural-language parser (typically `chrono-node`'s `parseDate`)
* for {@link parseNaturalLanguage} / {@link parseHumanDate} to use.
*
* The consumer imports the package themselves, so their bundler resolves it
* and this library never references it directly. Call with `null` to disable.
*
* @example
* import * as chrono from 'chrono-node';
* setNaturalLanguageParser((text, ref) => chrono.parseDate(text, ref));
*
* @param parser - The parser to use, or `null` to disable.
*/
declare function setNaturalLanguageParser(parser: NaturalLanguageParser | null): void;
/**
* Parses natural language (`7 days ago`, `next friday`) using the parser
* registered via {@link setNaturalLanguageParser}.
*
* @param input - The natural-language date expression.
* @param base - Reference date the parser resolves against. Defaults to `new Date()`.
* @returns The parsed Date, or `null` if no parser is registered or the text
* could not be parsed.
*/
declare function parseNaturalLanguage(input: string, base?: Date): Date | null;
/**
* Public entry point: parses a human-readable date/duration expression into a
* concrete Date by trying, in order, date math, ISO 8601 duration, then
* natural language via the registered parser.
*
* Unlike {@link parseIso8601Duration}, this accepts lowercase ISO durations
* (`p7d`) by upper-casing the input before the ISO attempt.
*
* @param input - The expression, e.g. `now-7d`, `P7D`, `p7d`, `3 weeks ago`.
* @param options - See {@link ParseHumanDateOptions}.
* @returns The parsed Date, or `null` if nothing matched.
*/
declare function parseHumanDate(input: string, options?: ParseHumanDateOptions): Date | null;
export { ACTIVE_DATE_DEBOUNCE, DATE_OPTION_TYPE, NgDatePickerComponent, NgDatePickerModule, SelectDateOption, addDuration, parseDateMath, parseHumanDate, parseIso8601Duration, parseNaturalLanguage, setNaturalLanguageParser };
export type { Duration, ISelectDateOption, NaturalLanguageParser, ParseHumanDateOptions, SelectedDateEvent };