@oneluiz/dual-datepicker 3.4.0 → 3.5.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/README.md +86 -1
- package/core/dual-date-range.store.d.ts +104 -0
- package/core/index.d.ts +7 -0
- package/core/preset.engine.d.ts +54 -0
- package/core/range.validator.d.ts +37 -0
- package/esm2022/core/dual-date-range.store.mjs +293 -0
- package/esm2022/core/index.mjs +8 -0
- package/esm2022/core/preset.engine.mjs +209 -0
- package/esm2022/core/range.validator.mjs +105 -0
- package/esm2022/public-api.mjs +5 -2
- package/fesm2022/oneluiz-dual-datepicker.mjs +608 -1
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +2 -2
- package/public-api.d.ts +1 -0
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A lightweight, zero-dependency date range picker for Angular 17+. Built with standalone components, Reactive Forms, and Angular Signals. No Angular Material required.
|
|
4
4
|
|
|
5
|
+
> **🆕 NEW in v3.5.0**: [**Headless Architecture**](HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
|
|
6
|
+
|
|
5
7
|
[](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
|
|
6
8
|
[](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
|
|
7
9
|

|
|
@@ -17,6 +19,35 @@ npm install @oneluiz/dual-datepicker
|
|
|
17
19
|
|
|
18
20
|
---
|
|
19
21
|
|
|
22
|
+
## 🌟 What's New
|
|
23
|
+
|
|
24
|
+
### Headless Architecture (v3.5.0)
|
|
25
|
+
|
|
26
|
+
Use date range logic **without the UI component**:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// Inject the store anywhere - no UI needed!
|
|
30
|
+
const rangeStore = inject(DualDateRangeStore);
|
|
31
|
+
|
|
32
|
+
// Apply preset
|
|
33
|
+
rangeStore.applyPreset('THIS_MONTH');
|
|
34
|
+
|
|
35
|
+
// Use in API calls
|
|
36
|
+
const range = rangeStore.range();
|
|
37
|
+
http.get(`/api/sales?start=${range.start}&end=${range.end}`);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Perfect for:**
|
|
41
|
+
- 📊 Dashboard filters (control multiple charts)
|
|
42
|
+
- 🏢 SSR applications
|
|
43
|
+
- 🔄 Global state management
|
|
44
|
+
- 🎯 Service-layer filtering
|
|
45
|
+
- 📈 Analytics and BI tools
|
|
46
|
+
|
|
47
|
+
**[📖 Read the Headless Architecture Guide →](HEADLESS.md)**
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
20
51
|
## 📋 Table of Contents
|
|
21
52
|
|
|
22
53
|
- [Features](#-features)
|
|
@@ -26,6 +57,7 @@ npm install @oneluiz/dual-datepicker
|
|
|
26
57
|
- [Basic Usage](#basic-usage)
|
|
27
58
|
- [Reactive Forms](#with-reactive-forms)
|
|
28
59
|
- [Angular Signals](#with-angular-signals)
|
|
60
|
+
- [Headless Usage](#headless-usage-new) ⭐ NEW
|
|
29
61
|
- [Advanced Features](#-advanced-features)
|
|
30
62
|
- [Multi-Range Selection](#multi-range-support)
|
|
31
63
|
- [Disabled Dates](#disabled-dates)
|
|
@@ -169,6 +201,52 @@ dateRange = signal<DateRange | null>(null);
|
|
|
169
201
|
</ngx-dual-datepicker>
|
|
170
202
|
```
|
|
171
203
|
|
|
204
|
+
### Headless Usage (NEW) ⭐
|
|
205
|
+
|
|
206
|
+
**Use date range state WITHOUT the UI component** - perfect for SSR, services, and global filters!
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { Component, inject } from '@angular/core';
|
|
210
|
+
import { DualDateRangeStore } from '@oneluiz/dual-datepicker';
|
|
211
|
+
import { HttpClient } from '@angular/common/http';
|
|
212
|
+
|
|
213
|
+
@Component({
|
|
214
|
+
template: `
|
|
215
|
+
<div class="dashboard">
|
|
216
|
+
<button (click)="setPreset('TODAY')">Today</button>
|
|
217
|
+
<button (click)="setPreset('THIS_MONTH')">This Month</button>
|
|
218
|
+
<p>{{ rangeText() }}</p>
|
|
219
|
+
</div>
|
|
220
|
+
`
|
|
221
|
+
})
|
|
222
|
+
export class DashboardComponent {
|
|
223
|
+
private rangeStore = inject(DualDateRangeStore);
|
|
224
|
+
private http = inject(HttpClient);
|
|
225
|
+
|
|
226
|
+
// Expose signals for template
|
|
227
|
+
rangeText = this.rangeStore.rangeText;
|
|
228
|
+
|
|
229
|
+
setPreset(key: string) {
|
|
230
|
+
this.rangeStore.applyPreset(key);
|
|
231
|
+
|
|
232
|
+
// Use in API call
|
|
233
|
+
const range = this.rangeStore.range();
|
|
234
|
+
this.http.get(`/api/sales`, {
|
|
235
|
+
params: { start: range.start, end: range.end }
|
|
236
|
+
}).subscribe(data => console.log(data));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Benefits:**
|
|
242
|
+
- ✅ No UI component needed
|
|
243
|
+
- ✅ SSR-compatible
|
|
244
|
+
- ✅ Global state management
|
|
245
|
+
- ✅ Perfect for services and guards
|
|
246
|
+
- ✅ Testable and deterministic
|
|
247
|
+
|
|
248
|
+
**[📖 Full Headless Architecture Guide →](HEADLESS.md)** | **[💻 Code Examples →](HEADLESS_EXAMPLES.ts)**
|
|
249
|
+
|
|
172
250
|
---
|
|
173
251
|
|
|
174
252
|
## 🎯 Advanced Features
|
|
@@ -1998,6 +2076,12 @@ export class ExampleComponent {
|
|
|
1998
2076
|
|
|
1999
2077
|
Recently shipped:
|
|
2000
2078
|
|
|
2079
|
+
**v3.4.0:**
|
|
2080
|
+
- ✅ **Time Picker** - Select precise datetime ranges with 12h/24h format
|
|
2081
|
+
- ✅ **Configurable Minute Steps** - Choose 1, 5, 15, or 30-minute intervals
|
|
2082
|
+
- ✅ **Default Times** - Set default start/end times
|
|
2083
|
+
- ✅ **Full Theme Support** - Works seamlessly with all built-in themes
|
|
2084
|
+
|
|
2001
2085
|
**v3.3.0:**
|
|
2002
2086
|
- ✅ **Theming System** - Pre-built themes for Bootstrap, Bulma, Foundation, Tailwind CSS, and Custom
|
|
2003
2087
|
- ✅ **CSS Variables Support** - 13 customizable variables for branding
|
|
@@ -2025,9 +2109,10 @@ Recently shipped:
|
|
|
2025
2109
|
|
|
2026
2110
|
Planned features:
|
|
2027
2111
|
|
|
2028
|
-
- ⬜ **Time Picker** - Select date + time ranges
|
|
2029
2112
|
- ⬜ **Mobile Optimizations** - Enhanced touch gestures and responsive layout
|
|
2030
2113
|
- ⬜ **Range Shortcuts** - Quick selection buttons (Today, This Week, etc.)
|
|
2114
|
+
- ⬜ **Time Constraints** - Min/max time validation and business hours
|
|
2115
|
+
- ⬜ **Multi-range + Time Picker** - Combined support for multiple datetime ranges
|
|
2031
2116
|
|
|
2032
2117
|
## 📄 License
|
|
2033
2118
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export interface DateRangeState {
|
|
3
|
+
start: string;
|
|
4
|
+
end: string;
|
|
5
|
+
startTime?: string;
|
|
6
|
+
endTime?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DateRangeConfig {
|
|
9
|
+
minDate?: Date;
|
|
10
|
+
maxDate?: Date;
|
|
11
|
+
disabledDates?: Date[] | ((date: Date) => boolean);
|
|
12
|
+
enableTimePicker?: boolean;
|
|
13
|
+
defaultStartTime?: string;
|
|
14
|
+
defaultEndTime?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class DualDateRangeStore {
|
|
17
|
+
private config;
|
|
18
|
+
private _startDate;
|
|
19
|
+
private _endDate;
|
|
20
|
+
private _leftMonth;
|
|
21
|
+
private _rightMonth;
|
|
22
|
+
private _selectingStart;
|
|
23
|
+
private _startTime;
|
|
24
|
+
private _endTime;
|
|
25
|
+
private _pendingStart;
|
|
26
|
+
private _pendingEnd;
|
|
27
|
+
private _hasPendingChanges;
|
|
28
|
+
readonly startDate: import("@angular/core").Signal<Date>;
|
|
29
|
+
readonly endDate: import("@angular/core").Signal<Date>;
|
|
30
|
+
readonly leftMonth: import("@angular/core").Signal<Date>;
|
|
31
|
+
readonly rightMonth: import("@angular/core").Signal<Date>;
|
|
32
|
+
readonly selectingStart: import("@angular/core").Signal<boolean>;
|
|
33
|
+
readonly startTime: import("@angular/core").Signal<string>;
|
|
34
|
+
readonly endTime: import("@angular/core").Signal<string>;
|
|
35
|
+
readonly hasPendingChanges: import("@angular/core").Signal<boolean>;
|
|
36
|
+
readonly range: import("@angular/core").Signal<DateRangeState>;
|
|
37
|
+
readonly isValid: import("@angular/core").Signal<boolean>;
|
|
38
|
+
readonly rangeText: import("@angular/core").Signal<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Configure the store
|
|
41
|
+
*/
|
|
42
|
+
configure(config: Partial<DateRangeConfig>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Set start date (with validation)
|
|
45
|
+
*/
|
|
46
|
+
setStart(date: Date | string | null): void;
|
|
47
|
+
/**
|
|
48
|
+
* Set end date (with validation)
|
|
49
|
+
*/
|
|
50
|
+
setEnd(date: Date | string | null): void;
|
|
51
|
+
/**
|
|
52
|
+
* Set complete range at once
|
|
53
|
+
*/
|
|
54
|
+
setRange(start: Date | string | null, end: Date | string | null): void;
|
|
55
|
+
/**
|
|
56
|
+
* Set pending selection (for requireApply mode)
|
|
57
|
+
*/
|
|
58
|
+
setPendingStart(date: Date | string | null): void;
|
|
59
|
+
setPendingEnd(date: Date | string | null): void;
|
|
60
|
+
/**
|
|
61
|
+
* Apply pending changes
|
|
62
|
+
*/
|
|
63
|
+
applyPending(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Cancel pending changes
|
|
66
|
+
*/
|
|
67
|
+
cancelPending(): void;
|
|
68
|
+
private clearPending;
|
|
69
|
+
/**
|
|
70
|
+
* Reset to empty state
|
|
71
|
+
*/
|
|
72
|
+
reset(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Apply a preset by key
|
|
75
|
+
*/
|
|
76
|
+
applyPreset(presetKey: string, now?: Date): void;
|
|
77
|
+
/**
|
|
78
|
+
* Navigate left calendar month
|
|
79
|
+
*/
|
|
80
|
+
setLeftMonth(date: Date): void;
|
|
81
|
+
/**
|
|
82
|
+
* Navigate right calendar month
|
|
83
|
+
*/
|
|
84
|
+
setRightMonth(date: Date): void;
|
|
85
|
+
/**
|
|
86
|
+
* Set time values
|
|
87
|
+
*/
|
|
88
|
+
setStartTime(time: string): void;
|
|
89
|
+
setEndTime(time: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Get current state as snapshot
|
|
92
|
+
*/
|
|
93
|
+
getSnapshot(): DateRangeState;
|
|
94
|
+
/**
|
|
95
|
+
* Load state from snapshot
|
|
96
|
+
*/
|
|
97
|
+
loadSnapshot(snapshot: DateRangeState): void;
|
|
98
|
+
private parseDate;
|
|
99
|
+
private getNextMonth;
|
|
100
|
+
private getPreviousMonth;
|
|
101
|
+
private formatDateShort;
|
|
102
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DualDateRangeStore, never>;
|
|
103
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<DualDateRangeStore>;
|
|
104
|
+
}
|
package/core/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless Preset Engine
|
|
3
|
+
* Pure functions that resolve date ranges WITHOUT render dependency
|
|
4
|
+
* Perfect for SSR, global state, dashboard filters
|
|
5
|
+
*/
|
|
6
|
+
export interface RangePreset {
|
|
7
|
+
/**
|
|
8
|
+
* Resolve preset to actual date range
|
|
9
|
+
* @param now - Current date for deterministic calculation
|
|
10
|
+
*/
|
|
11
|
+
resolve(now: Date): {
|
|
12
|
+
start: Date;
|
|
13
|
+
end: Date;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface PresetRange {
|
|
17
|
+
start: string;
|
|
18
|
+
end: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Registry of built-in presets
|
|
22
|
+
* Can be extended by consumers
|
|
23
|
+
*/
|
|
24
|
+
export declare class PresetEngine {
|
|
25
|
+
private presets;
|
|
26
|
+
constructor();
|
|
27
|
+
/**
|
|
28
|
+
* Register a custom preset
|
|
29
|
+
*/
|
|
30
|
+
register(key: string, preset: RangePreset): void;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a preset to date range
|
|
33
|
+
*/
|
|
34
|
+
resolve(key: string, now?: Date): PresetRange | null;
|
|
35
|
+
/**
|
|
36
|
+
* Get all available preset keys
|
|
37
|
+
*/
|
|
38
|
+
getPresetKeys(): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Register all built-in presets
|
|
41
|
+
*/
|
|
42
|
+
private registerBuiltInPresets;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a custom preset from a function
|
|
46
|
+
*/
|
|
47
|
+
export declare function createPreset(resolver: (now: Date) => {
|
|
48
|
+
start: Date;
|
|
49
|
+
end: Date;
|
|
50
|
+
}): RangePreset;
|
|
51
|
+
/**
|
|
52
|
+
* Singleton preset engine instance
|
|
53
|
+
*/
|
|
54
|
+
export declare const presetEngine: PresetEngine;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure validation functions for date ranges
|
|
3
|
+
* No dependencies, no side effects - just logic
|
|
4
|
+
* Perfect for SSR, testing, and reusability
|
|
5
|
+
*/
|
|
6
|
+
export interface ValidationResult {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validate that end date is not before start date
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateRangeOrder(start: Date | null, end: Date | null): ValidationResult;
|
|
14
|
+
/**
|
|
15
|
+
* Validate that date is within min/max bounds
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateDateBounds(date: Date | null, minDate?: Date, maxDate?: Date): ValidationResult;
|
|
18
|
+
/**
|
|
19
|
+
* Validate that a range is within bounds
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateRangeBounds(start: Date | null, end: Date | null, minDate?: Date, maxDate?: Date): ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a date is disabled
|
|
24
|
+
*/
|
|
25
|
+
export declare function isDateDisabled(date: Date, disabledDates?: Date[] | ((date: Date) => boolean)): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Apply bounds to a date (clamp it)
|
|
28
|
+
*/
|
|
29
|
+
export declare function applyBounds(date: Date, minDate?: Date, maxDate?: Date): Date;
|
|
30
|
+
/**
|
|
31
|
+
* Parse ISO date string to Date object (deterministic)
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseISODate(dateStr: string): Date | null;
|
|
34
|
+
/**
|
|
35
|
+
* Format Date to ISO string (YYYY-MM-DD)
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatISODate(date: Date | null): string;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless Date Range Store using Angular Signals
|
|
3
|
+
*
|
|
4
|
+
* Architecture:
|
|
5
|
+
* - State lives HERE, not in UI component
|
|
6
|
+
* - Deterministic: no hidden side effects
|
|
7
|
+
* - SSR-compatible: no window/document dependencies
|
|
8
|
+
* - Testable: pure signal-based state
|
|
9
|
+
* - Reusable: inject anywhere (services, components, guards)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // In component
|
|
14
|
+
* const rangeStore = inject(DualDateRangeStore);
|
|
15
|
+
* rangeStore.applyPreset('THIS_MONTH');
|
|
16
|
+
*
|
|
17
|
+
* // In service (headless!)
|
|
18
|
+
* const store = inject(DualDateRangeStore);
|
|
19
|
+
* const range = store.range();
|
|
20
|
+
* this.http.get(`/api/sales?start=${range.start}&end=${range.end}`);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { Injectable, signal, computed } from '@angular/core';
|
|
24
|
+
import { validateRangeOrder, validateRangeBounds, isDateDisabled, applyBounds, parseISODate, formatISODate } from './range.validator';
|
|
25
|
+
import { presetEngine } from './preset.engine';
|
|
26
|
+
import * as i0 from "@angular/core";
|
|
27
|
+
export class DualDateRangeStore {
|
|
28
|
+
// Configuration
|
|
29
|
+
config = signal({
|
|
30
|
+
enableTimePicker: false,
|
|
31
|
+
defaultStartTime: '00:00',
|
|
32
|
+
defaultEndTime: '23:59'
|
|
33
|
+
});
|
|
34
|
+
// Core state - using signals
|
|
35
|
+
_startDate = signal(null);
|
|
36
|
+
_endDate = signal(null);
|
|
37
|
+
_leftMonth = signal(new Date());
|
|
38
|
+
_rightMonth = signal(this.getNextMonth(new Date()));
|
|
39
|
+
_selectingStart = signal(true);
|
|
40
|
+
// Time state
|
|
41
|
+
_startTime = signal('00:00');
|
|
42
|
+
_endTime = signal('23:59');
|
|
43
|
+
// Pending state for requireApply mode
|
|
44
|
+
_pendingStart = signal(null);
|
|
45
|
+
_pendingEnd = signal(null);
|
|
46
|
+
_hasPendingChanges = signal(false);
|
|
47
|
+
// Public read-only signals
|
|
48
|
+
startDate = this._startDate.asReadonly();
|
|
49
|
+
endDate = this._endDate.asReadonly();
|
|
50
|
+
leftMonth = this._leftMonth.asReadonly();
|
|
51
|
+
rightMonth = this._rightMonth.asReadonly();
|
|
52
|
+
selectingStart = this._selectingStart.asReadonly();
|
|
53
|
+
startTime = this._startTime.asReadonly();
|
|
54
|
+
endTime = this._endTime.asReadonly();
|
|
55
|
+
hasPendingChanges = this._hasPendingChanges.asReadonly();
|
|
56
|
+
// Computed: ISO range for API consumption
|
|
57
|
+
range = computed(() => {
|
|
58
|
+
const start = this._startDate();
|
|
59
|
+
const end = this._endDate();
|
|
60
|
+
const cfg = this.config();
|
|
61
|
+
const result = {
|
|
62
|
+
start: formatISODate(start),
|
|
63
|
+
end: formatISODate(end)
|
|
64
|
+
};
|
|
65
|
+
if (cfg.enableTimePicker) {
|
|
66
|
+
result.startTime = this._startTime();
|
|
67
|
+
result.endTime = this._endTime();
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
});
|
|
71
|
+
// Computed: validation state
|
|
72
|
+
isValid = computed(() => {
|
|
73
|
+
const start = this._startDate();
|
|
74
|
+
const end = this._endDate();
|
|
75
|
+
const cfg = this.config();
|
|
76
|
+
const orderValidation = validateRangeOrder(start, end);
|
|
77
|
+
if (!orderValidation.valid)
|
|
78
|
+
return false;
|
|
79
|
+
const boundsValidation = validateRangeBounds(start, end, cfg.minDate, cfg.maxDate);
|
|
80
|
+
return boundsValidation.valid;
|
|
81
|
+
});
|
|
82
|
+
// Computed: range text for display
|
|
83
|
+
rangeText = computed(() => {
|
|
84
|
+
const start = this._startDate();
|
|
85
|
+
const end = this._endDate();
|
|
86
|
+
if (!start && !end)
|
|
87
|
+
return '';
|
|
88
|
+
if (!start)
|
|
89
|
+
return `? - ${this.formatDateShort(end)}`;
|
|
90
|
+
if (!end)
|
|
91
|
+
return `${this.formatDateShort(start)}`;
|
|
92
|
+
return `${this.formatDateShort(start)} - ${this.formatDateShort(end)}`;
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
95
|
+
* Configure the store
|
|
96
|
+
*/
|
|
97
|
+
configure(config) {
|
|
98
|
+
this.config.update(current => ({ ...current, ...config }));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Set start date (with validation)
|
|
102
|
+
*/
|
|
103
|
+
setStart(date) {
|
|
104
|
+
const parsedDate = this.parseDate(date);
|
|
105
|
+
if (parsedDate) {
|
|
106
|
+
const cfg = this.config();
|
|
107
|
+
// Apply bounds
|
|
108
|
+
const boundedDate = applyBounds(parsedDate, cfg.minDate, cfg.maxDate);
|
|
109
|
+
// Check if disabled
|
|
110
|
+
if (isDateDisabled(boundedDate, cfg.disabledDates)) {
|
|
111
|
+
console.warn('Cannot select disabled date');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this._startDate.set(boundedDate);
|
|
115
|
+
this._selectingStart.set(false);
|
|
116
|
+
// Auto-adjust end if it becomes invalid
|
|
117
|
+
const end = this._endDate();
|
|
118
|
+
if (end && end < boundedDate) {
|
|
119
|
+
this._endDate.set(null);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this._startDate.set(null);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Set end date (with validation)
|
|
128
|
+
*/
|
|
129
|
+
setEnd(date) {
|
|
130
|
+
const parsedDate = this.parseDate(date);
|
|
131
|
+
if (parsedDate) {
|
|
132
|
+
const cfg = this.config();
|
|
133
|
+
// Apply bounds
|
|
134
|
+
const boundedDate = applyBounds(parsedDate, cfg.minDate, cfg.maxDate);
|
|
135
|
+
// Check if disabled
|
|
136
|
+
if (isDateDisabled(boundedDate, cfg.disabledDates)) {
|
|
137
|
+
console.warn('Cannot select disabled date');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Validate order
|
|
141
|
+
const start = this._startDate();
|
|
142
|
+
if (start && boundedDate < start) {
|
|
143
|
+
console.warn('End date cannot be before start date');
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this._endDate.set(boundedDate);
|
|
147
|
+
this._selectingStart.set(true); // Ready for next selection
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
this._endDate.set(null);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Set complete range at once
|
|
155
|
+
*/
|
|
156
|
+
setRange(start, end) {
|
|
157
|
+
this.setStart(start);
|
|
158
|
+
this.setEnd(end);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Set pending selection (for requireApply mode)
|
|
162
|
+
*/
|
|
163
|
+
setPendingStart(date) {
|
|
164
|
+
const parsedDate = this.parseDate(date);
|
|
165
|
+
this._pendingStart.set(parsedDate);
|
|
166
|
+
this._hasPendingChanges.set(true);
|
|
167
|
+
}
|
|
168
|
+
setPendingEnd(date) {
|
|
169
|
+
const parsedDate = this.parseDate(date);
|
|
170
|
+
this._pendingEnd.set(parsedDate);
|
|
171
|
+
this._hasPendingChanges.set(true);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Apply pending changes
|
|
175
|
+
*/
|
|
176
|
+
applyPending() {
|
|
177
|
+
const pendingStart = this._pendingStart();
|
|
178
|
+
const pendingEnd = this._pendingEnd();
|
|
179
|
+
if (pendingStart)
|
|
180
|
+
this.setStart(pendingStart);
|
|
181
|
+
if (pendingEnd)
|
|
182
|
+
this.setEnd(pendingEnd);
|
|
183
|
+
this.clearPending();
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Cancel pending changes
|
|
187
|
+
*/
|
|
188
|
+
cancelPending() {
|
|
189
|
+
this.clearPending();
|
|
190
|
+
}
|
|
191
|
+
clearPending() {
|
|
192
|
+
this._pendingStart.set(null);
|
|
193
|
+
this._pendingEnd.set(null);
|
|
194
|
+
this._hasPendingChanges.set(false);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Reset to empty state
|
|
198
|
+
*/
|
|
199
|
+
reset() {
|
|
200
|
+
this._startDate.set(null);
|
|
201
|
+
this._endDate.set(null);
|
|
202
|
+
this._selectingStart.set(true);
|
|
203
|
+
this.clearPending();
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Apply a preset by key
|
|
207
|
+
*/
|
|
208
|
+
applyPreset(presetKey, now = new Date()) {
|
|
209
|
+
const range = presetEngine.resolve(presetKey, now);
|
|
210
|
+
if (range) {
|
|
211
|
+
this.setRange(range.start, range.end);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
console.warn(`Preset "${presetKey}" not found`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Navigate left calendar month
|
|
219
|
+
*/
|
|
220
|
+
setLeftMonth(date) {
|
|
221
|
+
this._leftMonth.set(date);
|
|
222
|
+
// Ensure right month is always after left
|
|
223
|
+
const right = this._rightMonth();
|
|
224
|
+
if (right <= date) {
|
|
225
|
+
this._rightMonth.set(this.getNextMonth(date));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Navigate right calendar month
|
|
230
|
+
*/
|
|
231
|
+
setRightMonth(date) {
|
|
232
|
+
this._rightMonth.set(date);
|
|
233
|
+
// Ensure left month is always before right
|
|
234
|
+
const left = this._leftMonth();
|
|
235
|
+
if (left >= date) {
|
|
236
|
+
this._leftMonth.set(this.getPreviousMonth(date));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Set time values
|
|
241
|
+
*/
|
|
242
|
+
setStartTime(time) {
|
|
243
|
+
this._startTime.set(time);
|
|
244
|
+
}
|
|
245
|
+
setEndTime(time) {
|
|
246
|
+
this._endTime.set(time);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get current state as snapshot
|
|
250
|
+
*/
|
|
251
|
+
getSnapshot() {
|
|
252
|
+
return this.range();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Load state from snapshot
|
|
256
|
+
*/
|
|
257
|
+
loadSnapshot(snapshot) {
|
|
258
|
+
this.setRange(snapshot.start, snapshot.end);
|
|
259
|
+
if (snapshot.startTime) {
|
|
260
|
+
this.setStartTime(snapshot.startTime);
|
|
261
|
+
}
|
|
262
|
+
if (snapshot.endTime) {
|
|
263
|
+
this.setEndTime(snapshot.endTime);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Helper methods
|
|
267
|
+
parseDate(date) {
|
|
268
|
+
if (!date)
|
|
269
|
+
return null;
|
|
270
|
+
if (date instanceof Date)
|
|
271
|
+
return date;
|
|
272
|
+
return parseISODate(date);
|
|
273
|
+
}
|
|
274
|
+
getNextMonth(date) {
|
|
275
|
+
return new Date(date.getFullYear(), date.getMonth() + 1, 1);
|
|
276
|
+
}
|
|
277
|
+
getPreviousMonth(date) {
|
|
278
|
+
return new Date(date.getFullYear(), date.getMonth() - 1, 1);
|
|
279
|
+
}
|
|
280
|
+
formatDateShort(date) {
|
|
281
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
282
|
+
return `${date.getDate()} ${months[date.getMonth()]}`;
|
|
283
|
+
}
|
|
284
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
285
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, providedIn: 'root' });
|
|
286
|
+
}
|
|
287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, decorators: [{
|
|
288
|
+
type: Injectable,
|
|
289
|
+
args: [{
|
|
290
|
+
providedIn: 'root'
|
|
291
|
+
}]
|
|
292
|
+
}] });
|
|
293
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVhbC1kYXRlLXJhbmdlLnN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvZHVhbC1kYXRlLXJhbmdlLnN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQWtCLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsbUJBQW1CLEVBQ25CLGNBQWMsRUFDZCxXQUFXLEVBQ1gsWUFBWSxFQUNaLGFBQWEsRUFDZCxNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sRUFBRSxZQUFZLEVBQWUsTUFBTSxpQkFBaUIsQ0FBQzs7QUFxQjVELE1BQU0sT0FBTyxrQkFBa0I7SUFDN0IsZ0JBQWdCO0lBQ1IsTUFBTSxHQUFHLE1BQU0sQ0FBa0I7UUFDdkMsZ0JBQWdCLEVBQUUsS0FBSztRQUN2QixnQkFBZ0IsRUFBRSxPQUFPO1FBQ3pCLGNBQWMsRUFBRSxPQUFPO0tBQ3hCLENBQUMsQ0FBQztJQUVILDZCQUE2QjtJQUNyQixVQUFVLEdBQUcsTUFBTSxDQUFjLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsR0FBRyxNQUFNLENBQWMsSUFBSSxDQUFDLENBQUM7SUFDckMsVUFBVSxHQUFHLE1BQU0sQ0FBTyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdEMsV0FBVyxHQUFHLE1BQU0sQ0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFELGVBQWUsR0FBRyxNQUFNLENBQVUsSUFBSSxDQUFDLENBQUM7SUFFaEQsYUFBYTtJQUNMLFVBQVUsR0FBRyxNQUFNLENBQVMsT0FBTyxDQUFDLENBQUM7SUFDckMsUUFBUSxHQUFHLE1BQU0sQ0FBUyxPQUFPLENBQUMsQ0FBQztJQUUzQyxzQ0FBc0M7SUFDOUIsYUFB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LElBQTBCO1FBQzFDLElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDdkIsSUFBSSxJQUFJLFlBQVksSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3RDLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFTyxZQUFZLENBQUMsSUFBVTtRQUM3QixPQUFPLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFVO1FBQ2pDLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVPLGVBQWUsQ0FBQyxJQUFVO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNwRyxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hELENBQUM7d0dBOVNVLGtCQUFrQjs0R0FBbEIsa0JBQWtCLGNBRmpCLE1BQU07OzRGQUVQLGtCQUFrQjtrQkFIOUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlYWRsZXNzIERhdGUgUmFuZ2UgU3RvcmUgdXNpbmcgQW5ndWxhciBTaWduYWxzXG4gKiBcbiAqIEFyY2hpdGVjdHVyZTpcbiAqIC0gU3RhdGUgbGl2ZXMgSEVSRSwgbm90IGluIFVJIGNvbXBvbmVudFxuICogLSBEZXRlcm1pbmlzdGljOiBubyBoaWRkZW4gc2lkZSBlZmZlY3RzXG4gKiAtIFNTUi1jb21wYXRpYmxlOiBubyB3aW5kb3cvZG9jdW1lbnQgZGVwZW5kZW5jaWVzXG4gKiAtIFRlc3RhYmxlOiBwdXJlIHNpZ25hbC1iYXNlZCBzdGF0ZVxuICogLSBSZXVzYWJsZTogaW5qZWN0IGFueXdoZXJlIChzZXJ2aWNlcywgY29tcG9uZW50cywgZ3VhcmRzKVxuICogXG4gKiBVc2FnZTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGNvbXBvbmVudFxuICogY29uc3QgcmFuZ2VTdG9yZSA9IGluamVjdChEdWFsRGF0ZVJhbmdlU3RvcmUpO1xuICogcmFuZ2VTdG9yZS5hcHBseVByZXNldCgnVEhJU19NT05USCcpO1xuICogXG4gKiAvLyBJbiBzZXJ2aWNlIChoZWFkbGVzcyEpXG4gKiBjb25zdCBzdG9yZSA9IGluamVjdChEdWFsRGF0ZVJhbmdlU3RvcmUpO1xuICogY29uc3QgcmFuZ2UgPSBzdG9yZS5yYW5nZSgpO1xuICogdGhpcy5odHRwLmdldChgL2FwaS9zYWxlcz9zdGFydD0ke3JhbmdlLnN0YXJ0fSZlbmQ9JHtyYW5nZS5lbmR9YCk7XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBzaWduYWwsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgXG4gIHZhbGlkYXRlUmFuZ2VPcmRlciwgXG4gIHZhbGlkYXRlUmFuZ2VCb3VuZHMsIFxuICBpc0RhdGVEaXNhYmxlZCxcbiAgYXBwbHlCb3VuZHMsXG4gIHBhcnNlSVNPRGF0ZSxcbiAgZm9ybWF0SVNPRGF0ZVxufSBmcm9tICcuL3JhbmdlLnZhbGlkYXRvcic7XG5pbXBvcnQgeyBwcmVzZXRFbmdpbmUsIFByZXNldFJhbmdlIH0gZnJvbSAnLi9wcmVzZXQuZW5naW5lJztcblxuZXhwb3J0IGludGVyZmFjZSBEYXRlUmFuZ2VTdGF0ZSB7XG4gIHN0YXJ0OiBzdHJpbmc7IC8vIElTTyBkYXRlXG4gIGVuZDogc3RyaW5nOyAvLyBJU08gZGF0ZVxuICBzdGFydFRpbWU/OiBzdHJpbmc7IC8vIEhIOm1tXG4gIGVuZFRpbWU/OiBzdHJpbmc7IC8vIEhIOm1tXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0ZVJhbmdlQ29uZmlnIHtcbiAgbWluRGF0ZT86IERhdGU7XG4gIG1heERhdGU/OiBEYXRlO1xuICBkaXNhYmxlZERhdGVzPzogRGF0ZVtdIHwgKChkYXRlOiBEYXRlKSA9PiBib29sZWFuKTtcbiAgZW5hYmxlVGltZVBpY2tlcj86IGJvb2xlYW47XG4gIGRlZmF1bHRTdGFydFRpbWU/OiBzdHJpbmc7XG4gIGRlZmF1bHRFbmRUaW1lPzogc3RyaW5nO1xufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBEdWFsRGF0ZVJhbmdlU3RvcmUge1xuICAvLyBDb25maWd1cmF0aW9uXG4gIHByaXZhdGUgY29uZmlnID0gc2lnbmFsPERhdGVSYW5nZUNvbmZpZz4oe1xuICAgIGVuYWJsZVRpbWVQaWNrZXI6IGZhbHNlLFxuICAgIGRlZmF1bHRTdGFydFRpbWU6ICcwMDowMCcsXG4gICAgZGVmYXVsdEVuZFRpbWU6ICcyMzo1OSdcbiAgfSk7XG5cbiAgLy8gQ29yZSBzdGF0ZSAtIHVzaW5nIHNpZ25hbHNcbiAgcHJpdmF0ZSBfc3RhcnREYXRlID0gc2lnbmFsPERhdGUgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBfZW5kRGF0ZSA9IHNpZ25hbDxEYXRlIHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgX2xlZnRNb250aCA9IHNpZ25hbDxEYXRlPihuZXcgRGF0ZSgpKTtcbiAgcHJpdmF0ZSBfcmlnaHRNb250aCA9IHNpZ25hbDxEYXRlPih0aGlzLmdldE5leHRNb250aChuZXcgRGF0ZSgpKSk7XG4gIHByaXZhdGUgX3NlbGVjdGluZ1N0YXJ0ID0gc2lnbmFsPGJvb2xlYW4+KHRydWUpO1xuXG4gIC8vIFRpbWUgc3RhdGVcbiAgcHJpdmF0ZSBfc3RhcnRUaW1lID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwJyk7XG4gIHByaXZhdGUgX2VuZFRpbWUgPSBzaWduYWw8c3RyaW5nPignMjM6NTknKTtcblxuICAvLyBQZW5kaW5nIHN0YXRlIGZvciByZXF1aXJlQXBwbHkgbW9kZVxuICBwcml2YXRlIF9wZW5kaW5nU3RhcnQgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuICBwcml2YXRlIF9wZW5kaW5nRW5kID0gc2lnbmFsPERhdGUgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBfaGFzUGVuZGluZ0NoYW5nZXMgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIC8vIFB1YmxpYyByZWFkLW9ubHkgc2lnbmFsc1xuICByZWFkb25seSBzdGFydERhdGUgPSB0aGlzLl9zdGFydERhdGUuYXNSZWFkb25seSgpO1xuICByZWFkb25seSBlbmREYXRlID0gdGhpcy5fZW5kRGF0ZS5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IGxlZnRNb250aCA9IHRoaXMuX2xlZnRNb250aC5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IHJpZ2h0TW9udGggPSB0aGlzLl9yaWdodE1vbnRoLmFzUmVhZG9ubHkoKTtcbiAgcmVhZG9ubHkgc2VsZWN0aW5nU3RhcnQgPSB0aGlzLl9zZWxlY3RpbmdTdGFydC5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IHN0YXJ0VGltZSA9IHRoaXMuX3N0YXJ0VGltZS5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IGVuZFRpbWUgPSB0aGlzLl9lbmRUaW1lLmFzUmVhZG9ubHkoKTtcbiAgcmVhZG9ubHkgaGFzUGVuZGluZ0NoYW5nZXMgPSB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5hc1JlYWRvbmx5KCk7XG5cbiAgLy8gQ29tcHV0ZWQ6IElTTyByYW5nZSBmb3IgQVBJIGNvbnN1bXB0aW9uXG4gIHJlYWRvbmx5IHJhbmdlID0gY29tcHV0ZWQ8RGF0ZVJhbmdlU3RhdGU+KCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcbiAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuXG4gICAgY29uc3QgcmVzdWx0OiBEYXRlUmFuZ2VTdGF0ZSA9IHtcbiAgICAgIHN0YXJ0OiBmb3JtYXRJU09EYXRlKHN0YXJ0KSxcbiAgICAgIGVuZDogZm9ybWF0SVNPRGF0ZShlbmQpXG4gICAgfTtcblxuICAgIGlmIChjZmcuZW5hYmxlVGltZVBpY2tlcikge1xuICAgICAgcmVzdWx0LnN0YXJ0VGltZSA9IHRoaXMuX3N0YXJ0VGltZSgpO1xuICAgICAgcmVzdWx0LmVuZFRpbWUgPSB0aGlzLl9lbmRUaW1lKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSk7XG5cbiAgLy8gQ29tcHV0ZWQ6IHZhbGlkYXRpb24gc3RhdGVcbiAgcmVhZG9ubHkgaXNWYWxpZCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcbiAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuXG4gICAgY29uc3Qgb3JkZXJWYWxpZGF0aW9uID0gdmFsaWRhdGVSYW5nZU9yZGVyKHN0YXJ0LCBlbmQpO1xuICAgIGlmICghb3JkZXJWYWxpZGF0aW9uLnZhbGlkKSByZXR1cm4gZmFsc2U7XG5cbiAgICBjb25zdCBib3VuZHNWYWxpZGF0aW9uID0gdmFsaWRhdGVSYW5nZUJvdW5kcyhcbiAgICAgIHN0YXJ0LFxuICAgICAgZW5kLFxuICAgICAgY2ZnLm1pbkRhdGUsXG4gICAgICBjZmcubWF4RGF0ZVxuICAgICk7XG4gICAgcmV0dXJuIGJvdW5kc1ZhbGlkYXRpb24udmFsaWQ7XG4gIH0pO1xuXG4gIC8vIENvbXB1dGVkOiByYW5nZSB0ZXh0IGZvciBkaXNwbGF5XG4gIHJlYWRvbmx5IHJhbmdlVGV4dCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcblxuICAgIGlmICghc3RhcnQgJiYgIWVuZCkgcmV0dXJuICcnO1xuICAgIGlmICghc3RhcnQpIHJldHVybiBgPyAtICR7dGhpcy5mb3JtYXREYXRlU2hvcnQoZW5kISl9YDtcbiAgICBpZiAoIWVuZCkgcmV0dXJuIGAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KHN0YXJ0KX1gO1xuXG4gICAgcmV0dXJuIGAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KHN0YXJ0KX0gLSAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KGVuZCl9YDtcbiAgfSk7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSB0aGUgc3RvcmVcbiAgICovXG4gIGNvbmZpZ3VyZShjb25maWc6IFBhcnRpYWw8RGF0ZVJhbmdlQ29uZmlnPik6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnLnVwZGF0ZShjdXJyZW50ID0+ICh7IC4uLmN1cnJlbnQsIC4uLmNvbmZpZyB9KSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHN0YXJ0IGRhdGUgKHdpdGggdmFsaWRhdGlvbilcbiAgICovXG4gIHNldFN0YXJ0KGRhdGU6IERhdGUgfCBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VkRGF0ZSA9IHRoaXMucGFyc2VEYXRlKGRhdGUpO1xuICAgIFxuICAgIGlmIChwYXJzZWREYXRlKSB7XG4gICAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuICAgICAgXG4gICAgICAvLyBBcHBseSBib3VuZHNcbiAgICAgIGNvbnN0IGJvdW5kZWREYXRlID0gYXBwbHlCb3VuZHMocGFyc2VkRGF0ZSwgY2ZnLm1pbkRhdGUsIGNmZy5tYXhEYXRlKTtcbiAgICAgIFxuICAgICAgLy8gQ2hlY2sgaWYgZGlzYWJsZWRcbiAgICAgIGlmIChpc0RhdGVEaXNhYmxlZChib3VuZGVkRGF0ZSwgY2ZnLmRpc2FibGVkRGF0ZXMpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQ2Fubm90IHNlbGVjdCBkaXNhYmxlZCBkYXRlJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc3RhcnREYXRlLnNldChib3VuZGVkRGF0ZSk7XG4gICAgICB0aGlzLl9zZWxlY3RpbmdTdGFydC5zZXQoZmFsc2UpO1xuXG4gICAgICAvLyBBdXRvLWFkanVzdCBlbmQgaWYgaXQgYmVjb21lcyBpbnZhbGlkXG4gICAgICBjb25zdCBlbmQgPSB0aGlzLl9lbmREYXRlKCk7XG4gICAgICBpZiAoZW5kICYmIGVuZCA8IGJvdW5kZWREYXRlKSB7XG4gICAgICAgIHRoaXMuX2VuZERhdGUuc2V0KG51bGwpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zdGFydERhdGUuc2V0KG51bGwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgZW5kIGRhdGUgKHdpdGggdmFsaWRhdGlvbilcbiAgICovXG4gIHNldEVuZChkYXRlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IHBhcnNlZERhdGUgPSB0aGlzLnBhcnNlRGF0ZShkYXRlKTtcbiAgICBcbiAgICBpZiAocGFyc2VkRGF0ZSkge1xuICAgICAgY29uc3QgY2ZnID0gdGhpcy5jb25maWcoKTtcbiAgICAgIFxuICAgICAgLy8gQXBwbHkgYm91bmRzXG4gICAgICBjb25zdCBib3VuZGVkRGF0ZSA9IGFwcGx5Qm91bmRzKHBhcnNlZERhdGUsIGNmZy5taW5EYXRlLCBjZmcubWF4RGF0ZSk7XG4gICAgICBcbiAgICAgIC8vIENoZWNrIGlmIGRpc2FibGVkXG4gICAgICBpZiAoaXNEYXRlRGlzYWJsZWQoYm91bmRlZERhdGUsIGNmZy5kaXNhYmxlZERhdGVzKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0Nhbm5vdCBzZWxlY3QgZGlzYWJsZWQgZGF0ZScpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIG9yZGVyXG4gICAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgICAgaWYgKHN0YXJ0ICYmIGJvdW5kZWREYXRlIDwgc3RhcnQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdFbmQgZGF0ZSBjYW5ub3QgYmUgYmVmb3JlIHN0YXJ0IGRhdGUnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9lbmREYXRlLnNldChib3VuZGVkRGF0ZSk7XG4gICAgICB0aGlzLl9zZWxlY3RpbmdTdGFydC5zZXQodHJ1ZSk7IC8vIFJlYWR5IGZvciBuZXh0IHNlbGVjdGlvblxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9lbmREYXRlLnNldChudWxsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IGNvbXBsZXRlIHJhbmdlIGF0IG9uY2VcbiAgICovXG4gIHNldFJhbmdlKHN0YXJ0OiBEYXRlIHwgc3RyaW5nIHwgbnVsbCwgZW5kOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuc2V0U3RhcnQoc3RhcnQpO1xuICAgIHRoaXMuc2V0RW5kKGVuZCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHBlbmRpbmcgc2VsZWN0aW9uIChmb3IgcmVxdWlyZUFwcGx5IG1vZGUpXG4gICAqL1xuICBzZXRQZW5kaW5nU3RhcnQoZGF0ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICBjb25zdCBwYXJzZWREYXRlID0gdGhpcy5wYXJzZURhdGUoZGF0ZSk7XG4gICAgdGhpcy5fcGVuZGluZ1N0YXJ0LnNldChwYXJzZWREYXRlKTtcbiAgICB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5zZXQodHJ1ZSk7XG4gIH1cblxuICBzZXRQZW5kaW5nRW5kKGRhdGU6IERhdGUgfCBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VkRGF0ZSA9IHRoaXMucGFyc2VEYXRlKGRhdGUpO1xuICAgIHRoaXMuX3BlbmRpbmdFbmQuc2V0KHBhcnNlZERhdGUpO1xuICAgIHRoaXMuX2hhc1BlbmRpbmdDaGFuZ2VzLnNldCh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBwZW5kaW5nIGNoYW5nZXNcbiAgICovXG4gIGFwcGx5UGVuZGluZygpOiB2b2lkIHtcbiAgICBjb25zdCBwZW5kaW5nU3RhcnQgPSB0aGlzLl9wZW5kaW5nU3RhcnQoKTtcbiAgICBjb25zdCBwZW5kaW5nRW5kID0gdGhpcy5fcGVuZGluZ0VuZCgpO1xuXG4gICAgaWYgKHBlbmRpbmdTdGFydCkgdGhpcy5zZXRTdGFydChwZW5kaW5nU3RhcnQpO1xuICAgIGlmIChwZW5kaW5nRW5kKSB0aGlzLnNldEVuZChwZW5kaW5nRW5kKTtcblxuICAgIHRoaXMuY2xlYXJQZW5kaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FuY2VsIHBlbmRpbmcgY2hhbmdlc1xuICAgKi9cbiAgY2FuY2VsUGVuZGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFyUGVuZGluZygpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhclBlbmRpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5fcGVuZGluZ1N0YXJ0LnNldChudWxsKTtcbiAgICB0aGlzLl9wZW5kaW5nRW5kLnNldChudWxsKTtcbiAgICB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5zZXQoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRvIGVtcHR5IHN0YXRlXG4gICAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLl9zdGFydERhdGUuc2V0KG51bGwpO1xuICAgIHRoaXMuX2VuZERhdGUuc2V0KG51bGwpO1xuICAgIHRoaXMuX3NlbGVjdGluZ1N0YXJ0LnNldCh0cnVlKTtcbiAgICB0aGlzLmNsZWFyUGVuZGluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGx5IGEgcHJlc2V0IGJ5IGtleVxuICAgKi9cbiAgYXBwbHlQcmVzZXQocHJlc2V0S2V5OiBzdHJpbmcsIG5vdzogRGF0ZSA9IG5ldyBEYXRlKCkpOiB2b2lkIHtcbiAgICBjb25zdCByYW5nZSA9IHByZXNldEVuZ2luZS5yZXNvbHZlKHByZXNldEtleSwgbm93KTtcbiAgICBcbiAgICBpZiAocmFuZ2UpIHtcbiAgICAgIHRoaXMuc2V0UmFuZ2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihgUHJlc2V0IFwiJHtwcmVzZXRLZXl9XCIgbm90IGZvdW5kYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE5hdmlnYXRlIGxlZnQgY2FsZW5kYXIgbW9udGhcbiAgICovXG4gIHNldExlZnRNb250aChkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5fbGVmdE1vbnRoLnNldChkYXRlKTtcbiAgICBcbiAgICAvLyBFbnN1cmUgcmlnaHQgbW9udGggaXMgYWx3YXlzIGFmdGVyIGxlZnRcbiAgICBjb25zdCByaWdodCA9IHRoaXMuX3JpZ2h0TW9udGgoKTtcbiAgICBpZiAocmlnaHQgPD0gZGF0ZSkge1xuICAgICAgdGhpcy5fcmlnaHRNb250aC5zZXQodGhpcy5nZXROZXh0TW9udGgoZGF0ZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZSByaWdodCBjYWxlbmRhciBtb250aFxuICAgKi9cbiAgc2V0UmlnaHRNb250aChkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5fcmlnaHRNb250aC5zZXQoZGF0ZSk7XG4gICAgXG4gICAgLy8gRW5zdXJlIGxlZnQgbW9udGggaXMgYWx3YXlzIGJlZm9yZSByaWdodFxuICAgIGNvbnN0IGxlZnQgPSB0aGlzLl9sZWZ0TW9udGgoKTtcbiAgICBpZiAobGVmdCA+PSBkYXRlKSB7XG4gICAgICB0aGlzLl9sZWZ0TW9udGguc2V0KHRoaXMuZ2V0UHJldmlvdXNNb250aChkYXRlKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aW1lIHZhbHVlc1xuICAgKi9cbiAgc2V0U3RhcnRUaW1lKHRpbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX3N0YXJ0VGltZS5zZXQodGltZSk7XG4gIH1cblxuICBzZXRFbmRUaW1lKHRpbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX2VuZFRpbWUuc2V0KHRpbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHN0YXRlIGFzIHNuYXBzaG90XG4gICAqL1xuICBnZXRTbmFwc2hvdCgpOiBEYXRlUmFuZ2VTdGF0ZSB7XG4gICAgcmV0dXJuIHRoaXMucmFuZ2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIHN0YXRlIGZyb20gc25hcHNob3RcbiAgICovXG4gIGxvYWRTbmFwc2hvdChzbmFwc2hvdDogRGF0ZVJhbmdlU3RhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnNldFJhbmdlKHNuYXBzaG90LnN0YXJ0LCBzbmFwc2hvdC5lbmQpO1xuICAgIFxuICAgIGlmIChzbmFwc2hvdC5zdGFydFRpbWUpIHtcbiAgICAgIHRoaXMuc2V0U3RhcnRUaW1lKHNuYXBzaG90LnN0YXJ0VGltZSk7XG4gICAgfVxuICAgIFxuICAgIGlmIChzbmFwc2hvdC5lbmRUaW1lKSB7XG4gICAgICB0aGlzLnNldEVuZFRpbWUoc25hcHNob3QuZW5kVGltZSk7XG4gICAgfVxuICB9XG5cbiAgLy8gSGVscGVyIG1ldGhvZHNcbiAgcHJpdmF0ZSBwYXJzZURhdGUoZGF0ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwpOiBEYXRlIHwgbnVsbCB7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBkYXRlO1xuICAgIHJldHVybiBwYXJzZUlTT0RhdGUoZGF0ZSk7XG4gIH1cblxuICBwcml2YXRlIGdldE5leHRNb250aChkYXRlOiBEYXRlKTogRGF0ZSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgZGF0ZS5nZXRNb250aCgpICsgMSwgMSk7XG4gIH1cblxuICBwcml2YXRlIGdldFByZXZpb3VzTW9udGgoZGF0ZTogRGF0ZSk6IERhdGUge1xuICAgIHJldHVybiBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSAtIDEsIDEpO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXREYXRlU2hvcnQoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsICdPY3QnLCAnTm92JywgJ0RlYyddO1xuICAgIHJldHVybiBgJHtkYXRlLmdldERhdGUoKX0gJHttb250aHNbZGF0ZS5nZXRNb250aCgpXX1gO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core headless date range logic
|
|
3
|
+
* Import from here for clean barrel exports
|
|
4
|
+
*/
|
|
5
|
+
export * from './dual-date-range.store';
|
|
6
|
+
export * from './preset.engine';
|
|
7
|
+
export * from './range.validator';
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29yZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxtQkFBbUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29yZSBoZWFkbGVzcyBkYXRlIHJhbmdlIGxvZ2ljXG4gKiBJbXBvcnQgZnJvbSBoZXJlIGZvciBjbGVhbiBiYXJyZWwgZXhwb3J0c1xuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vZHVhbC1kYXRlLXJhbmdlLnN0b3JlJztcbmV4cG9ydCAqIGZyb20gJy4vcHJlc2V0LmVuZ2luZSc7XG5leHBvcnQgKiBmcm9tICcuL3JhbmdlLnZhbGlkYXRvcic7XG4iXX0=
|