@oneluiz/dual-datepicker 4.0.0 → 4.0.2
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 +26 -2
- package/fesm2022/oneluiz-dual-datepicker.mjs +75 -71
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +8 -9
- package/types/oneluiz-dual-datepicker.d.ts +1618 -0
- package/dual-datepicker.component.d.ts +0 -243
- package/esm2022/core/built-in-presets.mjs +0 -289
- package/esm2022/core/calendar-grid/cache.config.mjs +0 -35
- package/esm2022/core/calendar-grid/calendar-grid.cache.mjs +0 -98
- package/esm2022/core/calendar-grid/calendar-grid.factory.mjs +0 -97
- package/esm2022/core/calendar-grid/calendar-grid.types.mjs +0 -8
- package/esm2022/core/calendar-grid/range-highlighter.cache.mjs +0 -200
- package/esm2022/core/calendar-grid/range-highlighter.mjs +0 -185
- package/esm2022/core/calendar-grid/range-highlighter.types.mjs +0 -11
- package/esm2022/core/calendar-grid/virtual-weeks.logic.mjs +0 -149
- package/esm2022/core/calendar-grid/virtual-weeks.types.mjs +0 -11
- package/esm2022/core/date-adapter.mjs +0 -77
- package/esm2022/core/date-clock.mjs +0 -65
- package/esm2022/core/dual-date-range.store.mjs +0 -329
- package/esm2022/core/internal.mjs +0 -92
- package/esm2022/core/native-date-adapter.mjs +0 -286
- package/esm2022/core/preset-providers.mjs +0 -243
- package/esm2022/core/preset-registry.mjs +0 -277
- package/esm2022/core/preset.engine.mjs +0 -179
- package/esm2022/core/public.mjs +0 -94
- package/esm2022/core/range-preset.plugin.mjs +0 -70
- package/esm2022/core/range.validator.mjs +0 -105
- package/esm2022/core/system-clock.mjs +0 -34
- package/esm2022/core/testing/date.helpers.mjs +0 -49
- package/esm2022/core/testing/fixed-clock.mjs +0 -30
- package/esm2022/core/testing/index.mjs +0 -8
- package/esm2022/dual-datepicker.component.mjs +0 -1314
- package/esm2022/oneluiz-dual-datepicker.mjs +0 -5
- package/esm2022/public-api.mjs +0 -43
- package/index.d.ts +0 -5
- package/public-api.d.ts +0 -44
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, Injectable, inject, signal, computed, makeEnvironmentProviders, APP_INITIALIZER, Inject, EventEmitter, effect, forwardRef, HostListener, Output, Input, Component } from '@angular/core';
|
|
2
|
+
import { InjectionToken, Injectable, inject, signal, computed, makeEnvironmentProviders, APP_INITIALIZER, Optional, Inject, EventEmitter, effect, forwardRef, HostListener, Output, Input, Component } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
@@ -195,10 +195,10 @@ class SystemClock {
|
|
|
195
195
|
now() {
|
|
196
196
|
return new Date();
|
|
197
197
|
}
|
|
198
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
199
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
198
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SystemClock, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
199
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SystemClock, providedIn: 'root' });
|
|
200
200
|
}
|
|
201
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
201
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SystemClock, decorators: [{
|
|
202
202
|
type: Injectable,
|
|
203
203
|
args: [{
|
|
204
204
|
providedIn: 'root'
|
|
@@ -555,10 +555,10 @@ class NativeDateAdapter {
|
|
|
555
555
|
const startsWithMonday = mondayStartLocales.some(loc => normalizedLocale.startsWith(loc.toLowerCase()));
|
|
556
556
|
return startsWithMonday ? 1 : 0;
|
|
557
557
|
}
|
|
558
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
559
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
558
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: NativeDateAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
559
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: NativeDateAdapter, providedIn: 'root' });
|
|
560
560
|
}
|
|
561
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
561
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: NativeDateAdapter, decorators: [{
|
|
562
562
|
type: Injectable,
|
|
563
563
|
args: [{
|
|
564
564
|
providedIn: 'root'
|
|
@@ -899,10 +899,10 @@ class PresetRegistry {
|
|
|
899
899
|
clear() {
|
|
900
900
|
this.presets.clear();
|
|
901
901
|
}
|
|
902
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
903
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
902
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
903
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetRegistry, providedIn: 'root' });
|
|
904
904
|
}
|
|
905
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
905
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetRegistry, decorators: [{
|
|
906
906
|
type: Injectable,
|
|
907
907
|
args: [{
|
|
908
908
|
providedIn: 'root'
|
|
@@ -1048,10 +1048,10 @@ class PresetEngine {
|
|
|
1048
1048
|
hasPreset(key) {
|
|
1049
1049
|
return this.registry.has(key);
|
|
1050
1050
|
}
|
|
1051
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1052
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1051
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetEngine, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1052
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetEngine, providedIn: 'root' });
|
|
1053
1053
|
}
|
|
1054
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1054
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: PresetEngine, decorators: [{
|
|
1055
1055
|
type: Injectable,
|
|
1056
1056
|
args: [{
|
|
1057
1057
|
providedIn: 'root'
|
|
@@ -1127,26 +1127,28 @@ class DualDateRangeStore {
|
|
|
1127
1127
|
catch {
|
|
1128
1128
|
this.adapter = new NativeDateAdapter();
|
|
1129
1129
|
}
|
|
1130
|
+
// Update _rightMonth to correct value after adapter is available
|
|
1131
|
+
this._rightMonth.set(this.getNextMonth(new Date()));
|
|
1130
1132
|
}
|
|
1131
1133
|
// Configuration
|
|
1132
1134
|
config = signal({
|
|
1133
1135
|
enableTimePicker: false,
|
|
1134
1136
|
defaultStartTime: '00:00',
|
|
1135
1137
|
defaultEndTime: '23:59'
|
|
1136
|
-
});
|
|
1138
|
+
}, ...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
1137
1139
|
// Core state - using signals
|
|
1138
|
-
_startDate = signal(null);
|
|
1139
|
-
_endDate = signal(null);
|
|
1140
|
-
_leftMonth = signal(new Date());
|
|
1141
|
-
_rightMonth = signal(
|
|
1142
|
-
_selectingStart = signal(true);
|
|
1140
|
+
_startDate = signal(null, ...(ngDevMode ? [{ debugName: "_startDate" }] : /* istanbul ignore next */ []));
|
|
1141
|
+
_endDate = signal(null, ...(ngDevMode ? [{ debugName: "_endDate" }] : /* istanbul ignore next */ []));
|
|
1142
|
+
_leftMonth = signal(new Date(), ...(ngDevMode ? [{ debugName: "_leftMonth" }] : /* istanbul ignore next */ []));
|
|
1143
|
+
_rightMonth = signal(new Date(), ...(ngDevMode ? [{ debugName: "_rightMonth" }] : /* istanbul ignore next */ [])); // Temporary value, updated in constructor
|
|
1144
|
+
_selectingStart = signal(true, ...(ngDevMode ? [{ debugName: "_selectingStart" }] : /* istanbul ignore next */ []));
|
|
1143
1145
|
// Time state
|
|
1144
|
-
_startTime = signal('00:00');
|
|
1145
|
-
_endTime = signal('23:59');
|
|
1146
|
+
_startTime = signal('00:00', ...(ngDevMode ? [{ debugName: "_startTime" }] : /* istanbul ignore next */ []));
|
|
1147
|
+
_endTime = signal('23:59', ...(ngDevMode ? [{ debugName: "_endTime" }] : /* istanbul ignore next */ []));
|
|
1146
1148
|
// Pending state for requireApply mode
|
|
1147
|
-
_pendingStart = signal(null);
|
|
1148
|
-
_pendingEnd = signal(null);
|
|
1149
|
-
_hasPendingChanges = signal(false);
|
|
1149
|
+
_pendingStart = signal(null, ...(ngDevMode ? [{ debugName: "_pendingStart" }] : /* istanbul ignore next */ []));
|
|
1150
|
+
_pendingEnd = signal(null, ...(ngDevMode ? [{ debugName: "_pendingEnd" }] : /* istanbul ignore next */ []));
|
|
1151
|
+
_hasPendingChanges = signal(false, ...(ngDevMode ? [{ debugName: "_hasPendingChanges" }] : /* istanbul ignore next */ []));
|
|
1150
1152
|
// Public read-only signals
|
|
1151
1153
|
startDate = this._startDate.asReadonly();
|
|
1152
1154
|
endDate = this._endDate.asReadonly();
|
|
@@ -1170,7 +1172,7 @@ class DualDateRangeStore {
|
|
|
1170
1172
|
result.endTime = this._endTime();
|
|
1171
1173
|
}
|
|
1172
1174
|
return result;
|
|
1173
|
-
});
|
|
1175
|
+
}, ...(ngDevMode ? [{ debugName: "range" }] : /* istanbul ignore next */ []));
|
|
1174
1176
|
// Computed: validation state
|
|
1175
1177
|
isValid = computed(() => {
|
|
1176
1178
|
const start = this._startDate();
|
|
@@ -1181,7 +1183,7 @@ class DualDateRangeStore {
|
|
|
1181
1183
|
return false;
|
|
1182
1184
|
const boundsValidation = validateRangeBounds(start, end, cfg.minDate, cfg.maxDate);
|
|
1183
1185
|
return boundsValidation.valid;
|
|
1184
|
-
});
|
|
1186
|
+
}, ...(ngDevMode ? [{ debugName: "isValid" }] : /* istanbul ignore next */ []));
|
|
1185
1187
|
// Computed: range text for display
|
|
1186
1188
|
rangeText = computed(() => {
|
|
1187
1189
|
const start = this._startDate();
|
|
@@ -1193,7 +1195,7 @@ class DualDateRangeStore {
|
|
|
1193
1195
|
if (!end)
|
|
1194
1196
|
return `${this.formatDateShort(start)}`;
|
|
1195
1197
|
return `${this.formatDateShort(start)} - ${this.formatDateShort(end)}`;
|
|
1196
|
-
});
|
|
1198
|
+
}, ...(ngDevMode ? [{ debugName: "rangeText" }] : /* istanbul ignore next */ []));
|
|
1197
1199
|
/**
|
|
1198
1200
|
* Configure the store
|
|
1199
1201
|
*/
|
|
@@ -1389,13 +1391,13 @@ class DualDateRangeStore {
|
|
|
1389
1391
|
formatDateShort(date) {
|
|
1390
1392
|
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
1391
1393
|
const month = this.adapter.getMonth(date);
|
|
1392
|
-
const day = this.adapter.
|
|
1394
|
+
const day = this.adapter.getDate(date); // FIX: use getDate() not getDay()
|
|
1393
1395
|
return `${day} ${months[month]}`;
|
|
1394
1396
|
}
|
|
1395
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1396
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1397
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DualDateRangeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1398
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DualDateRangeStore, providedIn: 'root' });
|
|
1397
1399
|
}
|
|
1398
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1400
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DualDateRangeStore, decorators: [{
|
|
1399
1401
|
type: Injectable,
|
|
1400
1402
|
args: [{
|
|
1401
1403
|
providedIn: 'root'
|
|
@@ -1969,7 +1971,7 @@ function providePresetPackage(packageName, presets) {
|
|
|
1969
1971
|
class CalendarGridFactory {
|
|
1970
1972
|
adapter;
|
|
1971
1973
|
constructor(adapter) {
|
|
1972
|
-
this.adapter = adapter;
|
|
1974
|
+
this.adapter = adapter ?? new NativeDateAdapter();
|
|
1973
1975
|
}
|
|
1974
1976
|
/**
|
|
1975
1977
|
* Create a calendar grid for a given month
|
|
@@ -2038,13 +2040,15 @@ class CalendarGridFactory {
|
|
|
2038
2040
|
}
|
|
2039
2041
|
return offset;
|
|
2040
2042
|
}
|
|
2041
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2042
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2043
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridFactory, deps: [{ token: DATE_ADAPTER, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2044
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridFactory, providedIn: 'root' });
|
|
2043
2045
|
}
|
|
2044
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2046
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridFactory, decorators: [{
|
|
2045
2047
|
type: Injectable,
|
|
2046
2048
|
args: [{ providedIn: 'root' }]
|
|
2047
2049
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
2050
|
+
type: Optional
|
|
2051
|
+
}, {
|
|
2048
2052
|
type: Inject,
|
|
2049
2053
|
args: [DATE_ADAPTER]
|
|
2050
2054
|
}] }] });
|
|
@@ -2170,10 +2174,10 @@ class CalendarGridCache {
|
|
|
2170
2174
|
const key = this.buildKey(monthDate, weekStart, locale);
|
|
2171
2175
|
return this.cache.has(key);
|
|
2172
2176
|
}
|
|
2173
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2174
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2177
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridCache, deps: [{ token: CalendarGridFactory }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2178
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridCache, providedIn: 'root' });
|
|
2175
2179
|
}
|
|
2176
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CalendarGridCache, decorators: [{
|
|
2177
2181
|
type: Injectable,
|
|
2178
2182
|
args: [{ providedIn: 'root' }]
|
|
2179
2183
|
}], ctorParameters: () => [{ type: CalendarGridFactory }] });
|
|
@@ -2349,10 +2353,10 @@ class RangeHighlighter {
|
|
|
2349
2353
|
const max = startISO > hoverISO ? startISO : hoverISO;
|
|
2350
2354
|
return { min, max };
|
|
2351
2355
|
}
|
|
2352
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2353
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2356
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighter, deps: [{ token: DATE_ADAPTER }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2357
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighter, providedIn: 'root' });
|
|
2354
2358
|
}
|
|
2355
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2359
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighter, decorators: [{
|
|
2356
2360
|
type: Injectable,
|
|
2357
2361
|
args: [{ providedIn: 'root' }]
|
|
2358
2362
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
@@ -2544,10 +2548,10 @@ class RangeHighlighterCache {
|
|
|
2544
2548
|
const key = this.buildKey(grid, params);
|
|
2545
2549
|
return this.cache.has(key.full);
|
|
2546
2550
|
}
|
|
2547
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2548
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2551
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighterCache, deps: [{ token: RangeHighlighter }, { token: DATE_ADAPTER }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2552
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighterCache, providedIn: 'root' });
|
|
2549
2553
|
}
|
|
2550
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: RangeHighlighterCache, decorators: [{
|
|
2551
2555
|
type: Injectable,
|
|
2552
2556
|
args: [{ providedIn: 'root' }]
|
|
2553
2557
|
}], ctorParameters: () => [{ type: RangeHighlighter }, { type: undefined, decorators: [{
|
|
@@ -2892,15 +2896,15 @@ class DualDatepickerComponent {
|
|
|
2892
2896
|
// Headless store for date range state (v3.5.0+)
|
|
2893
2897
|
rangeStore = inject(DualDateRangeStore);
|
|
2894
2898
|
// UI-only signals
|
|
2895
|
-
showDatePicker = signal(false);
|
|
2896
|
-
currentMonth = signal(this.dateAdapter.normalize(new Date()));
|
|
2897
|
-
previousMonth = signal(this.dateAdapter.normalize(new Date()));
|
|
2898
|
-
currentMonthDays = signal([]);
|
|
2899
|
-
previousMonthDays = signal([]);
|
|
2900
|
-
isDisabled = signal(false);
|
|
2901
|
-
showStartTimePicker = signal(false);
|
|
2902
|
-
showEndTimePicker = signal(false);
|
|
2903
|
-
hoverDate = signal(null);
|
|
2899
|
+
showDatePicker = signal(false, ...(ngDevMode ? [{ debugName: "showDatePicker" }] : /* istanbul ignore next */ []));
|
|
2900
|
+
currentMonth = signal(this.dateAdapter.normalize(new Date()), ...(ngDevMode ? [{ debugName: "currentMonth" }] : /* istanbul ignore next */ []));
|
|
2901
|
+
previousMonth = signal(this.dateAdapter.normalize(new Date()), ...(ngDevMode ? [{ debugName: "previousMonth" }] : /* istanbul ignore next */ []));
|
|
2902
|
+
currentMonthDays = signal([], ...(ngDevMode ? [{ debugName: "currentMonthDays" }] : /* istanbul ignore next */ []));
|
|
2903
|
+
previousMonthDays = signal([], ...(ngDevMode ? [{ debugName: "previousMonthDays" }] : /* istanbul ignore next */ []));
|
|
2904
|
+
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
2905
|
+
showStartTimePicker = signal(false, ...(ngDevMode ? [{ debugName: "showStartTimePicker" }] : /* istanbul ignore next */ []));
|
|
2906
|
+
showEndTimePicker = signal(false, ...(ngDevMode ? [{ debugName: "showEndTimePicker" }] : /* istanbul ignore next */ []));
|
|
2907
|
+
hoverDate = signal(null, ...(ngDevMode ? [{ debugName: "hoverDate" }] : /* istanbul ignore next */ []));
|
|
2904
2908
|
/**
|
|
2905
2909
|
* Virtual Weeks State (v3.9.0+)
|
|
2906
2910
|
*
|
|
@@ -2910,8 +2914,8 @@ class DualDatepickerComponent {
|
|
|
2910
2914
|
*
|
|
2911
2915
|
* Reset to 0 when month changes for consistent UX.
|
|
2912
2916
|
*/
|
|
2913
|
-
previousMonthWeekStart = signal(0);
|
|
2914
|
-
currentMonthWeekStart = signal(0);
|
|
2917
|
+
previousMonthWeekStart = signal(0, ...(ngDevMode ? [{ debugName: "previousMonthWeekStart" }] : /* istanbul ignore next */ []));
|
|
2918
|
+
currentMonthWeekStart = signal(0, ...(ngDevMode ? [{ debugName: "currentMonthWeekStart" }] : /* istanbul ignore next */ []));
|
|
2915
2919
|
/**
|
|
2916
2920
|
* Computed: Visible weeks for windowed rendering (v3.9.0+)
|
|
2917
2921
|
*
|
|
@@ -2932,7 +2936,7 @@ class DualDatepickerComponent {
|
|
|
2932
2936
|
}
|
|
2933
2937
|
const visibleWeeks = getVisibleWeeks(allWeeks, this.previousMonthWeekStart(), this.virtualWeeks.windowSize);
|
|
2934
2938
|
return visibleWeeks.flat();
|
|
2935
|
-
});
|
|
2939
|
+
}, ...(ngDevMode ? [{ debugName: "previousMonthVisibleDays" }] : /* istanbul ignore next */ []));
|
|
2936
2940
|
currentMonthVisibleDays = computed(() => {
|
|
2937
2941
|
const allDays = this.currentMonthDays();
|
|
2938
2942
|
if (!this.virtualWeeks || !isVirtualWeeksEnabled(this.virtualWeeks.windowSize, 6)) {
|
|
@@ -2945,7 +2949,7 @@ class DualDatepickerComponent {
|
|
|
2945
2949
|
}
|
|
2946
2950
|
const visibleWeeks = getVisibleWeeks(allWeeks, this.currentMonthWeekStart(), this.virtualWeeks.windowSize);
|
|
2947
2951
|
return visibleWeeks.flat();
|
|
2948
|
-
});
|
|
2952
|
+
}, ...(ngDevMode ? [{ debugName: "currentMonthVisibleDays" }] : /* istanbul ignore next */ []));
|
|
2949
2953
|
// Computed time properties from store
|
|
2950
2954
|
get startHour() {
|
|
2951
2955
|
const time = this.rangeStore.startTime();
|
|
@@ -2972,18 +2976,18 @@ class DualDatepickerComponent {
|
|
|
2972
2976
|
this.rangeStore.setEndTime(timeStr);
|
|
2973
2977
|
}
|
|
2974
2978
|
// Multi-range support (UI-specific)
|
|
2975
|
-
selectedRanges = signal([]);
|
|
2976
|
-
currentRangeIndex = signal(-1);
|
|
2979
|
+
selectedRanges = signal([], ...(ngDevMode ? [{ debugName: "selectedRanges" }] : /* istanbul ignore next */ []));
|
|
2980
|
+
currentRangeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "currentRangeIndex" }] : /* istanbul ignore next */ []));
|
|
2977
2981
|
// Keyboard navigation (UI-specific)
|
|
2978
|
-
focusedDay = signal(null);
|
|
2982
|
+
focusedDay = signal(null, ...(ngDevMode ? [{ debugName: "focusedDay" }] : /* istanbul ignore next */ []));
|
|
2979
2983
|
// Computed values
|
|
2980
|
-
currentMonthName = computed(() => this.getMonthName(this.currentMonth()));
|
|
2981
|
-
previousMonthName = computed(() => this.getMonthName(this.previousMonth()));
|
|
2982
|
-
weekDayNames = computed(() => this.getDayNames());
|
|
2984
|
+
currentMonthName = computed(() => this.getMonthName(this.currentMonth()), ...(ngDevMode ? [{ debugName: "currentMonthName" }] : /* istanbul ignore next */ []));
|
|
2985
|
+
previousMonthName = computed(() => this.getMonthName(this.previousMonth()), ...(ngDevMode ? [{ debugName: "previousMonthName" }] : /* istanbul ignore next */ []));
|
|
2986
|
+
weekDayNames = computed(() => this.getDayNames(), ...(ngDevMode ? [{ debugName: "weekDayNames" }] : /* istanbul ignore next */ []));
|
|
2983
2987
|
// Computed from store
|
|
2984
|
-
dateRangeText = computed(() => this.rangeStore.rangeText());
|
|
2985
|
-
selectingStartDate = computed(() => this.rangeStore.selectingStart());
|
|
2986
|
-
hasPendingChanges = computed(() => this.rangeStore.hasPendingChanges());
|
|
2988
|
+
dateRangeText = computed(() => this.rangeStore.rangeText(), ...(ngDevMode ? [{ debugName: "dateRangeText" }] : /* istanbul ignore next */ []));
|
|
2989
|
+
selectingStartDate = computed(() => this.rangeStore.selectingStart(), ...(ngDevMode ? [{ debugName: "selectingStartDate" }] : /* istanbul ignore next */ []));
|
|
2990
|
+
hasPendingChanges = computed(() => this.rangeStore.hasPendingChanges(), ...(ngDevMode ? [{ debugName: "hasPendingChanges" }] : /* istanbul ignore next */ []));
|
|
2987
2991
|
// Computed for template access to pending dates (requireApply mode)
|
|
2988
2992
|
get pendingStartDate() {
|
|
2989
2993
|
// In requireApply mode, store keeps pending values
|
|
@@ -3992,8 +3996,8 @@ class DualDatepickerComponent {
|
|
|
3992
3996
|
setDisabledState(isDisabled) {
|
|
3993
3997
|
this.isDisabled.set(isDisabled);
|
|
3994
3998
|
}
|
|
3995
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3996
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
3999
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
4000
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: DualDatepickerComponent, isStandalone: true, selector: "ngx-dual-datepicker", inputs: { placeholder: "placeholder", startDate: "startDate", endDate: "endDate", showPresets: "showPresets", showClearButton: "showClearButton", multiRange: "multiRange", closeOnSelection: "closeOnSelection", closeOnPresetSelection: "closeOnPresetSelection", closeOnClickOutside: "closeOnClickOutside", enableKeyboardNavigation: "enableKeyboardNavigation", presets: "presets", theme: "theme", inputBackgroundColor: "inputBackgroundColor", inputTextColor: "inputTextColor", inputBorderColor: "inputBorderColor", inputBorderColorHover: "inputBorderColorHover", inputBorderColorFocus: "inputBorderColorFocus", inputPadding: "inputPadding", locale: "locale", disabledDates: "disabledDates", displayFormat: "displayFormat", requireApply: "requireApply", enableTimePicker: "enableTimePicker", timeFormat: "timeFormat", minuteStep: "minuteStep", defaultStartTime: "defaultStartTime", defaultEndTime: "defaultEndTime", virtualWeeks: "virtualWeeks" }, outputs: { dateRangeChange: "dateRangeChange", dateRangeSelected: "dateRangeSelected", multiDateRangeChange: "multiDateRangeChange", multiDateRangeSelected: "multiDateRangeSelected" }, host: { listeners: { "document:click": "onClickOutside($event)", "keydown": "handleKeyboardNavigation($event)" } }, providers: [
|
|
3997
4001
|
{
|
|
3998
4002
|
provide: NG_VALUE_ACCESSOR,
|
|
3999
4003
|
useExisting: forwardRef(() => DualDatepickerComponent),
|
|
@@ -4014,9 +4018,9 @@ class DualDatepickerComponent {
|
|
|
4014
4018
|
},
|
|
4015
4019
|
deps: [PresetRegistry]
|
|
4016
4020
|
}
|
|
4017
|
-
], usesOnChanges: true, ngImport: i0, template: "<div class=\"datepicker-wrapper\" \n [class]=\"'theme-' + theme\"\n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Time Picker -->\n @if (enableTimePicker) {\n <div class=\"time-picker-container\">\n <!-- Start Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">Start Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startHour.toString().padStart(2, '0')\"\n readonly\n title=\"Start hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startMinute.toString().padStart(2, '0')\"\n readonly\n title=\"Start minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ startHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n\n <!-- Separator -->\n <div class=\"time-separator-vertical\"></div>\n\n <!-- End Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">End Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endHour.toString().padStart(2, '0')\"\n readonly\n title=\"End hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endMinute.toString().padStart(2, '0')\"\n readonly\n title=\"End minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ endHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Footer with buttons -->\n @if (showClearButton || multiRange || requireApply) {\n <div class=\"date-picker-footer\">\n @if (requireApply && !multiRange) {\n <div class=\"apply-footer-actions\">\n <button \n type=\"button\" \n class=\"btn-cancel\" \n (click)=\"cancelSelection()\" \n [disabled]=\"!hasPendingChanges()\"\n title=\"Cancel selection\">\n Cancel\n </button>\n <button \n type=\"button\" \n class=\"btn-apply\" \n (click)=\"applySelection()\" \n [disabled]=\"!hasPendingChanges() || !pendingStartDate || !pendingEndDate\"\n title=\"Apply selection\">\n Apply\n </button>\n </div>\n }\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && !requireApply && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1;contain:layout paint}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;contain:layout paint}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400;position:relative}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day.in-hover-range{background-color:#e0e7ff;border-radius:0;opacity:.7;position:relative}.date-picker-day.in-hover-range:after{content:\"\";position:absolute;inset:0;border:1px dashed #6366f1;pointer-events:none}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-day.disabled{cursor:not-allowed;opacity:.4;color:#9ca3af;background-color:#f9fafb;text-decoration:line-through}.date-picker-day.disabled:hover{background-color:#f9fafb;color:#9ca3af}.date-picker-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply{padding:8px 24px;background-color:#2563eb;border:1px solid #2563eb;border-radius:6px;font-size:.875rem;font-weight:600;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-apply:hover:not(:disabled){background-color:#1d4ed8;border-color:#1d4ed8;transform:translateY(-1px);box-shadow:0 2px 8px #2563eb40}.date-picker-footer .btn-apply:active:not(:disabled){transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .btn-cancel{padding:8px 24px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-cancel:hover:not(:disabled){background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-cancel:active:not(:disabled){transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-cancel:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .apply-footer-actions{display:flex;gap:8px;width:100%;justify-content:flex-end}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}.time-picker-container{display:flex;align-items:center;justify-content:center;gap:16px;padding:16px;border-top:1px solid #e5e7eb;border-bottom:1px solid #e5e7eb;margin:12px 0;background-color:#f9fafb}.time-picker-container .time-picker-section{display:flex;flex-direction:column;gap:8px;flex:1;align-items:center}.time-picker-container .time-picker-section .time-picker-label{font-size:.875rem;font-weight:600;color:#374151;text-align:center}.time-picker-container .time-picker-section .time-picker-inputs{display:flex;align-items:center;gap:8px}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group{display:flex;flex-direction:column;gap:4px;align-items:center}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input{width:48px;padding:8px 6px;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background-color:#fff;border:2px solid #e5e7eb;border-radius:6px;outline:none;transition:all .15s ease;cursor:default;-webkit-user-select:none;user-select:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input:focus{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn{padding:4px 8px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:hover{background-color:var(--primary-color, #3b82f6);border-color:var(--primary-color, #3b82f6);color:#fff;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:active{transform:translateY(0);box-shadow:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn svg{pointer-events:none}.time-picker-container .time-picker-section .time-picker-inputs .time-separator{font-size:1.5rem;font-weight:700;color:#9ca3af;margin:0 4px}.time-picker-container .time-picker-section .time-picker-inputs .time-period{font-size:.875rem;font-weight:600;color:#6b7280;padding:8px 12px;background-color:#f3f4f6;border-radius:6px;min-width:48px;text-align:center}.time-picker-container .time-separator-vertical{width:1px;height:80px;background-color:#e5e7eb}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
4021
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"datepicker-wrapper\" \n [class]=\"'theme-' + theme\"\n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Time Picker -->\n @if (enableTimePicker) {\n <div class=\"time-picker-container\">\n <!-- Start Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">Start Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startHour.toString().padStart(2, '0')\"\n readonly\n title=\"Start hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startMinute.toString().padStart(2, '0')\"\n readonly\n title=\"Start minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ startHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n\n <!-- Separator -->\n <div class=\"time-separator-vertical\"></div>\n\n <!-- End Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">End Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endHour.toString().padStart(2, '0')\"\n readonly\n title=\"End hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endMinute.toString().padStart(2, '0')\"\n readonly\n title=\"End minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ endHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Footer with buttons -->\n @if (showClearButton || multiRange || requireApply) {\n <div class=\"date-picker-footer\">\n @if (requireApply && !multiRange) {\n <div class=\"apply-footer-actions\">\n <button \n type=\"button\" \n class=\"btn-cancel\" \n (click)=\"cancelSelection()\" \n [disabled]=\"!hasPendingChanges()\"\n title=\"Cancel selection\">\n Cancel\n </button>\n <button \n type=\"button\" \n class=\"btn-apply\" \n (click)=\"applySelection()\" \n [disabled]=\"!hasPendingChanges() || !pendingStartDate || !pendingEndDate\"\n title=\"Apply selection\">\n Apply\n </button>\n </div>\n }\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && !requireApply && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media(max-width:768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media(max-width:768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media(max-width:768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1;contain:layout paint}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;contain:layout paint}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400;position:relative}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day.in-hover-range{background-color:#e0e7ff;border-radius:0;opacity:.7;position:relative}.date-picker-day.in-hover-range:after{content:\"\";position:absolute;inset:0;border:1px dashed #6366f1;pointer-events:none}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-day.disabled{cursor:not-allowed;opacity:.4;color:#9ca3af;background-color:#f9fafb;text-decoration:line-through}.date-picker-day.disabled:hover{background-color:#f9fafb;color:#9ca3af}.date-picker-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply{padding:8px 24px;background-color:#2563eb;border:1px solid #2563eb;border-radius:6px;font-size:.875rem;font-weight:600;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-apply:hover:not(:disabled){background-color:#1d4ed8;border-color:#1d4ed8;transform:translateY(-1px);box-shadow:0 2px 8px #2563eb40}.date-picker-footer .btn-apply:active:not(:disabled){transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .btn-cancel{padding:8px 24px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-cancel:hover:not(:disabled){background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-cancel:active:not(:disabled){transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-cancel:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .apply-footer-actions{display:flex;gap:8px;width:100%;justify-content:flex-end}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}.time-picker-container{display:flex;align-items:center;justify-content:center;gap:16px;padding:16px;border-top:1px solid #e5e7eb;border-bottom:1px solid #e5e7eb;margin:12px 0;background-color:#f9fafb}.time-picker-container .time-picker-section{display:flex;flex-direction:column;gap:8px;flex:1;align-items:center}.time-picker-container .time-picker-section .time-picker-label{font-size:.875rem;font-weight:600;color:#374151;text-align:center}.time-picker-container .time-picker-section .time-picker-inputs{display:flex;align-items:center;gap:8px}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group{display:flex;flex-direction:column;gap:4px;align-items:center}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input{width:48px;padding:8px 6px;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background-color:#fff;border:2px solid #e5e7eb;border-radius:6px;outline:none;transition:all .15s ease;cursor:default;-webkit-user-select:none;user-select:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input:focus{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn{padding:4px 8px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:hover{background-color:var(--primary-color, #3b82f6);border-color:var(--primary-color, #3b82f6);color:#fff;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:active{transform:translateY(0);box-shadow:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn svg{pointer-events:none}.time-picker-container .time-picker-section .time-picker-inputs .time-separator{font-size:1.5rem;font-weight:700;color:#9ca3af;margin:0 4px}.time-picker-container .time-picker-section .time-picker-inputs .time-period{font-size:.875rem;font-weight:600;color:#6b7280;padding:8px 12px;background-color:#f3f4f6;border-radius:6px;min-width:48px;text-align:center}.time-picker-container .time-separator-vertical{width:1px;height:80px;background-color:#e5e7eb}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
4018
4022
|
}
|
|
4019
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4023
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: DualDatepickerComponent, decorators: [{
|
|
4020
4024
|
type: Component,
|
|
4021
4025
|
args: [{ selector: 'ngx-dual-datepicker', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule], providers: [
|
|
4022
4026
|
{
|
|
@@ -4039,7 +4043,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4039
4043
|
},
|
|
4040
4044
|
deps: [PresetRegistry]
|
|
4041
4045
|
}
|
|
4042
|
-
], template: "<div class=\"datepicker-wrapper\" \n [class]=\"'theme-' + theme\"\n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Time Picker -->\n @if (enableTimePicker) {\n <div class=\"time-picker-container\">\n <!-- Start Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">Start Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startHour.toString().padStart(2, '0')\"\n readonly\n title=\"Start hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startMinute.toString().padStart(2, '0')\"\n readonly\n title=\"Start minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ startHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n\n <!-- Separator -->\n <div class=\"time-separator-vertical\"></div>\n\n <!-- End Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">End Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endHour.toString().padStart(2, '0')\"\n readonly\n title=\"End hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endMinute.toString().padStart(2, '0')\"\n readonly\n title=\"End minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ endHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Footer with buttons -->\n @if (showClearButton || multiRange || requireApply) {\n <div class=\"date-picker-footer\">\n @if (requireApply && !multiRange) {\n <div class=\"apply-footer-actions\">\n <button \n type=\"button\" \n class=\"btn-cancel\" \n (click)=\"cancelSelection()\" \n [disabled]=\"!hasPendingChanges()\"\n title=\"Cancel selection\">\n Cancel\n </button>\n <button \n type=\"button\" \n class=\"btn-apply\" \n (click)=\"applySelection()\" \n [disabled]=\"!hasPendingChanges() || !pendingStartDate || !pendingEndDate\"\n title=\"Apply selection\">\n Apply\n </button>\n </div>\n }\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && !requireApply && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1;contain:layout paint}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;contain:layout paint}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400;position:relative}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day.in-hover-range{background-color:#e0e7ff;border-radius:0;opacity:.7;position:relative}.date-picker-day.in-hover-range:after{content:\"\";position:absolute;inset:0;border:1px dashed #6366f1;pointer-events:none}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-day.disabled{cursor:not-allowed;opacity:.4;color:#9ca3af;background-color:#f9fafb;text-decoration:line-through}.date-picker-day.disabled:hover{background-color:#f9fafb;color:#9ca3af}.date-picker-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply{padding:8px 24px;background-color:#2563eb;border:1px solid #2563eb;border-radius:6px;font-size:.875rem;font-weight:600;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-apply:hover:not(:disabled){background-color:#1d4ed8;border-color:#1d4ed8;transform:translateY(-1px);box-shadow:0 2px 8px #2563eb40}.date-picker-footer .btn-apply:active:not(:disabled){transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .btn-cancel{padding:8px 24px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-cancel:hover:not(:disabled){background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-cancel:active:not(:disabled){transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-cancel:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .apply-footer-actions{display:flex;gap:8px;width:100%;justify-content:flex-end}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}.time-picker-container{display:flex;align-items:center;justify-content:center;gap:16px;padding:16px;border-top:1px solid #e5e7eb;border-bottom:1px solid #e5e7eb;margin:12px 0;background-color:#f9fafb}.time-picker-container .time-picker-section{display:flex;flex-direction:column;gap:8px;flex:1;align-items:center}.time-picker-container .time-picker-section .time-picker-label{font-size:.875rem;font-weight:600;color:#374151;text-align:center}.time-picker-container .time-picker-section .time-picker-inputs{display:flex;align-items:center;gap:8px}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group{display:flex;flex-direction:column;gap:4px;align-items:center}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input{width:48px;padding:8px 6px;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background-color:#fff;border:2px solid #e5e7eb;border-radius:6px;outline:none;transition:all .15s ease;cursor:default;-webkit-user-select:none;user-select:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input:focus{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn{padding:4px 8px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:hover{background-color:var(--primary-color, #3b82f6);border-color:var(--primary-color, #3b82f6);color:#fff;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:active{transform:translateY(0);box-shadow:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn svg{pointer-events:none}.time-picker-container .time-picker-section .time-picker-inputs .time-separator{font-size:1.5rem;font-weight:700;color:#9ca3af;margin:0 4px}.time-picker-container .time-picker-section .time-picker-inputs .time-period{font-size:.875rem;font-weight:600;color:#6b7280;padding:8px 12px;background-color:#f3f4f6;border-radius:6px;min-width:48px;text-align:center}.time-picker-container .time-separator-vertical{width:1px;height:80px;background-color:#e5e7eb}\n"] }]
|
|
4046
|
+
], template: "<div class=\"datepicker-wrapper\" \n [class]=\"'theme-' + theme\"\n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthVisibleDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.in-hover-range]=\"dayObj.inHoverRange && !dayObj.isStart && !dayObj.isEnd\"\n [class.disabled]=\"dayObj.isDisabled\"\n [class.keyboard-focused]=\"enableKeyboardNavigation && hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"enableKeyboardNavigation && dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\n [attr.aria-disabled]=\"dayObj.isDisabled\"\n (click)=\"selectDay(dayObj)\"\n (mouseenter)=\"onDayHover(dayObj)\"\n (mouseleave)=\"clearDayHover()\"\n [disabled]=\"!dayObj.isCurrentMonth || dayObj.isDisabled\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Time Picker -->\n @if (enableTimePicker) {\n <div class=\"time-picker-container\">\n <!-- Start Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">Start Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startHour.toString().padStart(2, '0')\"\n readonly\n title=\"Start hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementStartMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"startMinute.toString().padStart(2, '0')\"\n readonly\n title=\"Start minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementStartMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ startHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n\n <!-- Separator -->\n <div class=\"time-separator-vertical\"></div>\n\n <!-- End Time -->\n <div class=\"time-picker-section\">\n <div class=\"time-picker-label\">End Time</div>\n <div class=\"time-picker-inputs\">\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndHour()\"\n title=\"Increment hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endHour.toString().padStart(2, '0')\"\n readonly\n title=\"End hour\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndHour()\"\n title=\"Decrement hour\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n <span class=\"time-separator\">:</span>\n <div class=\"time-input-group\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-up\" \n (click)=\"incrementEndMinute()\"\n title=\"Increment minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 4.86l-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z\"/>\n </svg>\n </button>\n <input\n type=\"text\"\n class=\"time-input\"\n [value]=\"endMinute.toString().padStart(2, '0')\"\n readonly\n title=\"End minute\">\n <button \n type=\"button\" \n class=\"time-btn time-btn-down\" \n (click)=\"decrementEndMinute()\"\n title=\"Decrement minute\">\n <svg width=\"12\" height=\"12\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M7.247 11.14l-4.796-5.481C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z\"/>\n </svg>\n </button>\n </div>\n @if (timeFormat === '12h') {\n <div class=\"time-period\">\n {{ endHour >= 12 ? 'PM' : 'AM' }}\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Footer with buttons -->\n @if (showClearButton || multiRange || requireApply) {\n <div class=\"date-picker-footer\">\n @if (requireApply && !multiRange) {\n <div class=\"apply-footer-actions\">\n <button \n type=\"button\" \n class=\"btn-cancel\" \n (click)=\"cancelSelection()\" \n [disabled]=\"!hasPendingChanges()\"\n title=\"Cancel selection\">\n Cancel\n </button>\n <button \n type=\"button\" \n class=\"btn-apply\" \n (click)=\"applySelection()\" \n [disabled]=\"!hasPendingChanges() || !pendingStartDate || !pendingEndDate\"\n title=\"Apply selection\">\n Apply\n </button>\n </div>\n }\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && !requireApply && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media(max-width:768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media(max-width:768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media(max-width:768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1;contain:layout paint}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;contain:layout paint}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400;position:relative}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day.in-hover-range{background-color:#e0e7ff;border-radius:0;opacity:.7;position:relative}.date-picker-day.in-hover-range:after{content:\"\";position:absolute;inset:0;border:1px dashed #6366f1;pointer-events:none}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-day.disabled{cursor:not-allowed;opacity:.4;color:#9ca3af;background-color:#f9fafb;text-decoration:line-through}.date-picker-day.disabled:hover{background-color:#f9fafb;color:#9ca3af}.date-picker-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply{padding:8px 24px;background-color:#2563eb;border:1px solid #2563eb;border-radius:6px;font-size:.875rem;font-weight:600;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-apply:hover:not(:disabled){background-color:#1d4ed8;border-color:#1d4ed8;transform:translateY(-1px);box-shadow:0 2px 8px #2563eb40}.date-picker-footer .btn-apply:active:not(:disabled){transform:translateY(0);box-shadow:none}.date-picker-footer .btn-apply:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .btn-cancel{padding:8px 24px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-cancel:hover:not(:disabled){background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-cancel:active:not(:disabled){transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-cancel:disabled{opacity:.5;cursor:not-allowed}.date-picker-footer .apply-footer-actions{display:flex;gap:8px;width:100%;justify-content:flex-end}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}.time-picker-container{display:flex;align-items:center;justify-content:center;gap:16px;padding:16px;border-top:1px solid #e5e7eb;border-bottom:1px solid #e5e7eb;margin:12px 0;background-color:#f9fafb}.time-picker-container .time-picker-section{display:flex;flex-direction:column;gap:8px;flex:1;align-items:center}.time-picker-container .time-picker-section .time-picker-label{font-size:.875rem;font-weight:600;color:#374151;text-align:center}.time-picker-container .time-picker-section .time-picker-inputs{display:flex;align-items:center;gap:8px}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group{display:flex;flex-direction:column;gap:4px;align-items:center}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input{width:48px;padding:8px 6px;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background-color:#fff;border:2px solid #e5e7eb;border-radius:6px;outline:none;transition:all .15s ease;cursor:default;-webkit-user-select:none;user-select:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-input:focus{border-color:var(--primary-color, #3b82f6);box-shadow:0 0 0 3px #3b82f61a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn{padding:4px 8px;background-color:#fff;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:hover{background-color:var(--primary-color, #3b82f6);border-color:var(--primary-color, #3b82f6);color:#fff;transform:translateY(-1px);box-shadow:0 2px 4px #0000001a}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn:active{transform:translateY(0);box-shadow:none}.time-picker-container .time-picker-section .time-picker-inputs .time-input-group .time-btn svg{pointer-events:none}.time-picker-container .time-picker-section .time-picker-inputs .time-separator{font-size:1.5rem;font-weight:700;color:#9ca3af;margin:0 4px}.time-picker-container .time-picker-section .time-picker-inputs .time-period{font-size:.875rem;font-weight:600;color:#6b7280;padding:8px 12px;background-color:#f3f4f6;border-radius:6px;min-width:48px;text-align:center}.time-picker-container .time-separator-vertical{width:1px;height:80px;background-color:#e5e7eb}\n"] }]
|
|
4043
4047
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { placeholder: [{
|
|
4044
4048
|
type: Input
|
|
4045
4049
|
}], startDate: [{
|