@oneluiz/dual-datepicker 3.6.0 → 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.
- package/core/calendar-grid/calendar-grid.cache.d.ts +39 -0
- package/core/calendar-grid/calendar-grid.factory.d.ts +26 -0
- package/core/calendar-grid/calendar-grid.types.d.ts +57 -0
- package/core/calendar-grid/index.d.ts +50 -0
- package/core/calendar-grid/range-highlighter.cache.d.ts +105 -0
- package/core/calendar-grid/range-highlighter.d.ts +85 -0
- package/core/calendar-grid/range-highlighter.types.d.ts +182 -0
- package/core/calendar-grid/virtual-weeks.logic.d.ts +116 -0
- package/core/calendar-grid/virtual-weeks.types.d.ts +71 -0
- package/core/index.d.ts +11 -0
- package/dual-datepicker.component.d.ts +78 -1
- package/esm2022/core/calendar-grid/calendar-grid.cache.mjs +92 -0
- package/esm2022/core/calendar-grid/calendar-grid.factory.mjs +97 -0
- package/esm2022/core/calendar-grid/calendar-grid.types.mjs +8 -0
- package/esm2022/core/calendar-grid/index.mjs +51 -0
- package/esm2022/core/calendar-grid/range-highlighter.cache.mjs +198 -0
- package/esm2022/core/calendar-grid/range-highlighter.mjs +185 -0
- package/esm2022/core/calendar-grid/range-highlighter.types.mjs +11 -0
- package/esm2022/core/calendar-grid/virtual-weeks.logic.mjs +149 -0
- package/esm2022/core/calendar-grid/virtual-weeks.types.mjs +11 -0
- package/esm2022/core/index.mjs +14 -1
- package/esm2022/dual-datepicker.component.mjs +177 -38
- package/fesm2022/oneluiz-dual-datepicker.mjs +965 -39
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtual Weeks Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for windowed week rendering (virtual scrolling).
|
|
5
|
+
* Reduces DOM nodes by rendering only visible weeks instead of full month.
|
|
6
|
+
*
|
|
7
|
+
* @module core/calendar-grid/virtual-weeks.types
|
|
8
|
+
* @version 3.9.0
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Virtual weeks configuration
|
|
12
|
+
*
|
|
13
|
+
* Controls how many weeks to render at once (windowed rendering).
|
|
14
|
+
* Reduces DOM complexity for better mobile performance.
|
|
15
|
+
*
|
|
16
|
+
* Example:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* <ngx-dual-datepicker
|
|
19
|
+
* [virtualWeeks]="{ windowSize: 3 }"
|
|
20
|
+
* </ngx-dual-datepicker>
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* With windowSize=3:
|
|
24
|
+
* - Renders only 3 weeks at a time (21 cells vs 42 cells)
|
|
25
|
+
* - User can navigate between week windows
|
|
26
|
+
* - ~50% reduction in DOM nodes per calendar
|
|
27
|
+
* - ~50% reduction in reflow/repaint cost
|
|
28
|
+
*/
|
|
29
|
+
export interface VirtualWeeksConfig {
|
|
30
|
+
/**
|
|
31
|
+
* Number of weeks to render at once
|
|
32
|
+
*
|
|
33
|
+
* Default: undefined (render all 6 weeks - backward compatible)
|
|
34
|
+
*
|
|
35
|
+
* Recommended values:
|
|
36
|
+
* - 3: Good balance (21 cells)
|
|
37
|
+
* - 4: More context (28 cells)
|
|
38
|
+
* - 2: Minimal (14 cells, may feel cramped)
|
|
39
|
+
*/
|
|
40
|
+
windowSize: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Virtual week window state
|
|
44
|
+
*
|
|
45
|
+
* Tracks which weeks are currently visible in the window.
|
|
46
|
+
* Managed by component signals.
|
|
47
|
+
*/
|
|
48
|
+
export interface VirtualWeekWindow {
|
|
49
|
+
/**
|
|
50
|
+
* Start index of visible week range (0-based)
|
|
51
|
+
*
|
|
52
|
+
* Range: [0, totalWeeks - windowSize]
|
|
53
|
+
*/
|
|
54
|
+
startIndex: number;
|
|
55
|
+
/**
|
|
56
|
+
* Window size (how many weeks visible)
|
|
57
|
+
*/
|
|
58
|
+
windowSize: number;
|
|
59
|
+
/**
|
|
60
|
+
* Total weeks available in month (usually 6, sometimes 5)
|
|
61
|
+
*/
|
|
62
|
+
totalWeeks: number;
|
|
63
|
+
/**
|
|
64
|
+
* Whether user can scroll/navigate up (to earlier weeks)
|
|
65
|
+
*/
|
|
66
|
+
canNavigateUp: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Whether user can scroll/navigate down (to later weeks)
|
|
69
|
+
*/
|
|
70
|
+
canNavigateDown: boolean;
|
|
71
|
+
}
|
package/core/index.d.ts
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
* - Built-in presets as plugins
|
|
8
8
|
* - Provider functions for custom presets
|
|
9
9
|
*
|
|
10
|
+
* v3.7.0: Calendar Grid Cache
|
|
11
|
+
* - CalendarGridFactory for deterministic grid generation
|
|
12
|
+
* - CalendarGridCache with LRU memoization
|
|
13
|
+
* - Separates grid structure from decorations for performance
|
|
14
|
+
*
|
|
15
|
+
* v3.8.0: Range Highlight Cache
|
|
16
|
+
* - RangeHighlighter for decoration logic (pure computation)
|
|
17
|
+
* - RangeHighlighterCache with LRU (48 grids)
|
|
18
|
+
* - Eliminates redundant decoration recomputations
|
|
19
|
+
*
|
|
10
20
|
* Import from here for clean barrel exports
|
|
11
21
|
*/
|
|
12
22
|
export * from './dual-date-range.store';
|
|
@@ -20,3 +30,4 @@ export * from './range-preset.plugin';
|
|
|
20
30
|
export * from './preset-registry';
|
|
21
31
|
export * from './built-in-presets';
|
|
22
32
|
export * from './preset-providers';
|
|
33
|
+
export * from './calendar-grid';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter, OnInit, OnChanges, SimpleChanges, ElementRef } from '@angular/core';
|
|
2
2
|
import { ControlValueAccessor } from '@angular/forms';
|
|
3
3
|
import { DualDateRangeStore } from './core/dual-date-range.store';
|
|
4
|
+
import { VirtualWeeksConfig } from './core/calendar-grid';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
export interface DateRange {
|
|
6
7
|
startDate: string;
|
|
@@ -59,11 +60,32 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
59
60
|
minuteStep: number;
|
|
60
61
|
defaultStartTime: string;
|
|
61
62
|
defaultEndTime: string;
|
|
63
|
+
/**
|
|
64
|
+
* Virtual Weeks Configuration (v3.9.0+)
|
|
65
|
+
*
|
|
66
|
+
* Enables windowed rendering to reduce DOM complexity and improve mobile performance.
|
|
67
|
+
* Only renders a subset of calendar weeks instead of all 6.
|
|
68
|
+
*
|
|
69
|
+
* Example: `{ windowSize: 3 }` renders only 3 weeks (21 cells) instead of 6 weeks (42 cells),
|
|
70
|
+
* reducing DOM nodes by ~50% per calendar.
|
|
71
|
+
*
|
|
72
|
+
* @default undefined (disabled - renders all 6 weeks for backward compatibility)
|
|
73
|
+
*
|
|
74
|
+
* Example:
|
|
75
|
+
* ```html
|
|
76
|
+
* <ngx-dual-datepicker
|
|
77
|
+
* [virtualWeeks]="{ windowSize: 3 }">
|
|
78
|
+
* </ngx-dual-datepicker>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
virtualWeeks?: VirtualWeeksConfig;
|
|
62
82
|
dateRangeChange: EventEmitter<DateRange>;
|
|
63
83
|
dateRangeSelected: EventEmitter<DateRange>;
|
|
64
84
|
multiDateRangeChange: EventEmitter<MultiDateRange>;
|
|
65
85
|
multiDateRangeSelected: EventEmitter<MultiDateRange>;
|
|
66
86
|
private dateAdapter;
|
|
87
|
+
private gridCache;
|
|
88
|
+
private highlighterCache;
|
|
67
89
|
protected readonly rangeStore: DualDateRangeStore;
|
|
68
90
|
showDatePicker: import("@angular/core").WritableSignal<boolean>;
|
|
69
91
|
currentMonth: import("@angular/core").WritableSignal<any>;
|
|
@@ -74,6 +96,27 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
74
96
|
showStartTimePicker: import("@angular/core").WritableSignal<boolean>;
|
|
75
97
|
showEndTimePicker: import("@angular/core").WritableSignal<boolean>;
|
|
76
98
|
hoverDate: import("@angular/core").WritableSignal<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Virtual Weeks State (v3.9.0+)
|
|
101
|
+
*
|
|
102
|
+
* Signals to track which week window is currently visible for each calendar.
|
|
103
|
+
* - weekStart = 0: Shows first N weeks (windowSize)
|
|
104
|
+
* - weekStart = 1: Shows weeks 1 to N+1, etc.
|
|
105
|
+
*
|
|
106
|
+
* Reset to 0 when month changes for consistent UX.
|
|
107
|
+
*/
|
|
108
|
+
previousMonthWeekStart: import("@angular/core").WritableSignal<number>;
|
|
109
|
+
currentMonthWeekStart: import("@angular/core").WritableSignal<number>;
|
|
110
|
+
/**
|
|
111
|
+
* Computed: Visible weeks for windowed rendering (v3.9.0+)
|
|
112
|
+
*
|
|
113
|
+
* If virtualWeeks is enabled, returns only the visible subset of weeks.
|
|
114
|
+
* Otherwise, returns all weeks for backward compatibility.
|
|
115
|
+
*
|
|
116
|
+
* Example: If windowSize=3 and weekStart=0, returns first 3 weeks (rows 0-2).
|
|
117
|
+
*/
|
|
118
|
+
previousMonthVisibleDays: import("@angular/core").Signal<any[]>;
|
|
119
|
+
currentMonthVisibleDays: import("@angular/core").Signal<any[]>;
|
|
77
120
|
get startHour(): number;
|
|
78
121
|
get startMinute(): number;
|
|
79
122
|
get endHour(): number;
|
|
@@ -121,8 +164,42 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
121
164
|
toggleDatePicker(): void;
|
|
122
165
|
closeDatePicker(): void;
|
|
123
166
|
generateCalendars(): void;
|
|
167
|
+
/**
|
|
168
|
+
* Generate calendar grid with decorations (v3.8.0+)
|
|
169
|
+
*
|
|
170
|
+
* Uses CalendarGridCache for base grid structure (memoized by month),
|
|
171
|
+
* then uses RangeHighlighterCache for decorations (memoized by range/constraints).
|
|
172
|
+
*
|
|
173
|
+
* Performance:
|
|
174
|
+
* - Grid structure: Cached by month (same month = same grid object)
|
|
175
|
+
* - Decorations: Cached by range+hover+disabled (same state = same decorated grid)
|
|
176
|
+
* - Result: ~95% cache hit rate in typical usage
|
|
177
|
+
*
|
|
178
|
+
* Cache keys:
|
|
179
|
+
* - Grid: `${year}-${month}-${weekStart}`
|
|
180
|
+
* - Decorations: `${monthKey}|${start}|${end}|${hover}|${disabled}`
|
|
181
|
+
*/
|
|
124
182
|
generateMonthCalendar(date: Date): any[];
|
|
125
183
|
isInRange(dateStr: string): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Virtual Weeks Navigation (v3.9.0+)
|
|
186
|
+
*
|
|
187
|
+
* Navigate the visible week window up/down for windowed rendering.
|
|
188
|
+
*
|
|
189
|
+
* @param monthIndex 0 = previous month, 1 = current month
|
|
190
|
+
* @param direction -1 = scroll up (previous weeks), +1 = scroll down (next weeks)
|
|
191
|
+
*
|
|
192
|
+
* Example: If windowSize=3 and weekStart=0, navigateWeeks(0, +1) shows weeks 1-3.
|
|
193
|
+
*/
|
|
194
|
+
navigateWeeks(monthIndex: number, direction: number): void;
|
|
195
|
+
/**
|
|
196
|
+
* Check if week navigation is available (v3.9.0+)
|
|
197
|
+
*
|
|
198
|
+
* @param monthIndex 0 = previous month, 1 = current month
|
|
199
|
+
* @param direction -1 = up (can scroll to previous weeks?), +1 = down (can scroll to next weeks?)
|
|
200
|
+
* @returns true if navigation is available in that direction
|
|
201
|
+
*/
|
|
202
|
+
canNavigateWeeks(monthIndex: number, direction: number): boolean;
|
|
126
203
|
isDateDisabled(date: Date): boolean;
|
|
127
204
|
isInHoverRange(dateStr: string): boolean;
|
|
128
205
|
onDayHover(dayObj: any): void;
|
|
@@ -162,5 +239,5 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
162
239
|
registerOnTouched(fn: () => void): void;
|
|
163
240
|
setDisabledState(isDisabled: boolean): void;
|
|
164
241
|
static ɵfac: i0.ɵɵFactoryDeclaration<DualDatepickerComponent, never>;
|
|
165
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; "enableTimePicker": { "alias": "enableTimePicker"; "required": false; }; "timeFormat": { "alias": "timeFormat"; "required": false; }; "minuteStep": { "alias": "minuteStep"; "required": false; }; "defaultStartTime": { "alias": "defaultStartTime"; "required": false; }; "defaultEndTime": { "alias": "defaultEndTime"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
|
|
242
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; "enableTimePicker": { "alias": "enableTimePicker"; "required": false; }; "timeFormat": { "alias": "timeFormat"; "required": false; }; "minuteStep": { "alias": "minuteStep"; "required": false; }; "defaultStartTime": { "alias": "defaultStartTime"; "required": false; }; "defaultEndTime": { "alias": "defaultEndTime"; "required": false; }; "virtualWeeks": { "alias": "virtualWeeks"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
|
|
166
243
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar Grid Cache
|
|
3
|
+
*
|
|
4
|
+
* LRU cache for calendar month grids to avoid recomputing the same month grid
|
|
5
|
+
* multiple times when only decorations (selected dates, hover, etc.) change.
|
|
6
|
+
*
|
|
7
|
+
* Strategy:
|
|
8
|
+
* - Key: year-month-weekStart-locale
|
|
9
|
+
* - LRU eviction (least recently used) when limit is reached
|
|
10
|
+
* - Default limit: 24 months (covers 1 year forward + 1 year back)
|
|
11
|
+
*
|
|
12
|
+
* Performance impact:
|
|
13
|
+
* - Eliminates ~90% of grid recalculations in typical usage
|
|
14
|
+
* - Memory footprint: ~10KB per cached month (negligible)
|
|
15
|
+
*/
|
|
16
|
+
import { Injectable } from '@angular/core';
|
|
17
|
+
import * as i0 from "@angular/core";
|
|
18
|
+
import * as i1 from "./calendar-grid.factory";
|
|
19
|
+
export class CalendarGridCache {
|
|
20
|
+
factory;
|
|
21
|
+
cache = new Map();
|
|
22
|
+
maxSize = 24;
|
|
23
|
+
constructor(factory) {
|
|
24
|
+
this.factory = factory;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get or create a calendar grid
|
|
28
|
+
*
|
|
29
|
+
* @param monthDate - Any date within the target month
|
|
30
|
+
* @param weekStart - First day of week (0 = Sunday, 1 = Monday, etc.)
|
|
31
|
+
* @param locale - Locale identifier (optional)
|
|
32
|
+
* @returns CalendarGrid - cached or newly created
|
|
33
|
+
*/
|
|
34
|
+
get(monthDate, weekStart = 0, locale) {
|
|
35
|
+
const key = this.buildKey(monthDate, weekStart, locale);
|
|
36
|
+
// Check cache
|
|
37
|
+
const cached = this.cache.get(key);
|
|
38
|
+
if (cached) {
|
|
39
|
+
// Move to end (LRU)
|
|
40
|
+
this.cache.delete(key);
|
|
41
|
+
this.cache.set(key, cached);
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
// Generate new grid
|
|
45
|
+
const grid = this.factory.createGrid(monthDate, weekStart, locale);
|
|
46
|
+
// Store in cache
|
|
47
|
+
this.cache.set(key, grid);
|
|
48
|
+
// Evict oldest if over limit (LRU)
|
|
49
|
+
if (this.cache.size > this.maxSize) {
|
|
50
|
+
const firstKey = this.cache.keys().next().value;
|
|
51
|
+
this.cache.delete(firstKey);
|
|
52
|
+
}
|
|
53
|
+
return grid;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build cache key from month parameters
|
|
57
|
+
*
|
|
58
|
+
* Format: "year-month-weekStart-locale"
|
|
59
|
+
* Example: "2026-1-0-en" (Feb 2026, Sunday start, English)
|
|
60
|
+
*/
|
|
61
|
+
buildKey(monthDate, weekStart, locale) {
|
|
62
|
+
const year = monthDate.getFullYear();
|
|
63
|
+
const month = monthDate.getMonth();
|
|
64
|
+
return `${year}-${month}-${weekStart}${locale ? '-' + locale : ''}`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Clear entire cache (for testing or manual reset)
|
|
68
|
+
*/
|
|
69
|
+
clear() {
|
|
70
|
+
this.cache.clear();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get cache size (for debugging/testing)
|
|
74
|
+
*/
|
|
75
|
+
size() {
|
|
76
|
+
return this.cache.size;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if a specific month is cached
|
|
80
|
+
*/
|
|
81
|
+
has(monthDate, weekStart = 0, locale) {
|
|
82
|
+
const key = this.buildKey(monthDate, weekStart, locale);
|
|
83
|
+
return this.cache.has(key);
|
|
84
|
+
}
|
|
85
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridCache, deps: [{ token: i1.CalendarGridFactory }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
86
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridCache, providedIn: 'root' });
|
|
87
|
+
}
|
|
88
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridCache, decorators: [{
|
|
89
|
+
type: Injectable,
|
|
90
|
+
args: [{ providedIn: 'root' }]
|
|
91
|
+
}], ctorParameters: () => [{ type: i1.CalendarGridFactory }] });
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItZ3JpZC5jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL2NhbGVuZGFyLWdyaWQvY2FsZW5kYXItZ3JpZC5jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7OztBQUszQyxNQUFNLE9BQU8saUJBQWlCO0lBSVI7SUFIWixLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUM7SUFDL0IsT0FBTyxHQUFXLEVBQUUsQ0FBQztJQUV0QyxZQUFvQixPQUE0QjtRQUE1QixZQUFPLEdBQVAsT0FBTyxDQUFxQjtJQUFHLENBQUM7SUFFcEQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FBQyxTQUFlLEVBQUUsWUFBb0IsQ0FBQyxFQUFFLE1BQWU7UUFDekQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXhELGNBQWM7UUFDZCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsb0JBQW9CO1lBQ3BCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBRUQsb0JBQW9CO1FBQ3BCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFbkUsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUxQixtQ0FBbUM7UUFDbkMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDaEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUIsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssUUFBUSxDQUFDLFNBQWUsRUFBRSxTQUFpQixFQUFFLE1BQWU7UUFDbEUsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNuQyxPQUFPLEdBQUcsSUFBSSxJQUFJLEtBQUssSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztJQUN0RSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJO1FBQ0YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztJQUN6QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxHQUFHLENBQUMsU0FBZSxFQUFFLFlBQW9CLENBQUMsRUFBRSxNQUFlO1FBQ3pELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN4RCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLENBQUM7d0dBekVVLGlCQUFpQjs0R0FBakIsaUJBQWlCLGNBREosTUFBTTs7NEZBQ25CLGlCQUFpQjtrQkFEN0IsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENhbGVuZGFyIEdyaWQgQ2FjaGVcbiAqXG4gKiBMUlUgY2FjaGUgZm9yIGNhbGVuZGFyIG1vbnRoIGdyaWRzIHRvIGF2b2lkIHJlY29tcHV0aW5nIHRoZSBzYW1lIG1vbnRoIGdyaWRcbiAqIG11bHRpcGxlIHRpbWVzIHdoZW4gb25seSBkZWNvcmF0aW9ucyAoc2VsZWN0ZWQgZGF0ZXMsIGhvdmVyLCBldGMuKSBjaGFuZ2UuXG4gKlxuICogU3RyYXRlZ3k6XG4gKiAtIEtleTogeWVhci1tb250aC13ZWVrU3RhcnQtbG9jYWxlXG4gKiAtIExSVSBldmljdGlvbiAobGVhc3QgcmVjZW50bHkgdXNlZCkgd2hlbiBsaW1pdCBpcyByZWFjaGVkXG4gKiAtIERlZmF1bHQgbGltaXQ6IDI0IG1vbnRocyAoY292ZXJzIDEgeWVhciBmb3J3YXJkICsgMSB5ZWFyIGJhY2spXG4gKlxuICogUGVyZm9ybWFuY2UgaW1wYWN0OlxuICogLSBFbGltaW5hdGVzIH45MCUgb2YgZ3JpZCByZWNhbGN1bGF0aW9ucyBpbiB0eXBpY2FsIHVzYWdlXG4gKiAtIE1lbW9yeSBmb290cHJpbnQ6IH4xMEtCIHBlciBjYWNoZWQgbW9udGggKG5lZ2xpZ2libGUpXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ2FsZW5kYXJHcmlkRmFjdG9yeSB9IGZyb20gJy4vY2FsZW5kYXItZ3JpZC5mYWN0b3J5JztcbmltcG9ydCB7IENhbGVuZGFyR3JpZCwgQ2FsZW5kYXJHcmlkQ2FjaGVLZXkgfSBmcm9tICcuL2NhbGVuZGFyLWdyaWQudHlwZXMnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIENhbGVuZGFyR3JpZENhY2hlIHtcbiAgcHJpdmF0ZSBjYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBDYWxlbmRhckdyaWQ+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWF4U2l6ZTogbnVtYmVyID0gMjQ7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmYWN0b3J5OiBDYWxlbmRhckdyaWRGYWN0b3J5KSB7fVxuXG4gIC8qKlxuICAgKiBHZXQgb3IgY3JlYXRlIGEgY2FsZW5kYXIgZ3JpZFxuICAgKlxuICAgKiBAcGFyYW0gbW9udGhEYXRlIC0gQW55IGRhdGUgd2l0aGluIHRoZSB0YXJnZXQgbW9udGhcbiAgICogQHBhcmFtIHdlZWtTdGFydCAtIEZpcnN0IGRheSBvZiB3ZWVrICgwID0gU3VuZGF5LCAxID0gTW9uZGF5LCBldGMuKVxuICAgKiBAcGFyYW0gbG9jYWxlIC0gTG9jYWxlIGlkZW50aWZpZXIgKG9wdGlvbmFsKVxuICAgKiBAcmV0dXJucyBDYWxlbmRhckdyaWQgLSBjYWNoZWQgb3IgbmV3bHkgY3JlYXRlZFxuICAgKi9cbiAgZ2V0KG1vbnRoRGF0ZTogRGF0ZSwgd2Vla1N0YXJ0OiBudW1iZXIgPSAwLCBsb2NhbGU/OiBzdHJpbmcpOiBDYWxlbmRhckdyaWQge1xuICAgIGNvbnN0IGtleSA9IHRoaXMuYnVpbGRLZXkobW9udGhEYXRlLCB3ZWVrU3RhcnQsIGxvY2FsZSk7XG5cbiAgICAvLyBDaGVjayBjYWNoZVxuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuY2FjaGUuZ2V0KGtleSk7XG4gICAgaWYgKGNhY2hlZCkge1xuICAgICAgLy8gTW92ZSB0byBlbmQgKExSVSlcbiAgICAgIHRoaXMuY2FjaGUuZGVsZXRlKGtleSk7XG4gICAgICB0aGlzLmNhY2hlLnNldChrZXksIGNhY2hlZCk7XG4gICAgICByZXR1cm4gY2FjaGVkO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIG5ldyBncmlkXG4gICAgY29uc3QgZ3JpZCA9IHRoaXMuZmFjdG9yeS5jcmVhdGVHcmlkKG1vbnRoRGF0ZSwgd2Vla1N0YXJ0LCBsb2NhbGUpO1xuXG4gICAgLy8gU3RvcmUgaW4gY2FjaGVcbiAgICB0aGlzLmNhY2hlLnNldChrZXksIGdyaWQpO1xuXG4gICAgLy8gRXZpY3Qgb2xkZXN0IGlmIG92ZXIgbGltaXQgKExSVSlcbiAgICBpZiAodGhpcy5jYWNoZS5zaXplID4gdGhpcy5tYXhTaXplKSB7XG4gICAgICBjb25zdCBmaXJzdEtleSA9IHRoaXMuY2FjaGUua2V5cygpLm5leHQoKS52YWx1ZTtcbiAgICAgIHRoaXMuY2FjaGUuZGVsZXRlKGZpcnN0S2V5KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JpZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBjYWNoZSBrZXkgZnJvbSBtb250aCBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIEZvcm1hdDogXCJ5ZWFyLW1vbnRoLXdlZWtTdGFydC1sb2NhbGVcIlxuICAgKiBFeGFtcGxlOiBcIjIwMjYtMS0wLWVuXCIgKEZlYiAyMDI2LCBTdW5kYXkgc3RhcnQsIEVuZ2xpc2gpXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkS2V5KG1vbnRoRGF0ZTogRGF0ZSwgd2Vla1N0YXJ0OiBudW1iZXIsIGxvY2FsZT86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgeWVhciA9IG1vbnRoRGF0ZS5nZXRGdWxsWWVhcigpO1xuICAgIGNvbnN0IG1vbnRoID0gbW9udGhEYXRlLmdldE1vbnRoKCk7XG4gICAgcmV0dXJuIGAke3llYXJ9LSR7bW9udGh9LSR7d2Vla1N0YXJ0fSR7bG9jYWxlID8gJy0nICsgbG9jYWxlIDogJyd9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBlbnRpcmUgY2FjaGUgKGZvciB0ZXN0aW5nIG9yIG1hbnVhbCByZXNldClcbiAgICovXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIHRoaXMuY2FjaGUuY2xlYXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY2FjaGUgc2l6ZSAoZm9yIGRlYnVnZ2luZy90ZXN0aW5nKVxuICAgKi9cbiAgc2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmNhY2hlLnNpemU7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYSBzcGVjaWZpYyBtb250aCBpcyBjYWNoZWRcbiAgICovXG4gIGhhcyhtb250aERhdGU6IERhdGUsIHdlZWtTdGFydDogbnVtYmVyID0gMCwgbG9jYWxlPzogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qga2V5ID0gdGhpcy5idWlsZEtleShtb250aERhdGUsIHdlZWtTdGFydCwgbG9jYWxlKTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZS5oYXMoa2V5KTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar Grid Factory
|
|
3
|
+
*
|
|
4
|
+
* Generates calendar month grids using DateAdapter for deterministic,
|
|
5
|
+
* timezone-safe date operations.
|
|
6
|
+
*
|
|
7
|
+
* Grid structure:
|
|
8
|
+
* - Always 6 weeks x 7 days (42 cells) for layout stability
|
|
9
|
+
* - Includes padding days from previous/next month
|
|
10
|
+
* - No decorations (selected, disabled, etc.) - those are applied separately
|
|
11
|
+
*/
|
|
12
|
+
import { Injectable, Inject } from '@angular/core';
|
|
13
|
+
import { DATE_ADAPTER } from '../date-adapter';
|
|
14
|
+
import * as i0 from "@angular/core";
|
|
15
|
+
export class CalendarGridFactory {
|
|
16
|
+
adapter;
|
|
17
|
+
constructor(adapter) {
|
|
18
|
+
this.adapter = adapter;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a calendar grid for a given month
|
|
22
|
+
*
|
|
23
|
+
* @param monthDate - Any date within the target month (will be normalized to start of month)
|
|
24
|
+
* @param weekStart - First day of week (0 = Sunday, 1 = Monday, etc.)
|
|
25
|
+
* @param locale - Locale identifier (optional, for future use)
|
|
26
|
+
* @returns CalendarGrid - 6 weeks x 7 days grid
|
|
27
|
+
*/
|
|
28
|
+
createGrid(monthDate, weekStart = 0, locale) {
|
|
29
|
+
// Normalize to start of month
|
|
30
|
+
const year = this.adapter.getYear(monthDate);
|
|
31
|
+
const month = this.adapter.getMonth(monthDate);
|
|
32
|
+
const firstDayOfMonth = new Date(year, month, 1);
|
|
33
|
+
const normalizedFirst = this.adapter.normalize(firstDayOfMonth);
|
|
34
|
+
// Get days in month (day 0 of next month = last day of current month)
|
|
35
|
+
const lastDayOfMonth = new Date(year, month + 1, 0);
|
|
36
|
+
const daysInMonth = this.adapter.getDate(lastDayOfMonth);
|
|
37
|
+
// Get first day of week offset
|
|
38
|
+
const firstDayOfWeek = this.adapter.getDay(normalizedFirst);
|
|
39
|
+
const offset = this.calculateOffset(firstDayOfWeek, weekStart);
|
|
40
|
+
// Generate 42 cells (6 weeks x 7 days)
|
|
41
|
+
const cells = [];
|
|
42
|
+
let currentDate = this.adapter.addDays(normalizedFirst, -offset);
|
|
43
|
+
for (let i = 0; i < 42; i++) {
|
|
44
|
+
const cellDate = this.adapter.normalize(currentDate);
|
|
45
|
+
const cellYear = this.adapter.getYear(cellDate);
|
|
46
|
+
const cellMonth = this.adapter.getMonth(cellDate);
|
|
47
|
+
const cellDay = this.adapter.getDate(cellDate);
|
|
48
|
+
const cellDayOfWeek = this.adapter.getDay(cellDate);
|
|
49
|
+
cells.push({
|
|
50
|
+
date: cellDate,
|
|
51
|
+
inCurrentMonth: cellYear === year && cellMonth === month,
|
|
52
|
+
iso: this.adapter.toISODate(cellDate),
|
|
53
|
+
day: cellDay,
|
|
54
|
+
month: cellMonth,
|
|
55
|
+
year: cellYear,
|
|
56
|
+
dayOfWeek: cellDayOfWeek
|
|
57
|
+
});
|
|
58
|
+
currentDate = this.adapter.addDays(currentDate, 1);
|
|
59
|
+
}
|
|
60
|
+
// Split into weeks
|
|
61
|
+
const weeks = [];
|
|
62
|
+
for (let i = 0; i < 6; i++) {
|
|
63
|
+
weeks.push(cells.slice(i * 7, (i + 1) * 7));
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
month: { year, month },
|
|
67
|
+
weekStart,
|
|
68
|
+
locale,
|
|
69
|
+
weeks,
|
|
70
|
+
cells
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Calculate offset (number of padding days from previous month)
|
|
75
|
+
*
|
|
76
|
+
* @param firstDayOfWeek - Day of week for first day of month (0-6)
|
|
77
|
+
* @param weekStart - Desired week start (0-6)
|
|
78
|
+
* @returns Number of padding days needed
|
|
79
|
+
*/
|
|
80
|
+
calculateOffset(firstDayOfWeek, weekStart) {
|
|
81
|
+
let offset = firstDayOfWeek - weekStart;
|
|
82
|
+
if (offset < 0) {
|
|
83
|
+
offset += 7;
|
|
84
|
+
}
|
|
85
|
+
return offset;
|
|
86
|
+
}
|
|
87
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridFactory, deps: [{ token: DATE_ADAPTER }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
88
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridFactory, providedIn: 'root' });
|
|
89
|
+
}
|
|
90
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CalendarGridFactory, decorators: [{
|
|
91
|
+
type: Injectable,
|
|
92
|
+
args: [{ providedIn: 'root' }]
|
|
93
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
94
|
+
type: Inject,
|
|
95
|
+
args: [DATE_ADAPTER]
|
|
96
|
+
}] }] });
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItZ3JpZC5mYWN0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvcmUvY2FsZW5kYXItZ3JpZC9jYWxlbmRhci1ncmlkLmZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBZSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7QUFJNUQsTUFBTSxPQUFPLG1CQUFtQjtJQUVFO0lBRGhDLFlBQ2dDLE9BQW9CO1FBQXBCLFlBQU8sR0FBUCxPQUFPLENBQWE7SUFDakQsQ0FBQztJQUVKOzs7Ozs7O09BT0c7SUFDSCxVQUFVLENBQUMsU0FBZSxFQUFFLFlBQW9CLENBQUMsRUFBRSxNQUFlO1FBQ2hFLDhCQUE4QjtRQUM5QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMvQyxNQUFNLGVBQWUsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBRWhFLHNFQUFzRTtRQUN0RSxNQUFNLGNBQWMsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNwRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV6RCwrQkFBK0I7UUFDL0IsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFL0QsdUNBQXVDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFtQixFQUFFLENBQUM7UUFDakMsSUFBSSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFakUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzVCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2hELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBRXBELEtBQUssQ0FBQyxJQUFJLENBQUM7Z0JBQ1QsSUFBSSxFQUFFLFFBQVE7Z0JBQ2QsY0FBYyxFQUFFLFFBQVEsS0FBSyxJQUFJLElBQUksU0FBUyxLQUFLLEtBQUs7Z0JBQ3hELEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7Z0JBQ3JDLEdBQUcsRUFBRSxPQUFPO2dCQUNaLEtBQUssRUFBRSxTQUFTO2dCQUNoQixJQUFJLEVBQUUsUUFBUTtnQkFDZCxTQUFTLEVBQUUsYUFBYTthQUN6QixDQUFDLENBQUM7WUFFSCxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCxtQkFBbUI7UUFDbkIsTUFBTSxLQUFLLEdBQXFCLEVBQUUsQ0FBQztRQUNuQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDM0IsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsT0FBTztZQUNMLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUU7WUFDdEIsU0FBUztZQUNULE1BQU07WUFDTixLQUFLO1lBQ0wsS0FBSztTQUNOLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssZUFBZSxDQUFDLGNBQXNCLEVBQUUsU0FBaUI7UUFDL0QsSUFBSSxNQUFNLEdBQUcsY0FBYyxHQUFHLFNBQVMsQ0FBQztRQUN4QyxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxDQUFDLENBQUM7UUFDZCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQzt3R0FoRlUsbUJBQW1CLGtCQUVwQixZQUFZOzRHQUZYLG1CQUFtQixjQUROLE1BQU07OzRGQUNuQixtQkFBbUI7a0JBRC9CLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFHN0IsTUFBTTsyQkFBQyxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDYWxlbmRhciBHcmlkIEZhY3RvcnlcbiAqXG4gKiBHZW5lcmF0ZXMgY2FsZW5kYXIgbW9udGggZ3JpZHMgdXNpbmcgRGF0ZUFkYXB0ZXIgZm9yIGRldGVybWluaXN0aWMsXG4gKiB0aW1lem9uZS1zYWZlIGRhdGUgb3BlcmF0aW9ucy5cbiAqXG4gKiBHcmlkIHN0cnVjdHVyZTpcbiAqIC0gQWx3YXlzIDYgd2Vla3MgeCA3IGRheXMgKDQyIGNlbGxzKSBmb3IgbGF5b3V0IHN0YWJpbGl0eVxuICogLSBJbmNsdWRlcyBwYWRkaW5nIGRheXMgZnJvbSBwcmV2aW91cy9uZXh0IG1vbnRoXG4gKiAtIE5vIGRlY29yYXRpb25zIChzZWxlY3RlZCwgZGlzYWJsZWQsIGV0Yy4pIC0gdGhvc2UgYXJlIGFwcGxpZWQgc2VwYXJhdGVseVxuICovXG5cbmltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRGF0ZUFkYXB0ZXIsIERBVEVfQURBUFRFUiB9IGZyb20gJy4uL2RhdGUtYWRhcHRlcic7XG5pbXBvcnQgeyBDYWxlbmRhckNlbGwsIENhbGVuZGFyR3JpZCB9IGZyb20gJy4vY2FsZW5kYXItZ3JpZC50eXBlcyc7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQ2FsZW5kYXJHcmlkRmFjdG9yeSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoREFURV9BREFQVEVSKSBwcml2YXRlIGFkYXB0ZXI6IERhdGVBZGFwdGVyXG4gICkge31cblxuICAvKipcbiAgICogQ3JlYXRlIGEgY2FsZW5kYXIgZ3JpZCBmb3IgYSBnaXZlbiBtb250aFxuICAgKlxuICAgKiBAcGFyYW0gbW9udGhEYXRlIC0gQW55IGRhdGUgd2l0aGluIHRoZSB0YXJnZXQgbW9udGggKHdpbGwgYmUgbm9ybWFsaXplZCB0byBzdGFydCBvZiBtb250aClcbiAgICogQHBhcmFtIHdlZWtTdGFydCAtIEZpcnN0IGRheSBvZiB3ZWVrICgwID0gU3VuZGF5LCAxID0gTW9uZGF5LCBldGMuKVxuICAgKiBAcGFyYW0gbG9jYWxlIC0gTG9jYWxlIGlkZW50aWZpZXIgKG9wdGlvbmFsLCBmb3IgZnV0dXJlIHVzZSlcbiAgICogQHJldHVybnMgQ2FsZW5kYXJHcmlkIC0gNiB3ZWVrcyB4IDcgZGF5cyBncmlkXG4gICAqL1xuICBjcmVhdGVHcmlkKG1vbnRoRGF0ZTogRGF0ZSwgd2Vla1N0YXJ0OiBudW1iZXIgPSAwLCBsb2NhbGU/OiBzdHJpbmcpOiBDYWxlbmRhckdyaWQge1xuICAgIC8vIE5vcm1hbGl6ZSB0byBzdGFydCBvZiBtb250aFxuICAgIGNvbnN0IHllYXIgPSB0aGlzLmFkYXB0ZXIuZ2V0WWVhcihtb250aERhdGUpO1xuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5hZGFwdGVyLmdldE1vbnRoKG1vbnRoRGF0ZSk7XG4gICAgY29uc3QgZmlyc3REYXlPZk1vbnRoID0gbmV3IERhdGUoeWVhciwgbW9udGgsIDEpO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRGaXJzdCA9IHRoaXMuYWRhcHRlci5ub3JtYWxpemUoZmlyc3REYXlPZk1vbnRoKTtcblxuICAgIC8vIEdldCBkYXlzIGluIG1vbnRoIChkYXkgMCBvZiBuZXh0IG1vbnRoID0gbGFzdCBkYXkgb2YgY3VycmVudCBtb250aClcbiAgICBjb25zdCBsYXN0RGF5T2ZNb250aCA9IG5ldyBEYXRlKHllYXIsIG1vbnRoICsgMSwgMCk7XG4gICAgY29uc3QgZGF5c0luTW9udGggPSB0aGlzLmFkYXB0ZXIuZ2V0RGF0ZShsYXN0RGF5T2ZNb250aCk7XG5cbiAgICAvLyBHZXQgZmlyc3QgZGF5IG9mIHdlZWsgb2Zmc2V0XG4gICAgY29uc3QgZmlyc3REYXlPZldlZWsgPSB0aGlzLmFkYXB0ZXIuZ2V0RGF5KG5vcm1hbGl6ZWRGaXJzdCk7XG4gICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5jYWxjdWxhdGVPZmZzZXQoZmlyc3REYXlPZldlZWssIHdlZWtTdGFydCk7XG5cbiAgICAvLyBHZW5lcmF0ZSA0MiBjZWxscyAoNiB3ZWVrcyB4IDcgZGF5cylcbiAgICBjb25zdCBjZWxsczogQ2FsZW5kYXJDZWxsW10gPSBbXTtcbiAgICBsZXQgY3VycmVudERhdGUgPSB0aGlzLmFkYXB0ZXIuYWRkRGF5cyhub3JtYWxpemVkRmlyc3QsIC1vZmZzZXQpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0MjsgaSsrKSB7XG4gICAgICBjb25zdCBjZWxsRGF0ZSA9IHRoaXMuYWRhcHRlci5ub3JtYWxpemUoY3VycmVudERhdGUpO1xuICAgICAgY29uc3QgY2VsbFllYXIgPSB0aGlzLmFkYXB0ZXIuZ2V0WWVhcihjZWxsRGF0ZSk7XG4gICAgICBjb25zdCBjZWxsTW9udGggPSB0aGlzLmFkYXB0ZXIuZ2V0TW9udGgoY2VsbERhdGUpO1xuICAgICAgY29uc3QgY2VsbERheSA9IHRoaXMuYWRhcHRlci5nZXREYXRlKGNlbGxEYXRlKTtcbiAgICAgIGNvbnN0IGNlbGxEYXlPZldlZWsgPSB0aGlzLmFkYXB0ZXIuZ2V0RGF5KGNlbGxEYXRlKTtcblxuICAgICAgY2VsbHMucHVzaCh7XG4gICAgICAgIGRhdGU6IGNlbGxEYXRlLFxuICAgICAgICBpbkN1cnJlbnRNb250aDogY2VsbFllYXIgPT09IHllYXIgJiYgY2VsbE1vbnRoID09PSBtb250aCxcbiAgICAgICAgaXNvOiB0aGlzLmFkYXB0ZXIudG9JU09EYXRlKGNlbGxEYXRlKSxcbiAgICAgICAgZGF5OiBjZWxsRGF5LFxuICAgICAgICBtb250aDogY2VsbE1vbnRoLFxuICAgICAgICB5ZWFyOiBjZWxsWWVhcixcbiAgICAgICAgZGF5T2ZXZWVrOiBjZWxsRGF5T2ZXZWVrXG4gICAgICB9KTtcblxuICAgICAgY3VycmVudERhdGUgPSB0aGlzLmFkYXB0ZXIuYWRkRGF5cyhjdXJyZW50RGF0ZSwgMSk7XG4gICAgfVxuXG4gICAgLy8gU3BsaXQgaW50byB3ZWVrc1xuICAgIGNvbnN0IHdlZWtzOiBDYWxlbmRhckNlbGxbXVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA2OyBpKyspIHtcbiAgICAgIHdlZWtzLnB1c2goY2VsbHMuc2xpY2UoaSAqIDcsIChpICsgMSkgKiA3KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIG1vbnRoOiB7IHllYXIsIG1vbnRoIH0sXG4gICAgICB3ZWVrU3RhcnQsXG4gICAgICBsb2NhbGUsXG4gICAgICB3ZWVrcyxcbiAgICAgIGNlbGxzXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgb2Zmc2V0IChudW1iZXIgb2YgcGFkZGluZyBkYXlzIGZyb20gcHJldmlvdXMgbW9udGgpXG4gICAqXG4gICAqIEBwYXJhbSBmaXJzdERheU9mV2VlayAtIERheSBvZiB3ZWVrIGZvciBmaXJzdCBkYXkgb2YgbW9udGggKDAtNilcbiAgICogQHBhcmFtIHdlZWtTdGFydCAtIERlc2lyZWQgd2VlayBzdGFydCAoMC02KVxuICAgKiBAcmV0dXJucyBOdW1iZXIgb2YgcGFkZGluZyBkYXlzIG5lZWRlZFxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVPZmZzZXQoZmlyc3REYXlPZldlZWs6IG51bWJlciwgd2Vla1N0YXJ0OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBvZmZzZXQgPSBmaXJzdERheU9mV2VlayAtIHdlZWtTdGFydDtcbiAgICBpZiAob2Zmc2V0IDwgMCkge1xuICAgICAgb2Zmc2V0ICs9IDc7XG4gICAgfVxuICAgIHJldHVybiBvZmZzZXQ7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
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
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXItZ3JpZC50eXBlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL2NhbGVuZGFyLWdyaWQvY2FsZW5kYXItZ3JpZC50eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2FsZW5kYXIgR3JpZCBUeXBlc1xuICpcbiAqIERlZmluZXMgdGhlIHN0cnVjdHVyZSBmb3IgbWVtb2l6ZWQgY2FsZW5kYXIgbW9udGggZ3JpZHMuXG4gKiBTZXBhcmF0ZXMgYmFzZSBncmlkIHN0cnVjdHVyZSAoY2FjaGVhYmxlKSBmcm9tIGRlY29yYXRpb25zIChkeW5hbWljKS5cbiAqL1xuXG4vKipcbiAqIEEgc2luZ2xlIGNhbGVuZGFyIGNlbGwgcmVwcmVzZW50aW5nIG9uZSBkYXlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYWxlbmRhckNlbGwge1xuICAvKiogRGF0ZSBvYmplY3QgKG5vcm1hbGl6ZWQgdG8gc3RhcnQgb2YgZGF5KSAqL1xuICBkYXRlOiBEYXRlO1xuXG4gIC8qKiBXaGV0aGVyIHRoaXMgZGF5IGJlbG9uZ3MgdG8gdGhlIGN1cnJlbnQgcmVuZGVyZWQgbW9udGggKi9cbiAgaW5DdXJyZW50TW9udGg6IGJvb2xlYW47XG5cbiAgLyoqIElTTyBzdHJpbmcgJ1lZWVktTU0tREQnICh0aW1lem9uZS1zYWZlIHZpYSBEYXRlQWRhcHRlcikgKi9cbiAgaXNvOiBzdHJpbmc7XG5cbiAgLyoqIERheSBvZiBtb250aCAoMS0zMSkgKi9cbiAgZGF5OiBudW1iZXI7XG5cbiAgLyoqIE1vbnRoICgwLTExLCBKYXZhU2NyaXB0IGNvbnZlbnRpb24pICovXG4gIG1vbnRoOiBudW1iZXI7XG5cbiAgLyoqIEZ1bGwgeWVhciAqL1xuICB5ZWFyOiBudW1iZXI7XG5cbiAgLyoqIERheSBvZiB3ZWVrICgwID0gU3VuZGF5LCA2ID0gU2F0dXJkYXkpICovXG4gIGRheU9mV2VlazogbnVtYmVyO1xufVxuXG4vKipcbiAqIEEgY2FsZW5kYXIgZ3JpZCByZXByZXNlbnRpbmcgb25lIG1vbnRoXG4gKlxuICogR3JpZCBpcyBhbHdheXMgNiB3ZWVrcyB4IDcgZGF5cyAoNDIgY2VsbHMpIGZvciBsYXlvdXQgc3RhYmlsaXR5LlxuICogSW5jbHVkZXMgcGFkZGluZyBkYXlzIGZyb20gcHJldmlvdXMvbmV4dCBtb250aC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYWxlbmRhckdyaWQge1xuICAvKiogTW9udGggaWRlbnRpZmllciAqL1xuICBtb250aDoge1xuICAgIC8qKiBZZWFyICovXG4gICAgeWVhcjogbnVtYmVyO1xuICAgIC8qKiBNb250aCAwLTExICovXG4gICAgbW9udGg6IG51bWJlcjtcbiAgfTtcblxuICAvKiogV2VlayBzdGFydCBkYXkgKDAgPSBTdW5kYXksIDEgPSBNb25kYXksIGV0Yy4pICovXG4gIHdlZWtTdGFydDogbnVtYmVyO1xuXG4gIC8qKiBMb2NhbGUgKGZvciBmdXR1cmUgaTE4biwgb3B0aW9uYWwpICovXG4gIGxvY2FsZT86IHN0cmluZztcblxuICAvKiogNiB3ZWVrcyB4IDcgZGF5cyBtYXRyaXggKi9cbiAgd2Vla3M6IENhbGVuZGFyQ2VsbFtdW107XG5cbiAgLyoqIEZsYXQgYXJyYXkgb2YgYWxsIGNlbGxzIChjb252ZW5pZW5jZSBhY2Nlc3NvcikgKi9cbiAgY2VsbHM6IENhbGVuZGFyQ2VsbFtdO1xufVxuXG4vKipcbiAqIENhY2hlIGtleSBmb3IgY2FsZW5kYXIgZ3JpZHNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYWxlbmRhckdyaWRDYWNoZUtleSB7XG4gIHllYXI6IG51bWJlcjtcbiAgbW9udGg6IG51bWJlcjtcbiAgd2Vla1N0YXJ0OiBudW1iZXI7XG4gIGxvY2FsZT86IHN0cmluZztcbn1cbiJdfQ==
|
|
@@ -0,0 +1,51 @@
|
|
|
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';
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9jYWxlbmRhci1ncmlkL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlDRztBQUVILGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyx1QkFBdUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2FsZW5kYXIgR3JpZCBNb2R1bGVcbiAqXG4gKiBQZXJmb3JtYW5jZS1vcHRpbWl6ZWQgY2FsZW5kYXIgbW9udGggZ3JpZCBnZW5lcmF0aW9uIHdpdGggbWVtb2l6YXRpb24uXG4gKlxuICogdjMuNy4wOiBHcmlkIFN0cnVjdHVyZSBDYWNoZVxuICogLSBDYWxlbmRhckdyaWRGYWN0b3J5IGZvciBkZXRlcm1pbmlzdGljIDQyLWNlbGwgZ3JpZHNcbiAqIC0gQ2FsZW5kYXJHcmlkQ2FjaGUgd2l0aCBMUlUgKDI0IG1vbnRocylcbiAqIFxuICogdjMuOC4wOiBSYW5nZSBIaWdobGlnaHQgQ2FjaGVcbiAqIC0gUmFuZ2VIaWdobGlnaHRlciBmb3IgZGVjb3JhdGlvbiBsb2dpY1xuICogLSBSYW5nZUhpZ2hsaWdodGVyQ2FjaGUgd2l0aCBMUlUgKDQ4IGdyaWRzKVxuICogLSBTZXBhcmF0ZXMgZ3JpZCBzdHJ1Y3R1cmUgZnJvbSBkZWNvcmF0aW9uc1xuICogXG4gKiB2My45LjA6IFZpcnR1YWwgV2Vla3MgKFdpbmRvd2VkIFJlbmRlcmluZylcbiAqIC0gVmlydHVhbC13ZWVrcyBsb2dpYyBmb3IgcmVkdWNlZCBET00gY29tcGxleGl0eVxuICogLSBSZW5kZXIgb25seSB2aXNpYmxlIHdlZWtzIChjb25maWd1cmFibGUgd2luZG93KVxuICogLSB+NTAlIHJlZHVjdGlvbiBpbiBET00gbm9kZXMgd2l0aCB3aW5kb3dTaXplPTNcbiAqXG4gKiBVc2FnZTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0cnVjdG9yKFxuICogICBwcml2YXRlIGdyaWRDYWNoZTogQ2FsZW5kYXJHcmlkQ2FjaGUsXG4gKiAgIHByaXZhdGUgaGlnaGxpZ2h0ZXJDYWNoZTogUmFuZ2VIaWdobGlnaHRlckNhY2hlXG4gKiApIHt9XG4gKlxuICogY29uc3QgZ3JpZCA9IHRoaXMuZ3JpZENhY2hlLmdldChtb250aERhdGUsIHdlZWtTdGFydCk7XG4gKiBjb25zdCBkZWNvcmF0ZWQgPSB0aGlzLmhpZ2hsaWdodGVyQ2FjaGUuZ2V0KGdyaWQsIHtcbiAqICAgc3RhcnQsIGVuZCwgaG92ZXJEYXRlLCBkaXNhYmxlZERhdGVzXG4gKiB9KTtcbiAqIFxuICogLy8gT3B0aW9uYWw6IFdpbmRvd2VkIHJlbmRlcmluZyAodjMuOS4wKylcbiAqIGNvbnN0IHdpbmRvd1NpemUgPSAzOyAvLyBSZW5kZXIgb25seSAzIHdlZWtzXG4gKiBjb25zdCB2aXNpYmxlV2Vla3MgPSBnZXRWaXNpYmxlV2Vla3MoXG4gKiAgIGRlY29yYXRlZC53ZWVrcywgXG4gKiAgIHdlZWtTdGFydEluZGV4LCBcbiAqICAgd2luZG93U2l6ZVxuICogKTtcbiAqIC8vIGRlY29yYXRlZC5jZWxsc1swXS5pc28gPT4gJzIwMjYtMDItMDEnXG4gKiAvLyBkZWNvcmF0ZWQuY2VsbHNbMF0uaXNJblJhbmdlID0+IHRydWVcbiAqIGBgYFxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vY2FsZW5kYXItZ3JpZC50eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL2NhbGVuZGFyLWdyaWQuZmFjdG9yeSc7XG5leHBvcnQgKiBmcm9tICcuL2NhbGVuZGFyLWdyaWQuY2FjaGUnO1xuZXhwb3J0ICogZnJvbSAnLi9yYW5nZS1oaWdobGlnaHRlci50eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL3JhbmdlLWhpZ2hsaWdodGVyJztcbmV4cG9ydCAqIGZyb20gJy4vcmFuZ2UtaGlnaGxpZ2h0ZXIuY2FjaGUnO1xuZXhwb3J0ICogZnJvbSAnLi92aXJ0dWFsLXdlZWtzLnR5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vdmlydHVhbC13ZWVrcy5sb2dpYyc7XG4iXX0=
|