@oneluiz/dual-datepicker 3.5.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/core/built-in-presets.d.ts +98 -0
  2. package/core/calendar-grid/calendar-grid.cache.d.ts +39 -0
  3. package/core/calendar-grid/calendar-grid.factory.d.ts +26 -0
  4. package/core/calendar-grid/calendar-grid.types.d.ts +57 -0
  5. package/core/calendar-grid/index.d.ts +50 -0
  6. package/core/calendar-grid/range-highlighter.cache.d.ts +105 -0
  7. package/core/calendar-grid/range-highlighter.d.ts +85 -0
  8. package/core/calendar-grid/range-highlighter.types.d.ts +182 -0
  9. package/core/calendar-grid/virtual-weeks.logic.d.ts +116 -0
  10. package/core/calendar-grid/virtual-weeks.types.d.ts +71 -0
  11. package/core/index.d.ts +22 -0
  12. package/core/preset-providers.d.ts +176 -0
  13. package/core/preset-registry.d.ts +181 -0
  14. package/core/preset.engine.d.ts +57 -21
  15. package/core/range-preset.plugin.d.ts +188 -0
  16. package/dual-datepicker.component.d.ts +78 -1
  17. package/esm2022/core/built-in-presets.mjs +289 -0
  18. package/esm2022/core/calendar-grid/calendar-grid.cache.mjs +92 -0
  19. package/esm2022/core/calendar-grid/calendar-grid.factory.mjs +97 -0
  20. package/esm2022/core/calendar-grid/calendar-grid.types.mjs +8 -0
  21. package/esm2022/core/calendar-grid/index.mjs +51 -0
  22. package/esm2022/core/calendar-grid/range-highlighter.cache.mjs +198 -0
  23. package/esm2022/core/calendar-grid/range-highlighter.mjs +185 -0
  24. package/esm2022/core/calendar-grid/range-highlighter.types.mjs +11 -0
  25. package/esm2022/core/calendar-grid/virtual-weeks.logic.mjs +149 -0
  26. package/esm2022/core/calendar-grid/virtual-weeks.types.mjs +11 -0
  27. package/esm2022/core/index.mjs +26 -1
  28. package/esm2022/core/preset-providers.mjs +243 -0
  29. package/esm2022/core/preset-registry.mjs +277 -0
  30. package/esm2022/core/preset.engine.mjs +86 -210
  31. package/esm2022/core/range-preset.plugin.mjs +70 -0
  32. package/esm2022/dual-datepicker.component.mjs +202 -39
  33. package/fesm2022/oneluiz-dual-datepicker.mjs +1985 -282
  34. package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
  35. package/package.json +2 -2
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Built-in Date Range Preset Plugins
3
+ *
4
+ * Version: 3.6.0
5
+ *
6
+ * Standard presets provided by the library.
7
+ * All presets use DateClock and DateAdapter for SSR-safety and timezone-safety.
8
+ *
9
+ * PRESETS INCLUDED:
10
+ * - TODAY, YESTERDAY
11
+ * - LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_60_DAYS, LAST_90_DAYS
12
+ * - THIS_WEEK, LAST_WEEK
13
+ * - THIS_MONTH, LAST_MONTH, MONTH_TO_DATE
14
+ * - THIS_QUARTER, LAST_QUARTER, QUARTER_TO_DATE
15
+ * - THIS_YEAR, LAST_YEAR, YEAR_TO_DATE
16
+ */
17
+ import { RangePresetPlugin } from './range-preset.plugin';
18
+ /**
19
+ * TODAY - Current day
20
+ */
21
+ export declare const TODAY_PRESET: RangePresetPlugin;
22
+ /**
23
+ * YESTERDAY - Previous day
24
+ */
25
+ export declare const YESTERDAY_PRESET: RangePresetPlugin;
26
+ /**
27
+ * LAST_7_DAYS - Last 7 days including today
28
+ */
29
+ export declare const LAST_7_DAYS_PRESET: RangePresetPlugin;
30
+ /**
31
+ * LAST_14_DAYS - Last 14 days including today
32
+ */
33
+ export declare const LAST_14_DAYS_PRESET: RangePresetPlugin;
34
+ /**
35
+ * LAST_30_DAYS - Last 30 days including today
36
+ */
37
+ export declare const LAST_30_DAYS_PRESET: RangePresetPlugin;
38
+ /**
39
+ * LAST_60_DAYS - Last 60 days including today
40
+ */
41
+ export declare const LAST_60_DAYS_PRESET: RangePresetPlugin;
42
+ /**
43
+ * LAST_90_DAYS - Last 90 days including today
44
+ */
45
+ export declare const LAST_90_DAYS_PRESET: RangePresetPlugin;
46
+ /**
47
+ * THIS_WEEK - Current week (Monday to Sunday)
48
+ */
49
+ export declare const THIS_WEEK_PRESET: RangePresetPlugin;
50
+ /**
51
+ * LAST_WEEK - Previous week (Monday to Sunday)
52
+ */
53
+ export declare const LAST_WEEK_PRESET: RangePresetPlugin;
54
+ /**
55
+ * THIS_MONTH - Current calendar month (1st to last day)
56
+ */
57
+ export declare const THIS_MONTH_PRESET: RangePresetPlugin;
58
+ /**
59
+ * LAST_MONTH - Previous calendar month
60
+ */
61
+ export declare const LAST_MONTH_PRESET: RangePresetPlugin;
62
+ /**
63
+ * MONTH_TO_DATE - From start of current month to today
64
+ */
65
+ export declare const MONTH_TO_DATE_PRESET: RangePresetPlugin;
66
+ /**
67
+ * THIS_QUARTER - Current quarter (Q1: Jan-Mar, Q2: Apr-Jun, Q3: Jul-Sep, Q4: Oct-Dec)
68
+ */
69
+ export declare const THIS_QUARTER_PRESET: RangePresetPlugin;
70
+ /**
71
+ * LAST_QUARTER - Previous quarter
72
+ */
73
+ export declare const LAST_QUARTER_PRESET: RangePresetPlugin;
74
+ /**
75
+ * QUARTER_TO_DATE - From start of current quarter to today
76
+ */
77
+ export declare const QUARTER_TO_DATE_PRESET: RangePresetPlugin;
78
+ /**
79
+ * THIS_YEAR - Current calendar year (Jan 1 to Dec 31)
80
+ */
81
+ export declare const THIS_YEAR_PRESET: RangePresetPlugin;
82
+ /**
83
+ * LAST_YEAR - Previous calendar year
84
+ */
85
+ export declare const LAST_YEAR_PRESET: RangePresetPlugin;
86
+ /**
87
+ * YEAR_TO_DATE - From start of current year to today
88
+ */
89
+ export declare const YEAR_TO_DATE_PRESET: RangePresetPlugin;
90
+ /**
91
+ * All built-in presets as an array
92
+ *
93
+ * Use this to register all built-in presets at once:
94
+ * ```typescript
95
+ * BUILT_IN_PRESETS.forEach(preset => registry.register(preset));
96
+ * ```
97
+ */
98
+ export declare const BUILT_IN_PRESETS: RangePresetPlugin[];
@@ -0,0 +1,39 @@
1
+ import { CalendarGridFactory } from './calendar-grid.factory';
2
+ import { CalendarGrid } from './calendar-grid.types';
3
+ import * as i0 from "@angular/core";
4
+ export declare class CalendarGridCache {
5
+ private factory;
6
+ private cache;
7
+ private readonly maxSize;
8
+ constructor(factory: CalendarGridFactory);
9
+ /**
10
+ * Get or create a calendar grid
11
+ *
12
+ * @param monthDate - Any date within the target month
13
+ * @param weekStart - First day of week (0 = Sunday, 1 = Monday, etc.)
14
+ * @param locale - Locale identifier (optional)
15
+ * @returns CalendarGrid - cached or newly created
16
+ */
17
+ get(monthDate: Date, weekStart?: number, locale?: string): CalendarGrid;
18
+ /**
19
+ * Build cache key from month parameters
20
+ *
21
+ * Format: "year-month-weekStart-locale"
22
+ * Example: "2026-1-0-en" (Feb 2026, Sunday start, English)
23
+ */
24
+ private buildKey;
25
+ /**
26
+ * Clear entire cache (for testing or manual reset)
27
+ */
28
+ clear(): void;
29
+ /**
30
+ * Get cache size (for debugging/testing)
31
+ */
32
+ size(): number;
33
+ /**
34
+ * Check if a specific month is cached
35
+ */
36
+ has(monthDate: Date, weekStart?: number, locale?: string): boolean;
37
+ static ɵfac: i0.ɵɵFactoryDeclaration<CalendarGridCache, never>;
38
+ static ɵprov: i0.ɵɵInjectableDeclaration<CalendarGridCache>;
39
+ }
@@ -0,0 +1,26 @@
1
+ import { DateAdapter } from '../date-adapter';
2
+ import { CalendarGrid } from './calendar-grid.types';
3
+ import * as i0 from "@angular/core";
4
+ export declare class CalendarGridFactory {
5
+ private adapter;
6
+ constructor(adapter: DateAdapter);
7
+ /**
8
+ * Create a calendar grid for a given month
9
+ *
10
+ * @param monthDate - Any date within the target month (will be normalized to start of month)
11
+ * @param weekStart - First day of week (0 = Sunday, 1 = Monday, etc.)
12
+ * @param locale - Locale identifier (optional, for future use)
13
+ * @returns CalendarGrid - 6 weeks x 7 days grid
14
+ */
15
+ createGrid(monthDate: Date, weekStart?: number, locale?: string): CalendarGrid;
16
+ /**
17
+ * Calculate offset (number of padding days from previous month)
18
+ *
19
+ * @param firstDayOfWeek - Day of week for first day of month (0-6)
20
+ * @param weekStart - Desired week start (0-6)
21
+ * @returns Number of padding days needed
22
+ */
23
+ private calculateOffset;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<CalendarGridFactory, never>;
25
+ static ɵprov: i0.ɵɵInjectableDeclaration<CalendarGridFactory>;
26
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Calendar Grid Types
3
+ *
4
+ * Defines the structure for memoized calendar month grids.
5
+ * Separates base grid structure (cacheable) from decorations (dynamic).
6
+ */
7
+ /**
8
+ * A single calendar cell representing one day
9
+ */
10
+ export interface CalendarCell {
11
+ /** Date object (normalized to start of day) */
12
+ date: Date;
13
+ /** Whether this day belongs to the current rendered month */
14
+ inCurrentMonth: boolean;
15
+ /** ISO string 'YYYY-MM-DD' (timezone-safe via DateAdapter) */
16
+ iso: string;
17
+ /** Day of month (1-31) */
18
+ day: number;
19
+ /** Month (0-11, JavaScript convention) */
20
+ month: number;
21
+ /** Full year */
22
+ year: number;
23
+ /** Day of week (0 = Sunday, 6 = Saturday) */
24
+ dayOfWeek: number;
25
+ }
26
+ /**
27
+ * A calendar grid representing one month
28
+ *
29
+ * Grid is always 6 weeks x 7 days (42 cells) for layout stability.
30
+ * Includes padding days from previous/next month.
31
+ */
32
+ export interface CalendarGrid {
33
+ /** Month identifier */
34
+ month: {
35
+ /** Year */
36
+ year: number;
37
+ /** Month 0-11 */
38
+ month: number;
39
+ };
40
+ /** Week start day (0 = Sunday, 1 = Monday, etc.) */
41
+ weekStart: number;
42
+ /** Locale (for future i18n, optional) */
43
+ locale?: string;
44
+ /** 6 weeks x 7 days matrix */
45
+ weeks: CalendarCell[][];
46
+ /** Flat array of all cells (convenience accessor) */
47
+ cells: CalendarCell[];
48
+ }
49
+ /**
50
+ * Cache key for calendar grids
51
+ */
52
+ export interface CalendarGridCacheKey {
53
+ year: number;
54
+ month: number;
55
+ weekStart: number;
56
+ locale?: string;
57
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Calendar Grid Module
3
+ *
4
+ * Performance-optimized calendar month grid generation with memoization.
5
+ *
6
+ * v3.7.0: Grid Structure Cache
7
+ * - CalendarGridFactory for deterministic 42-cell grids
8
+ * - CalendarGridCache with LRU (24 months)
9
+ *
10
+ * v3.8.0: Range Highlight Cache
11
+ * - RangeHighlighter for decoration logic
12
+ * - RangeHighlighterCache with LRU (48 grids)
13
+ * - Separates grid structure from decorations
14
+ *
15
+ * v3.9.0: Virtual Weeks (Windowed Rendering)
16
+ * - Virtual-weeks logic for reduced DOM complexity
17
+ * - Render only visible weeks (configurable window)
18
+ * - ~50% reduction in DOM nodes with windowSize=3
19
+ *
20
+ * Usage:
21
+ * ```typescript
22
+ * constructor(
23
+ * private gridCache: CalendarGridCache,
24
+ * private highlighterCache: RangeHighlighterCache
25
+ * ) {}
26
+ *
27
+ * const grid = this.gridCache.get(monthDate, weekStart);
28
+ * const decorated = this.highlighterCache.get(grid, {
29
+ * start, end, hoverDate, disabledDates
30
+ * });
31
+ *
32
+ * // Optional: Windowed rendering (v3.9.0+)
33
+ * const windowSize = 3; // Render only 3 weeks
34
+ * const visibleWeeks = getVisibleWeeks(
35
+ * decorated.weeks,
36
+ * weekStartIndex,
37
+ * windowSize
38
+ * );
39
+ * // decorated.cells[0].iso => '2026-02-01'
40
+ * // decorated.cells[0].isInRange => true
41
+ * ```
42
+ */
43
+ export * from './calendar-grid.types';
44
+ export * from './calendar-grid.factory';
45
+ export * from './calendar-grid.cache';
46
+ export * from './range-highlighter.types';
47
+ export * from './range-highlighter';
48
+ export * from './range-highlighter.cache';
49
+ export * from './virtual-weeks.types';
50
+ export * from './virtual-weeks.logic';
@@ -0,0 +1,105 @@
1
+ import { DateAdapter } from '../date-adapter';
2
+ import { CalendarGrid } from './calendar-grid.types';
3
+ import { DecoratedGrid, RangeDecorationParams } from './range-highlighter.types';
4
+ import { RangeHighlighter } from './range-highlighter';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * Range Highlighter Cache
8
+ *
9
+ * Memoizes decorated grids to avoid recomputing decorations.
10
+ *
11
+ * Cache strategy:
12
+ * - LRU eviction (Map preserves insertion order)
13
+ * - Max 48 entries (~1-2 years of decorated grids)
14
+ * - Key: month + start + end + hover + disabled signature
15
+ *
16
+ * Performance:
17
+ * - Cache hit: ~0.1ms (object lookup)
18
+ * - Cache miss: ~1ms (decoration + store)
19
+ * - Hit rate: Expected >80% in typical usage
20
+ *
21
+ * Memory:
22
+ * - ~15KB per decorated grid
23
+ * - Max 48 grids = ~720KB
24
+ * - Auto-eviction prevents leaks
25
+ *
26
+ * Edge cases handled:
27
+ * - Function predicates: Not cacheable (recompute every time)
28
+ * - Large disabled arrays: Sorted + joined for stable key
29
+ * - Hover changes: Separate cache entries
30
+ * - Multi-range mode: Included in key
31
+ *
32
+ * Usage:
33
+ * ```typescript
34
+ * const grid = calendarGridCache.get(monthDate, 0);
35
+ * const decorated = rangeHighlighterCache.get(grid, {
36
+ * start: startDate,
37
+ * end: endDate,
38
+ * hoverDate: '2026-01-20',
39
+ * disabledDates: [...]
40
+ * });
41
+ * // Same params = same object reference (===)
42
+ * ```
43
+ */
44
+ export declare class RangeHighlighterCache {
45
+ private highlighter;
46
+ private adapter;
47
+ private cache;
48
+ private maxSize;
49
+ constructor(highlighter: RangeHighlighter, adapter: DateAdapter);
50
+ /**
51
+ * Get decorated grid (cached or computed)
52
+ *
53
+ * If cache hit: Returns existing DecoratedGrid (same object reference)
54
+ * If cache miss: Computes decorations, stores in cache, returns new grid
55
+ *
56
+ * @param grid Base calendar grid (from CalendarGridCache)
57
+ * @param params Decoration parameters
58
+ * @returns Decorated grid with range highlights
59
+ */
60
+ get(grid: CalendarGrid, params: RangeDecorationParams): DecoratedGrid;
61
+ /**
62
+ * Build cache key from grid and params
63
+ *
64
+ * Key structure:
65
+ * `${monthKey}|${startISO}|${endISO}|${minISO}|${maxISO}|${hoverISO}|${disabledSig}`
66
+ *
67
+ * Example:
68
+ * "2026-1-0-|2026-01-15|2026-01-25|null|null|2026-01-20|2026-01-10,2026-01-11"
69
+ *
70
+ * @param grid Base calendar grid
71
+ * @param params Decoration parameters
72
+ * @returns Cache key components
73
+ */
74
+ private buildKey;
75
+ /**
76
+ * Build signature for disabled dates
77
+ *
78
+ * Strategies:
79
+ * - null/undefined: 'none'
80
+ * - Function: 'function' (not cacheable)
81
+ * - Array: Sorted ISO dates joined with commas
82
+ *
83
+ * @param disabledDates Disabled dates specification
84
+ * @returns Signature string for cache key
85
+ */
86
+ private buildDisabledSignature;
87
+ /**
88
+ * Clear all cached grids
89
+ */
90
+ clear(): void;
91
+ /**
92
+ * Get current cache size
93
+ */
94
+ size(): number;
95
+ /**
96
+ * Check if key is cached
97
+ *
98
+ * @param grid Base calendar grid
99
+ * @param params Decoration parameters
100
+ * @returns True if this grid+params is cached
101
+ */
102
+ has(grid: CalendarGrid, params: RangeDecorationParams): boolean;
103
+ static ɵfac: i0.ɵɵFactoryDeclaration<RangeHighlighterCache, never>;
104
+ static ɵprov: i0.ɵɵInjectableDeclaration<RangeHighlighterCache>;
105
+ }
@@ -0,0 +1,85 @@
1
+ import { DateAdapter } from '../date-adapter';
2
+ import { CalendarGrid } from './calendar-grid.types';
3
+ import { DecoratedGrid, RangeDecorationParams } from './range-highlighter.types';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Range Highlighter
7
+ *
8
+ * Applies decorations to calendar grids:
9
+ * - isSelectedStart, isSelectedEnd (range boundaries)
10
+ * - isInRange (cells within selected range)
11
+ * - isInHoverRange (hover preview)
12
+ * - isDisabled (constraints, custom predicates)
13
+ *
14
+ * Design:
15
+ * - Pure functions (same input = same output)
16
+ * - Uses DateAdapter for all date operations (SSR-safe)
17
+ * - No side effects, no state
18
+ * - Fast (~1ms for 42 cells on mobile)
19
+ *
20
+ * Usage:
21
+ * ```typescript
22
+ * const grid = calendarGridCache.get(monthDate, 0);
23
+ * const decorated = rangeHighlighter.decorate(grid, {
24
+ * start: startDate,
25
+ * end: endDate,
26
+ * hoverDate: '2026-01-20',
27
+ * disabledDates: [...]
28
+ * });
29
+ * ```
30
+ */
31
+ export declare class RangeHighlighter {
32
+ private adapter;
33
+ constructor(adapter: DateAdapter);
34
+ /**
35
+ * Decorate calendar grid with range highlights
36
+ *
37
+ * @param grid Base calendar grid (from CalendarGridCache)
38
+ * @param params Decoration parameters (start, end, hover, disabled, etc.)
39
+ * @returns Decorated grid with computed properties
40
+ */
41
+ decorate(grid: CalendarGrid, params: RangeDecorationParams): DecoratedGrid;
42
+ /**
43
+ * Check if cell is within selected range
44
+ *
45
+ * @param cellISO Cell date (ISO format)
46
+ * @param startISO Start date (ISO or null)
47
+ * @param endISO End date (ISO or null)
48
+ * @returns True if cell is in range [start, end] (inclusive)
49
+ */
50
+ private isInRange;
51
+ /**
52
+ * Check if cell is within hover preview range
53
+ *
54
+ * @param cellISO Cell date (ISO format)
55
+ * @param hoverRange Hover range boundaries (or null)
56
+ * @returns True if cell is in hover range
57
+ */
58
+ private isInHoverRange;
59
+ /**
60
+ * Check if cell is disabled
61
+ *
62
+ * @param date Cell date object
63
+ * @param minISO Minimum allowed date (ISO or null)
64
+ * @param maxISO Maximum allowed date (ISO or null)
65
+ * @param disabledDates Disabled dates (array, function, or null)
66
+ * @returns True if cell is disabled
67
+ */
68
+ private isDisabled;
69
+ /**
70
+ * Compute hover preview range
71
+ *
72
+ * When user hovers over a date (and not selecting start):
73
+ * - Show preview range from start to hover
74
+ * - Range is always [min, max] where min <= max
75
+ *
76
+ * @param startISO Current start date (ISO or null)
77
+ * @param hoverISO Hovered date (ISO or null)
78
+ * @param selectingStart True if selecting start date (hover disabled)
79
+ * @param multiRange True if in multi-range mode
80
+ * @returns Hover range boundaries or null
81
+ */
82
+ private computeHoverRange;
83
+ static ɵfac: i0.ɵɵFactoryDeclaration<RangeHighlighter, never>;
84
+ static ɵprov: i0.ɵɵInjectableDeclaration<RangeHighlighter>;
85
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Range Highlighter Types
3
+ *
4
+ * Type definitions for calendar cell decorations with range highlighting.
5
+ * Used by RangeHighlighter to cache decorated grids and avoid recomputations.
6
+ *
7
+ * @module core/calendar-grid/range-highlighter.types
8
+ * @version 3.8.0
9
+ */
10
+ import { CalendarCell, CalendarGrid } from './calendar-grid.types';
11
+ /**
12
+ * Calendar cell with range highlight decorations
13
+ *
14
+ * Extends base CalendarCell with computed properties for:
15
+ * - Start/end markers (selected range boundaries)
16
+ * - Range membership (cell within selected range)
17
+ * - Hover preview (temporary range during mouse hover)
18
+ * - Disabled state (constraints, custom predicates)
19
+ */
20
+ export interface DecoratedCell extends CalendarCell {
21
+ /**
22
+ * True if this cell is the selected start date
23
+ */
24
+ isSelectedStart: boolean;
25
+ /**
26
+ * True if this cell is the selected end date
27
+ */
28
+ isSelectedEnd: boolean;
29
+ /**
30
+ * True if this cell is within the selected range (inclusive)
31
+ */
32
+ isInRange: boolean;
33
+ /**
34
+ * True if this cell is within the hover preview range
35
+ */
36
+ isInHoverRange: boolean;
37
+ /**
38
+ * True if this cell is disabled (via constraints or custom logic)
39
+ */
40
+ isDisabled: boolean;
41
+ }
42
+ /**
43
+ * Calendar grid with decorated cells
44
+ *
45
+ * Contains:
46
+ * - base: Original CalendarGrid (from CalendarGridCache)
47
+ * - weeks: 2D array of decorated cells (6 × 7)
48
+ * - cells: Flat array of decorated cells (42 cells)
49
+ */
50
+ export interface DecoratedGrid {
51
+ /**
52
+ * Base grid structure (memoized by CalendarGridCache)
53
+ */
54
+ base: CalendarGrid;
55
+ /**
56
+ * Decorated cells organized as weeks (6 weeks × 7 days)
57
+ */
58
+ weeks: DecoratedCell[][];
59
+ /**
60
+ * Decorated cells as flat array (42 cells for layout stability)
61
+ */
62
+ cells: DecoratedCell[];
63
+ }
64
+ /**
65
+ * Parameters for range decoration
66
+ *
67
+ * All dates must be Date objects (pre-parsed by component).
68
+ * Cache key is built from ISO dates (via DateAdapter.toISODate).
69
+ *
70
+ * Constraints:
71
+ * - start/end: Selected range boundaries (null if not selected)
72
+ * - minDate/maxDate: Hard constraints (optional, for future use)
73
+ * - hoverDate: Current hover date (null if not hovering)
74
+ * - disabledDates: Array of disabled dates OR function predicate
75
+ */
76
+ export interface RangeDecorationParams {
77
+ /**
78
+ * Selected start date (null if not selected yet)
79
+ */
80
+ start: Date | null;
81
+ /**
82
+ * Selected end date (null if not selected yet)
83
+ */
84
+ end: Date | null;
85
+ /**
86
+ * Minimum allowed date (optional, for future constraint support)
87
+ * All dates before this will be disabled.
88
+ */
89
+ minDate?: Date | null;
90
+ /**
91
+ * Maximum allowed date (optional, for future constraint support)
92
+ * All dates after this will be disabled.
93
+ */
94
+ maxDate?: Date | null;
95
+ /**
96
+ * Current hover date (null if not hovering)
97
+ * Used to calculate hover preview range.
98
+ */
99
+ hoverDate?: string | null;
100
+ /**
101
+ * Disabled dates specification
102
+ *
103
+ * Can be one of:
104
+ * - Array of Date objects to disable (exact matches)
105
+ * - Function predicate (date) => boolean
106
+ * - undefined/null (no dates disabled)
107
+ *
108
+ * NOTE: Functions cannot be cached reliably (no stable key).
109
+ * If using function, cache will be bypassed for isDisabled computation.
110
+ */
111
+ disabledDates?: Date[] | ((date: Date) => boolean) | null;
112
+ /**
113
+ * Multi-range mode flag (affects hover range behavior)
114
+ * Default: false
115
+ */
116
+ multiRange?: boolean;
117
+ /**
118
+ * Currently selecting start date (affects hover preview)
119
+ * Default: false
120
+ */
121
+ selectingStartDate?: boolean;
122
+ }
123
+ /**
124
+ * Cache key for decorated grid
125
+ *
126
+ * Built from:
127
+ * - monthKey: `${year}-${month}-${weekStart}-${locale}`
128
+ * - startISO, endISO: ISO dates or 'null'
129
+ * - minISO, maxISO: ISO dates or 'null' (optional)
130
+ * - hoverISO: ISO date or 'null'
131
+ * - disabledSignature: Hash of disabled dates (or 'none' / 'function')
132
+ *
133
+ * Example:
134
+ * "2026-1-0-|2026-01-15|2026-01-25|null|null|2026-01-20|2026-01-10,2026-01-11"
135
+ *
136
+ * Segment breakdown:
137
+ * 1. 2026-1-0- (month: Jan 2026, weekStart: Sunday, no locale)
138
+ * 2. 2026-01-15 (start date)
139
+ * 3. 2026-01-25 (end date)
140
+ * 4. null (no minDate)
141
+ * 5. null (no maxDate)
142
+ * 6. 2026-01-20 (hovering over Jan 20)
143
+ * 7. 2026-01-10,2026-01-11 (disabled dates: Jan 10 & 11)
144
+ */
145
+ export interface DecoratedGridCacheKey {
146
+ /**
147
+ * Combined month key (from base grid)
148
+ */
149
+ monthKey: string;
150
+ /**
151
+ * Start date ISO (YYYY-MM-DD) or 'null'
152
+ */
153
+ startISO: string;
154
+ /**
155
+ * End date ISO (YYYY-MM-DD) or 'null'
156
+ */
157
+ endISO: string;
158
+ /**
159
+ * Min date ISO (YYYY-MM-DD) or 'null'
160
+ */
161
+ minISO: string;
162
+ /**
163
+ * Max date ISO (YYYY-MM-DD) or 'null'
164
+ */
165
+ maxISO: string;
166
+ /**
167
+ * Hover date ISO (YYYY-MM-DD) or 'null'
168
+ */
169
+ hoverISO: string;
170
+ /**
171
+ * Disabled dates signature
172
+ *
173
+ * - 'none': No dates disabled
174
+ * - 'function': Using predicate function (not cacheable)
175
+ * - sorted ISO string: "2026-01-10,2026-01-11,..." (for array)
176
+ */
177
+ disabledSignature: string;
178
+ /**
179
+ * Full cache key (concatenation of all segments)
180
+ */
181
+ full: string;
182
+ }