Documentation
Complete guide to installing, configuring, and using FlexibleDatePicker in Angular applications.
Introduction
FlexibleDatePicker is an Angular 20+ date and time picker library built around headless selection engines and composable UI components. It uses date-fns for formatting and calendar math, ships with light/dark theming via CSS variables, and implements the Control Value Accessor (CVA) pattern for seamless reactive forms and template-driven forms integration.
Source code and releases: GitHub repository · npm package
All public pickers use the fdp-* selector prefix:
| Selector | Purpose |
|---|---|
fdp-date-picker | Single date selection |
fdp-date-range-picker | Date range with presets |
fdp-time-picker | Single time (roller wheel) |
fdp-time-range-picker | Start/end time range |
fdp-month-picker | Month selection |
fdp-month-range-picker | Month range |
fdp-year-picker | Year selection |
fdp-year-range-picker | Year range |
Features
See the full Features page for an overview of every capability, picker component, and developer experience highlight.
- Eight picker components covering date, time, month, and year — single and range modes
- Headless engines for custom UI or testing without the DOM
- Roller/wheel time selection with infinite loop scrolling (23 → 0 → 1)
- Optional inline time on date and date-range pickers
- Preset shortcut sidebar for date ranges (Last 7 days, This month, etc.)
- Responsive dual-calendar layout for range selection
- Min/max bounds, custom disabled dates, and weekend blocking
- Calendar and clock icons, configurable placeholders and formats
- Light/dark/auto themes, per-picker
colorScheme, and brand colors viacustomColors - Locale support and RTL layout via
FlexLocaleService - Popover overlay with focus trap, escape to close, and outside-click dismiss
- OnPush change detection and signal-based Angular APIs
Installation
Install from npm and its peer dependency:
npm install @manidev/ngx-flexible-date-picker date-fnsImport styles in your global stylesheet (required):
@import '@manidev/ngx-flexible-date-picker/themes/flexible-date-picker.css';Quick start
Import a picker as a standalone component and bind it to a form control:
import { Component } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { FlexDatePickerComponent } from '@manidev/ngx-flexible-date-picker';
@Component({
selector: 'app-demo',
imports: [ReactiveFormsModule, FlexDatePickerComponent],
template: `
<fdp-date-picker
[formControl]="dateControl"
placeholder="Select date"
dateFormat="MMM d, yyyy"
[showIcon]="true"
/>
`,
})
export class DemoComponent {
dateControl = new FormControl<Date | null>(null);
}Template-driven forms work the same way with [(ngModel)].
Styling & theming
The library uses CSS custom properties defined in flexible-date-picker-base.css. You can theme globally with FlexThemeService, per picker with colorScheme, or with partial brand overrides via customColors. Try the live examples — the last card demonstrates all three approaches.
Global theme
Apply light, dark, or system-aware mode on <html>:
import { FlexThemeService } from '@manidev/ngx-flexible-date-picker';
constructor(private theme: FlexThemeService) {}
enableDarkMode() {
this.theme.setDarkMode(true);
}
useSystemTheme() {
this.theme.setColorScheme('auto');
}setColorScheme('auto') follows prefers-color-scheme. applyCustomColors() sets inline overrides on the document root; clearCustomColors() removes them.
this.theme.setColorScheme('light');
this.theme.applyCustomColors({
primary: '#7c3aed',
surface: '#faf5ff',
});
// this.theme.clearCustomColors();Per-picker colorScheme
Every fdp-* picker accepts an optional colorScheme input: 'light', 'dark', or 'auto'. When set, the picker root gets data-flex-theme so it can differ from the page (e.g. a dark picker on a light page). Omit the input to inherit the document palette.
<fdp-date-picker colorScheme="dark" placeholder="Select date" />Custom colors (customColors)
Pass a partial FlexThemeTokens object to override specific CSS variables on that picker only. Combine with colorScheme for a built-in base plus brand accents — custom values win for the properties you set.
<fdp-date-picker
placeholder="Select date"
[customColors]="{
primary: '#be123c',
primaryForeground: '#ffffff',
range: '#fecdd3',
radius: '0.5rem'
}"
/>interface FlexThemeTokens {
surface?: string;
surfaceElevated?: string;
border?: string;
primary?: string;
primaryForeground?: string;
muted?: string;
mutedForeground?: string;
accent?: string;
accentForeground?: string;
range?: string;
today?: string;
disabled?: string;
radius?: string;
shadow?: string;
}CSS variables
| Token field | CSS variable | Description |
|---|---|---|
surface | --flex-surface | Background for popover panels, inputs, and elevated surfaces. |
surfaceElevated | --flex-surface-elevated | Secondary surface (e.g. nested panels). |
primary | --flex-primary | Selected days, primary buttons, focus rings, active states. |
primaryForeground | --flex-primary-foreground | Text/icon on primary backgrounds. |
border | --flex-border | Borders and dividers. |
muted | --flex-muted | Hover and subtle fill backgrounds. |
mutedForeground | --flex-muted-foreground | Secondary text, weekday headers, inactive drum values. |
accent | --flex-accent | Accent surface (presets, highlights). |
accentForeground | --flex-accent-foreground | Text on accent surfaces. |
range | --flex-range | In-range highlight between start and end in range pickers. |
today | --flex-today | Today indicator background. |
disabled | --flex-disabled | Disabled day/cell text color. |
radius | --flex-radius | Base border radius for panels, buttons, and inputs. |
shadow | --flex-shadow | Popover box shadow. |
Override any variable in your own CSS as well. The .dark class or data-flex-theme="dark" on <html> activates the dark palette globally.
Components overview
Every picker implements ControlValueAccessor and supports disabled via input or form control state. Outputs emit when the committed value changes (on selection or OK for time pickers).
All pickers share optional colorScheme ('light' | 'dark' | 'auto') and customColors (FlexThemeTokens) inputs for per-instance theming — see Styling & theming.
Date picker
Selector:fdp-date-picker
Value type:Date | null
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select date' | Trigger label when no date is selected. Any string; shown in the closed input. |
dateFormat | string | 'MMM d, yyyy' | date-fns format token for the trigger display. Examples: 'yyyy-MM-dd', 'PP', 'EEEE, MMM d'. See the date-fns format docs. |
min | Date | null | null | Earliest selectable calendar day (inclusive). Days before this are disabled. Use null for no lower bound. |
max | Date | null | null | Latest selectable calendar day (inclusive). Days after this are disabled. Use null for no upper bound. |
isDateDisabled | (date: Date) => boolean | — | Optional callback to disable individual dates. Return true to block a day (e.g. weekends: date.getDay() === 0 || date.getDay() === 6). Runs in addition to min/max. |
time | FlexTimeConfig | {} | Inline time drum config. Set enabled: true to show hour/minute rollers after picking a date. Supports format, hourStep, minuteStep, use24Hour, showSeconds, and defaultTime. |
disabled | boolean | false | When true, the trigger button is non-interactive. Also respects reactive form disabled state. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon on the trigger. |
colorScheme | 'light' | 'dark' | 'auto' | — | Per-picker light/dark/system theme. Sets data-flex-theme on the picker root. Omit to inherit the document theme from <html>. |
customColors | FlexThemeTokens | — | Partial palette overrides applied as --flex-* CSS variables on this picker. Combine with colorScheme to start from a preset and override brand colors (e.g. primary, range). |
Output:dateChange — emits Date | null
When time.enabled is true, the popover stays open after date selection so the user can adjust time. The popover closes on outside click or Escape.
<fdp-date-picker
[formControl]="date"
dateFormat="MMM d, yyyy"
[time]="{ enabled: true, format: 'HH:mm', showSeconds: false }"
/>Date range picker
Selector:fdp-date-range-picker
Value type:{ start: Date | null; end: Date | null }
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select date range' | Trigger label when start or end is unset. Any string. |
dateFormat | string | 'MMM d, yyyy' | date-fns format for both range endpoints in the trigger. Examples: 'MMM d, yyyy', 'yyyy-MM-dd', 'PP'. |
min / max | Date | null | null | Inclusive bounds applied to both start and end selection. null means no bound. Individual days outside the range are not selectable. |
isDateDisabled | (date: Date) => boolean | — | Optional per-day disable callback. Return true to block a date from either end of the range. Combined with min/max constraints. |
presetSidebar | FlexPresetSidebarConfig | {} | Shortcut sidebar config. enabled: true (default) or false. presets: custom PresetRange[], omit for built-ins (Today, Yesterday, Last 7 Days, Last 30 Days, This Month, Previous Month, This Year), or pass [] to hide all presets. |
calendarLayout | FlexDateRangeCalendarConfig | { mode: 'auto' } | Number of month panels. mode values: 'auto' — two months on desktop, one on mobile (default); 'single' — always one month; 'double' — always two consecutive months. |
time | FlexTimeConfig | {} | Optional start/end time drums shown below the calendars when enabled: true. Same options as single date picker time config; applied separately to range start and end. |
disabled | boolean | false | Disables the trigger and popover when true. Honors form control disabled state. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon on the trigger. |
Output:rangeChange
Includes Apply/Cancel action bar. Range is committed on Apply.
Time pickers
Time picker — fdp-time-picker
Value type:Date | null (time stored on a reference date)
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select time' | Trigger label when no time is set. Any string. |
timeFormat | string | 'HH:mm' | date-fns format for the trigger. Common values: 'HH:mm' (24h), 'h:mm a' (12h with AM/PM), 'HH:mm:ss' when seconds are enabled. |
hourStep | number | 1 | Increment between hour options in the roller. Positive integer (e.g. 1, 2, 6). |
minuteStep | number | 1 | Increment between minute options. Common values: 1, 5, 15, 30. |
secondStep | number | 1 | Increment for the seconds column when showSeconds is true. |
use24Hour | boolean | true | true — 0–23 hour drum (default). false — 1–12 hour drum plus AM/PM column. |
showSeconds | boolean | false | true adds a third roller column for seconds. false (default) shows hours and minutes only. |
disabled | boolean | false | Disables the trigger when true. Respects form control disabled state. |
showIcon | boolean | true | Show (true) or hide (false) the clock icon on the trigger. |
Output:timeChange
Time range picker — fdp-time-range-picker
Value type:TimeRange — { start: Date | null; end: Date | null }
Accepts the same inputs as fdp-time-picker (defaults shown above), plus placeholder defaulting to 'Select time range'. Start and end rollers appear side by side; OK commits the range, Cancel reverts.
Output:rangeChange
Roller wheel behavior
- Three visible rows: previous value, selected value, next value
- Infinite loop — hour 1 shows 23 above and 2 below
- Scroll or tap to change; OK commits, Cancel reverts draft
Month pickers
Month picker — fdp-month-picker
Value type:Date | null (normalized to first of month)
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select month' | Trigger label when no month is selected. |
monthFormat | string | 'MMM yyyy' | date-fns format for the selected month. Examples: 'MMM yyyy', 'MMMM yyyy', 'MM/yyyy'. |
min / max | Date | null | null | Inclusive month bounds (normalized to month start). Months outside the range are disabled. null for no bound. |
disabled | boolean | false | Disables the trigger when true. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon. |
Output:monthChange
Month range picker — fdp-month-range-picker
Value type:DateRange — months normalized to the first day of each selected month.
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select month range' | Trigger label when the range is incomplete. |
monthFormat | string | 'MMM yyyy' | date-fns format for both range endpoints in the trigger. |
min / max | Date | null | null | Inclusive month bounds for start and end selection. null for no bound. |
disabled | boolean | false | Disables the trigger when true. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon. |
Output:rangeChange
Year pickers
Year picker — fdp-year-picker
Value type:Date | null (normalized to January 1 of the selected year)
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select year' | Trigger label when no year is selected. |
yearFormat | string | 'yyyy' | date-fns format for the trigger. Typically 'yyyy'; also supports 'yy'. |
min / max | Date | null | null | Inclusive year bounds (normalized to Jan 1). Years outside the range are disabled. |
disabled | boolean | false | Disables the trigger when true. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon. |
Output:yearChange
Year range picker — fdp-year-range-picker
Value type:DateRange — years normalized to January 1.
| Input | Type | Default | Description |
|---|---|---|---|
placeholder | string | 'Select year range' | Trigger label when the range is incomplete. |
yearFormat | string | 'yyyy' | date-fns format for both endpoints in the trigger. |
min / max | Date | null | null | Inclusive year bounds for start and end. null for no bound. |
disabled | boolean | false | Disables the trigger when true. |
showIcon | boolean | true | Show (true) or hide (false) the calendar icon. |
Output:rangeChange
Shared configuration
FlexTimeConfig
Used by fdp-date-picker and fdp-date-range-picker via the time input:
interface FlexTimeConfig {
enabled?: boolean; // default false
format?: string; // default 'HH:mm'
minuteStep?: number; // default 1
hourStep?: number; // default 1
defaultTime?: { hours: number; minutes: number; seconds?: number };
use24Hour?: boolean; // default true
showSeconds?: boolean; // default false
}FlexPresetSidebarConfig
interface FlexPresetSidebarConfig {
enabled?: boolean; // default true
presets?: PresetRange[]; // built-in defaults when omitted
}
interface PresetRange {
id: string;
label: string;
getRange: (referenceDate?: Date) => DateRange;
}FlexDateRangeCalendarConfig
interface FlexDateRangeCalendarConfig {
mode?: 'single' | 'double' | 'auto'; // default 'auto'
}auto— two months on desktop, one on mobilesingle— always one calendardouble— always two consecutive months
FlexThemeTokens & FlexColorScheme
FlexColorScheme is 'light' | 'dark' | 'auto'. Use it on any picker’s colorScheme input or with FlexThemeService.setColorScheme(). FlexThemeTokens is a partial map of palette fields to CSS color/length values for the customColors input and applyCustomColors().
interface FlexThemeTokens {
surface?: string;
surfaceElevated?: string;
border?: string;
primary?: string;
primaryForeground?: string;
muted?: string;
mutedForeground?: string;
accent?: string;
accentForeground?: string;
range?: string;
today?: string;
disabled?: string;
radius?: string;
shadow?: string;
} The same colorScheme and customColors inputs are available on every fdp-* picker component.
Forms integration
All pickers register as NG_VALUE_ACCESSOR providers.
Reactive forms
readonly range = new FormControl<DateRange>({
start: null,
end: null,
});
<fdp-date-range-picker [formControl]="range" />Template-driven
<fdp-date-picker [(ngModel)]="selectedDate" name="date" />Validation
Use standard Angular validators on the form control. The date picker reactive example in the playground uses Validators.required.
Locale & RTL
import { FlexLocaleService } from '@manidev/ngx-flexible-date-picker';
constructor(private locale: FlexLocaleService) {}
setFrench() {
this.locale.setLocale('fr');
}
setArabic() {
this.locale.setLocale('ar');
document.documentElement.dir = 'rtl';
} Weekday labels and calendar layout respect the configured locale. Set dir="rtl" on <html> for right-to-left trigger alignment.
Headless engines
Build custom UIs or unit-test selection logic without rendering components. Engines live under @manidev/ngx-flexible-date-picker public API:
createDatePickerEngine()createDateRangePickerEngine()createTimePickerEngine()createTimeRangePickerEngine()createMonthPickerEngine()createMonthRangePickerEngine()createYearPickerEngine()createYearRangePickerEngine()
Each engine exposes state, actions, and selectors for calendar grids, validation, and open/close lifecycle.
import { createDatePickerEngine } from '@manidev/ngx-flexible-date-picker';
const engine = createDatePickerEngine({ weekStartsOn: 1 });
engine.actions.open();
engine.actions.selectDate(new Date(2026, 4, 13));
console.log(engine.state.value);Services
| Service | Purpose |
|---|---|
FlexThemeService | Global theming on <html>: setColorScheme('light' | 'dark' | 'auto'), setDarkMode(), toggleDarkMode(), getColorScheme(), isDarkMode(), applyCustomColors(tokens), and clearCustomColors(). |
FlexLocaleService | Set active locale with setLocale(code). Supported codes include 'en', 'fr', 'de', 'ar'. Controls weekday labels and week start day via weekStartsOn() (0 = Sunday, 1 = Monday). |
FlexOverlayService | Manages popover placement (above/below anchor), focus trap, outside-click dismiss, and mobile bottom-sheet layout. Used internally by picker components. |
PickerEngineBridgeService | Signal bridge syncing headless engine state with component UI. Useful when building custom picker shells on top of the engines. |
Accessibility
- Trigger buttons expose
aria-expandedandaria-haspopup="dialog" - Popover panels use
role="dialog"with accessible names - Calendar grids use semantic day buttons; time drums use
role="listbox" - Keyboard: Escape closes popover; Tab is trapped inside open dialogs
- Focus returns to logical targets on dismiss
API reference
Full public exports from @manidev/ngx-flexible-date-picker:
Components
FlexDatePickerComponent
FlexDateRangePickerComponent
FlexTimePickerComponent
FlexTimeRangePickerComponent
FlexMonthPickerComponent
FlexMonthRangePickerComponent
FlexYearPickerComponent
FlexYearRangePickerComponentTypes & models
DateRange, TimeRange, FlexTimeConfig
FlexPresetSidebarConfig, FlexDateRangeCalendarConfig
FlexColorScheme, FlexThemeTokens
PresetRange, CalendarMonth, CalendarDay
Granularity, WeekStart, LocaleCodeUtilities
normalizeDate, mergeDateAndTime, getTimeParts
generateHourOptions, generateMinuteOptions
getWeekdayLabels, buildLoopedOptions