• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / 2c17752c-a120-4d08-b03c-7ff08eddc062

19 Nov 2024 07:40AM UTC coverage: 90.366%. Remained the same
2c17752c-a120-4d08-b03c-7ff08eddc062

Pull #3258

circleci

minlovehua
refactor: remove useless import #TINFR-1017
Pull Request #3258: refactor: remove useless import #TINFR-1017

5524 of 6762 branches covered (81.69%)

Branch coverage included in aggregate %.

13218 of 13978 relevant lines covered (94.56%)

995.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.62
/src/date-picker/lib/popups/date-popup.component.ts
1
import { endOfDay, startOfDay } from 'date-fns';
2
import { FunctionProp, TinyDate, TinyDateCompareGrain, helpers, isFunction, isUndefinedOrNull, sortRangeValue } from 'ngx-tethys/util';
3

4
import {
5
    ChangeDetectionStrategy,
6
    ChangeDetectorRef,
7
    Component,
8
    EventEmitter,
9
    Input,
10
    OnChanges,
11
    OnInit,
12
    Output,
13
    SimpleChanges,
14
    TemplateRef,
15
    inject
16
} from '@angular/core';
17

18
import { NgTemplateOutlet } from '@angular/common';
1✔
19
import { FormsModule } from '@angular/forms';
20
import { ThyButtonIcon } from 'ngx-tethys/button';
150✔
21
import { ThyNav, ThyNavItemDirective } from 'ngx-tethys/nav';
150✔
22
import { ThyDatePickerConfigService } from '../../date-picker.service';
150✔
23
import { CompatibleValue, DatePickerFlexibleTab, RangeAdvancedValue, RangePartType } from '../../inner-types';
150✔
24
import { dateAddAmount, getShortcutValue, hasValue, makeValue, setValueByTimestampPrecision, transformDateValue } from '../../picker.util';
150✔
25
import {
150✔
26
    CompatibleDate,
150✔
27
    CompatiblePresets,
150✔
28
    DisabledDateFn,
150✔
29
    SupportTimeOptions,
150✔
30
    ThyDateChangeEvent,
150✔
31
    ThyDateGranularity,
150✔
32
    ThyPanelMode,
150✔
33
    ThyShortcutPosition,
150✔
34
    ThyShortcutPreset,
150✔
35
    ThyShortcutValue
36
} from '../../standard-types';
37
import { CalendarFooter } from '../calendar/calendar-footer.component';
1✔
38
import { DateCarousel } from '../date-carousel/date-carousel.component';
39
import { InnerPopup } from './inner-popup.component';
40

1✔
41
/**
1✔
42
 * @private
43
 */
44
@Component({
149✔
45
    changeDetection: ChangeDetectionStrategy.OnPush,
149✔
46
    // eslint-disable-next-line @angular-eslint/component-selector
149!
47
    selector: 'date-popup',
×
48
    exportAs: 'datePopup',
49
    templateUrl: './date-popup.component.html',
149!
50
    standalone: true,
×
51
    imports: [ThyNav, ThyNavItemDirective, ThyButtonIcon, DateCarousel, FormsModule, NgTemplateOutlet, InnerPopup, CalendarFooter]
×
52
})
53
export class DatePopup implements OnChanges, OnInit {
149✔
54
    private cdr = inject(ChangeDetectorRef);
149✔
55
    private datePickerConfigService = inject(ThyDatePickerConfigService);
149✔
56

8✔
57
    @Input() isRange: boolean;
58
    @Input() showWeek: boolean;
59

60
    @Input() format: string;
61
    @Input() disabledDate: DisabledDateFn;
62
    @Input() minDate: Date | number;
63
    @Input() maxDate: Date | number;
64
    @Input() showToday: boolean;
307✔
65

149✔
66
    /**
59✔
67
     * 是否支持设置时间(时、分)
68
     */
69
    @Input() showTime: SupportTimeOptions | boolean;
90✔
70

71
    /**
72
     * 是否展示时间(时、分)
307✔
73
     */
149✔
74
    @Input() mustShowTime: boolean;
75

307✔
76
    @Input() dateRender: FunctionProp<TemplateRef<Date> | string>;
198✔
77
    @Input() className: string;
78
    @Input() panelMode: ThyPanelMode | ThyPanelMode[];
79
    @Input() value: CompatibleValue;
80
    @Input() defaultPickerValue: CompatibleDate | number;
149✔
81

149✔
82
    @Input() showShortcut: boolean;
414✔
83

84
    @Input() shortcutPresets: CompatiblePresets;
85

149✔
86
    @Input() shortcutPosition: ThyShortcutPosition;
94✔
87

91✔
88
    @Input() flexible: boolean;
89

94✔
90
    @Input() flexibleDateGranularity: ThyDateGranularity;
94!
91

94✔
92
    @Input() timestampPrecision: 'seconds' | 'milliseconds';
94✔
93

94✔
94
    @Output() readonly panelModeChange = new EventEmitter<ThyPanelMode | ThyPanelMode[]>();
94✔
95
    @Output() readonly calendarChange = new EventEmitter<CompatibleValue>();
94✔
96
    @Output() readonly valueChange = new EventEmitter<CompatibleValue | RangeAdvancedValue>();
30✔
97
    @Output() readonly resultOk = new EventEmitter<void>(); // Emitted when done with date selecting
114✔
98
    @Output() readonly showTimePickerChange = new EventEmitter<boolean>();
114✔
99
    @Output() readonly dateValueChange = new EventEmitter<ThyDateChangeEvent>();
114✔
100

114✔
101
    prefixCls = 'thy-calendar';
114✔
102
    showTimePicker = false;
10✔
103
    timeOptions: SupportTimeOptions | SupportTimeOptions[] | null;
104
    activeDate: TinyDate | TinyDate[];
105
    selectedValue: TinyDate[] = []; // Range ONLY
104✔
106
    hoverValue: TinyDate[] = []; // Range ONLY
107

108
    advancedSelectedValue: RangeAdvancedValue; // advanced ONLY
109

110
    flexibleActiveTab: DatePickerFlexibleTab = 'advanced';
64✔
111

133✔
112
    get hasTimePicker(): boolean {
133✔
113
        return !!this.showTime;
133✔
114
    }
11✔
115
    private partTypeMap: { [key: string]: number } = { left: 0, right: 1 };
116

117
    [property: string]: any;
122✔
118

119
    endPanelMode: ThyPanelMode | ThyPanelMode[];
120

121
    innerShortcutPresets: ThyShortcutPreset[];
122

123
    disableTimeConfirm = false;
124

125
    setProperty<T extends keyof DatePopup>(key: T, value: this[T]): void {
497✔
126
        this[key] = value;
497✔
127
        this.cdr.markForCheck();
142✔
128
    }
142✔
129

130
    ngOnInit(): void {
497✔
131
        this.initShortcutPresets();
234✔
132
        this.initPanelMode();
196✔
133
        if (this.flexible && this.flexibleDateGranularity === 'day') {
134
            this.flexibleActiveTab = 'custom';
234✔
135
        }
136
        if (this.defaultPickerValue && !hasValue(this.value)) {
137
            const { value } = transformDateValue(this.defaultPickerValue);
263✔
138
            this.value = makeValue(value, this.isRange);
139
        }
497✔
140
        this.updateActiveDate();
141
        this.initDisabledDate();
142
        if (this.isRange && this.flexible && this.value) {
149!
143
            this.advancedSelectedValue = {
×
144
                begin: this.value[0],
×
145
                end: this.value[1],
146
                dateGranularity: this.flexibleDateGranularity
147
            };
×
148
        }
149
    }
150

151
    ngOnChanges(changes: SimpleChanges): void {
149✔
152
        if (changes.panelMode) {
59✔
153
            if (helpers.isArray(this.panelMode)) {
154
                this.endPanelMode = [...this.panelMode];
155
            } else {
90✔
156
                this.endPanelMode = this.panelMode;
157
            }
158
        }
159
        if (changes.defaultPickerValue) {
160
            this.updateActiveDate();
161
        }
162
        if (changes.value && changes.value.currentValue) {
163
            this.updateActiveDate();
149✔
164
        }
15✔
165
    }
15✔
166

167
    initShortcutPresets(): void {
149✔
168
        const { shortcutRangesPresets, shortcutDatePresets, showShortcut } = this.datePickerConfigService;
13✔
169

13✔
170
        this.showShortcut =
171
            ['date', 'date,date'].includes(this.panelMode.toString()) && isUndefinedOrNull(this.showShortcut)
149✔
172
                ? showShortcut
6✔
173
                : this.showShortcut;
174

149✔
175
        if (this.showShortcut) {
21,394✔
176
            if (!this.shortcutPresets) {
21,394✔
177
                this.shortcutPresets = this.isRange ? shortcutRangesPresets : shortcutDatePresets;
2,310✔
178
            }
179

21,394✔
180
            this.innerShortcutPresets = isFunction(this.shortcutPresets) ? this.shortcutPresets() : this.shortcutPresets;
1,830✔
181
            if (this.innerShortcutPresets.length) {
182
                const minDate: TinyDate = this.getMinTinyDate();
21,394✔
183
                const maxDate: TinyDate = this.getMaxTinyDate();
630✔
184

185
                const minTime = minDate ? minDate.getTime() : null;
21,394✔
186
                const maxTime = maxDate ? maxDate.getTime() : null;
187

188
                if (this.isRange) {
189
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
66✔
190
                        const begin: number | Date = getShortcutValue(preset.value[0]);
66✔
191
                        const beginTime: number = new TinyDate(startOfDay(begin)).getTime();
192

193
                        const end: number | Date = getShortcutValue(preset.value[1]);
5✔
194
                        const endTime: number = new TinyDate(endOfDay(end)).getTime();
5✔
195

5✔
196
                        if ((minDate && endTime < minTime) || (maxDate && beginTime > maxTime)) {
197
                            preset.disabled = true;
198
                        } else {
2!
199
                            preset.disabled = false;
2✔
200
                        }
201
                    });
202
                } else {
1!
203
                    this.innerShortcutPresets.forEach((preset: ThyShortcutPreset) => {
204
                        const singleValue: number | Date = getShortcutValue(preset.value as ThyShortcutValue);
×
205
                        const singleTime: number = new TinyDate(singleValue).getTime();
×
206

×
207
                        if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
208
                            preset.disabled = true;
209
                        } else {
×
210
                            preset.disabled = false;
211
                        }
212
                    });
213
                }
214
            }
14✔
215
        }
1✔
216
    }
217

218
    updateActiveDate() {
13✔
219
        this.clearHoverValue();
220
        if (!this.value) {
14✔
221
            const { value } = transformDateValue(this.defaultPickerValue);
222
            this.value = makeValue(value, this.isRange);
223
        }
42✔
224
        if (this.isRange) {
10✔
225
            if (!this.flexible || this.flexibleDateGranularity === 'day') {
10✔
226
                this.selectedValue = this.value as TinyDate[];
227
            }
228
            this.activeDate = this.normalizeRangeValue(this.value as TinyDate[], this.getPanelMode(this.endPanelMode) as ThyPanelMode);
32✔
229
        } else {
230
            this.activeDate = this.value as TinyDate;
231
        }
232
        this.isDisableTimeConfirm();
28!
233
    }
234

235
    initPanelMode() {
236
        if (!this.endPanelMode) {
28✔
237
            if (helpers.isArray(this.panelMode)) {
238
                this.endPanelMode = [...this.panelMode];
239
            } else {
240
                this.endPanelMode = this.panelMode;
2✔
241
            }
242
        } else {
243
            if (helpers.isArray(this.endPanelMode)) {
3✔
244
                this.panelMode = [...this.endPanelMode];
3!
245
            } else {
3✔
246
                this.panelMode = this.endPanelMode;
247
            }
248
        }
×
249
    }
250

3✔
251
    initDisabledDate(): void {
252
        let minDate: TinyDate;
253
        let maxDate: TinyDate;
254
        let disabledDateFn: DisabledDateFn;
255
        if (this.minDate) {
256
            const { value } = transformDateValue(this.minDate);
257
            minDate = new TinyDate(value as Date);
5✔
258
        }
259
        if (this.maxDate) {
5✔
260
            const { value } = transformDateValue(this.maxDate);
5✔
261
            maxDate = new TinyDate(value as Date);
262
        }
263
        if (this.disabledDate) {
264
            disabledDateFn = this.disabledDate;
265
        }
34✔
266
        this.disabledDate = d => {
267
            let expression = false;
20✔
268
            if (minDate) {
20✔
269
                expression = d < minDate.startOfDay().nativeDate;
20✔
270
            }
271
            if (maxDate && !expression) {
10✔
272
                expression = d > maxDate.endOfDay().nativeDate;
10✔
273
            }
10✔
274
            if (disabledDateFn && typeof disabledDateFn === 'function' && !expression) {
275
                expression = disabledDateFn(d);
10!
276
            }
277
            return expression;
10✔
278
        };
10✔
279
    }
10✔
280

10✔
281
    onShowTimePickerChange(show: boolean): void {
282
        this.showTimePicker = show;
283
        this.showTimePickerChange.emit(show);
284
    }
10✔
285

10✔
286
    onClickOk(): void {
10✔
287
        this.setValue(this.value);
10✔
288
        this.valueChange.emit(this.value);
289
        this.resultOk.emit();
290
    }
291

292
    onClickRemove(): void {
293
        this.value = this.isRange ? [] : null;
14✔
294
        this.valueChange.emit(this.value);
14✔
295
    }
14✔
296

297
    onDayHover(value: TinyDate): void {
298
        if (this.isRange && this.selectedValue[0] && !this.selectedValue[1]) {
299
            // When right value is selected, don't do hover
300
            const base = this.selectedValue[0]; // Use the left of selected value as the base to decide later hoverValue
301
            if (base.isBeforeDay(value)) {
25✔
302
                this.hoverValue = [base, value];
12✔
303
            } else {
304
                this.hoverValue = [value, base];
13✔
305
            }
13✔
306
        }
13✔
307
    }
13✔
308

13✔
309
    onPanelModeChange(mode: ThyPanelMode, partType?: RangePartType): void {
10✔
310
        if (this.isRange) {
311
            (this.panelMode as ThyPanelMode[])[this.getPartTypeIndex(partType)] = mode;
312
        } else {
3✔
313
            this.panelMode = mode;
314
        }
315
        this.panelModeChange.emit(this.panelMode);
316
    }
988!
317

×
318
    onHeaderChange(value: TinyDate, partType?: RangePartType): void {
×
319
        if (this.isRange) {
×
320
            this.activeDate[this.getPartTypeIndex(partType)] = value;
×
321
            this.activeDate = this.normalizeRangeValue(
322
                this.activeDate as TinyDate[],
×
323
                this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
324
            );
325
        } else {
988✔
326
            this.activeDate = value;
327
        }
328
    }
329

1,240✔
330
    onSelectTime(value: TinyDate, partType?: RangePartType): void {
786✔
331
        if (this.isRange) {
332
            // TODO:range picker set time
333
        } else {
454✔
334
            this.setValue(new TinyDate(value.nativeDate));
335
        }
336
    }
337

493✔
338
    selectTab(active: DatePickerFlexibleTab) {
266✔
339
        this.flexibleActiveTab = active;
266✔
340
    }
341

342
    clearFlexibleValue() {
227✔
343
        this.flexibleDateGranularity = null;
344
        if (this.flexibleActiveTab === 'advanced') {
345
            this.advancedSelectedValue = {};
346
        } else {
493✔
347
            this.selectedValue = [];
266✔
348
        }
349
        this.valueChange.emit({
350
            begin: null,
227✔
351
            end: null,
352
            dateGranularity: this.flexibleDateGranularity
353
        });
355✔
354
    }
1,339✔
355

356
    changeValueFromAdvancedSelect(value: RangeAdvancedValue) {
357
        this.valueChange.emit(value);
215✔
358
        // clear custom date when select a advanced date
359
        this.selectedValue = [];
360
        this.dateValueChange.emit({
215✔
361
            value: [value.begin, value.end]
362
        });
363
    }
507✔
364

365
    changeValueFromSelect(value: TinyDate, partType?: RangePartType): void {
366
        if (this.isRange) {
78✔
367
            // clear advanced date when select a custom date
78✔
368
            this.advancedSelectedValue = {};
1✔
369

1✔
370
            const [left, right] = this.selectedValue as TinyDate[];
371

372
            if ((!left && !right) || (left && right)) {
373
                // If totally full or empty, clean up && re-assign left first
374
                this.hoverValue = this.selectedValue = [value];
375
                this.selectedValue = [new TinyDate(startOfDay(this.selectedValue[0].nativeDate))];
376
                this.calendarChange.emit([this.selectedValue[0].clone()]);
77✔
377
            } else if (left && !right) {
41✔
378
                // If one of them is empty, assign the other one and sort, then set the final values
379
                this.clearHoverValue(); // Clean up
380
                this.setRangeValue('right', value);
78✔
381
                this.selectedValue = sortRangeValue(this.selectedValue); // Sort
382
                this.selectedValue = [
×
383
                    new TinyDate(startOfDay(this.selectedValue[0].nativeDate)),
254✔
384
                    new TinyDate(endOfDay(this.selectedValue[1].nativeDate))
385
                ];
386
                this.activeDate = this.normalizeRangeValue(
387
                    this.selectedValue,
388
                    this.getPanelMode(this.endPanelMode, partType) as ThyPanelMode
389
                );
390
                this.setValue(this.cloneRangeDate(this.selectedValue));
254✔
391
                this.calendarChange.emit(this.cloneRangeDate(this.selectedValue));
254✔
392
                this.dateValueChange.emit({
254✔
393
                    value: this.cloneRangeDate(this.selectedValue)
254✔
394
                });
254✔
395
            }
202✔
396
        } else {
397
            const updatedValue = this.updateHourMinute(value);
254✔
398
            this.setValue(updatedValue);
399
            this.dateValueChange.emit({
400
                value: updatedValue
10✔
401
            });
10✔
402
        }
403
    }
404

50✔
405
    private updateHourMinute(value: TinyDate): TinyDate {
406
        if (!this.value) {
407
            return value;
575✔
408
        }
475✔
409
        const originDate = this.value as TinyDate;
410
        const dateTime = [value.getHours(), value.getMinutes(), value.getSeconds()];
100✔
411
        const originDateTime = [originDate.getHours(), originDate.getMinutes(), originDate.getSeconds()];
100✔
412

100✔
413
        const isEqualTime = dateTime.toString() === originDateTime.toString();
100✔
414
        if (isEqualTime) {
16✔
415
            return value;
416
        } else {
417
            return value.setHms(originDateTime[0], originDateTime[1], originDateTime[2]);
84✔
418
        }
419
    }
420

421
    enablePrevNext(direction: 'prev' | 'next', partType?: RangePartType): boolean {
21✔
422
        if (this.isRange && this.panelMode === this.endPanelMode) {
21✔
423
            const [start, end] = this.activeDate as TinyDate[];
21✔
424
            const showMiddle = !start.addMonths(1).isSame(end, 'month'); // One month diff then don't show middle prev/next
21✔
425
            if ((partType === 'left' && direction === 'next') || (partType === 'right' && direction === 'prev')) {
21✔
426
                return showMiddle;
10✔
427
            }
10✔
428
            return true;
10✔
429
        } else {
10✔
430
            return true;
10!
431
        }
×
432
    }
433

10✔
434
    getPanelMode(panelMode: ThyPanelMode | ThyPanelMode[], partType?: RangePartType): ThyPanelMode {
1✔
435
        if (this.isRange) {
436
            return panelMode[this.getPartTypeIndex(partType)] as ThyPanelMode;
9✔
437
        } else {
1✔
438
            return panelMode as ThyPanelMode;
439
        }
8✔
440
    }
1✔
441

442
    getValueBySelector(partType?: RangePartType): TinyDate {
7✔
443
        if (this.isRange) {
444
            const valueShow = this.selectedValue; // Use the real time value that without decorations when timepicker is shown up
445
            return (valueShow as TinyDate[])[this.getPartTypeIndex(partType)];
11✔
446
        } else {
11!
447
            return this.value as TinyDate;
×
448
        }
449
    }
11✔
450

451
    getActiveDate(partType?: RangePartType): TinyDate {
452
        if (this.isRange) {
453
            return this.activeDate[this.getPartTypeIndex(partType)];
24✔
454
        } else {
2✔
455
            return this.activeDate as TinyDate;
456
        }
22✔
457
    }
22✔
458

1✔
459
    getPartTypeIndex(partType: RangePartType = 'left'): number {
460
        return this.partTypeMap[partType];
461
    }
21✔
462

10✔
463
    private getMinTinyDate() {
10✔
464
        return this.minDate ? new TinyDate(transformDateValue(this.minDate).value as Date) : null;
10!
465
    }
10✔
466

467
    private getMaxTinyDate() {
468
        return this.maxDate ? new TinyDate(transformDateValue(this.maxDate).value as Date) : null;
469
    }
10✔
470

471
    private clearHoverValue(): void {
472
        this.hoverValue = [];
473
    }
11✔
474

11✔
475
    private setValue(value: CompatibleValue): void {
11✔
476
        this.value = value;
477
        if (this.isRange && this.flexible) {
21✔
478
            this.flexibleDateGranularity = 'day';
21✔
479
            this.valueChange.emit({
21✔
480
                begin: value[0],
21✔
481
                end: value[1],
482
                dateGranularity: this.flexibleDateGranularity
483
            });
21✔
484
        } else {
1✔
485
            if (!this.showTime || !this.showTimePicker) {
486
                this.valueChange.emit(this.value);
487
            }
1✔
488
        }
489
        this.isDisableTimeConfirm();
490
    }
491

492
    private normalizeRangeValue(value: TinyDate[], mode: ThyPanelMode = 'month'): TinyDate[] {
493
        const headerModes: { [key in ThyPanelMode]?: ThyPanelMode } = {
494
            week: 'month',
495
            date: 'month',
496
            month: 'year',
497
            quarter: 'year',
498
            year: 'decade'
499
        };
500
        const headerMode = headerModes[mode];
501
        const [start, end] = value;
502
        const newStart = start || new TinyDate();
503
        let newEnd = end;
504
        if (!newEnd || newStart.isSame(end, headerMode as TinyDateCompareGrain)) {
505
            newEnd = dateAddAmount(newStart, 1, headerMode);
506
        }
507
        return [newStart, newEnd];
508
    }
509

510
    private setRangeValue(partType: RangePartType, value: TinyDate): void {
511
        const ref = (this.selectedValue = this.cloneRangeDate(this.selectedValue as TinyDate[]));
512
        ref[this.getPartTypeIndex(partType)] = value;
513
    }
514

515
    private cloneRangeDate(value: TinyDate[]): TinyDate[] {
516
        return [value[0] && value[0].clone(), value[1] && value[1].clone()] as TinyDate[];
1✔
517
    }
518

519
    private isDisableTimeConfirm() {
520
        if (this.isRange || !this.showTime) {
521
            return;
522
        }
523

524
        const date: TinyDate = this.value ? (this.value as TinyDate) : new TinyDate();
525
        const minDate: TinyDate = this.getMinTinyDate();
526
        const maxDate: TinyDate = this.getMaxTinyDate();
527

528
        if ((minDate && date.getTime() < minDate.getTime()) || (maxDate && date.getTime() > maxDate.getTime())) {
529
            this.disableTimeConfirm = true;
530
        } else {
531
            this.disableTimeConfirm = false;
532
        }
533
    }
534

535
    private getSelectedShortcutPreset(date: CompatibleValue): CompatibleValue {
536
        const minDate: TinyDate = this.getMinTinyDate();
537
        const maxDate: TinyDate = this.getMaxTinyDate();
538

539
        const minTime: number = (minDate && minDate.getTime()) || null;
540
        const maxTime: number = (maxDate && maxDate.getTime()) || null;
541

542
        if (helpers.isArray(date)) {
543
            const startDate: TinyDate = date[0];
544
            const endDate: TinyDate = date[1];
545

546
            const startTime: number = startDate.getTime();
547
            const endTime: number = endDate.getTime();
548

549
            if ((maxDate && startTime > maxTime) || (minDate && endTime < minTime)) {
550
                return [];
551
            }
552

553
            if (minDate && startTime < minTime && maxDate && endTime > maxTime) {
554
                return [minDate, maxDate];
555
            }
556

557
            if (minDate && startTime < minTime) {
558
                return [minDate, endDate];
559
            }
560

561
            if (maxDate && endTime > maxTime) {
562
                return [startDate, maxDate];
563
            }
564

565
            return date;
566
        } else {
567
            const singleTime: number = date.getTime();
568

569
            if ((minDate && singleTime < minTime) || (maxDate && singleTime > maxTime)) {
570
                return null;
571
            }
572

573
            return date;
574
        }
575
    }
576

577
    shortcutSetValue(shortcutPresets: ThyShortcutPreset) {
578
        if (shortcutPresets.disabled) {
579
            return;
580
        }
581

582
        const { value } = shortcutPresets;
583
        if (!value) {
584
            return;
585
        }
586

587
        let selectedPresetValue: CompatibleValue;
588
        if (helpers.isArray(value)) {
589
            const begin: number | Date = getShortcutValue(value[0]);
590
            const end: number | Date = getShortcutValue(value[1]);
591

592
            if (begin && end) {
593
                this.selectedValue = this.getSelectedShortcutPreset([
594
                    new TinyDate(startOfDay(begin)),
595
                    new TinyDate(endOfDay(end))
596
                ]) as TinyDate[];
597

598
                selectedPresetValue = this.cloneRangeDate(this.selectedValue);
599
            }
600
        } else {
601
            const singleDate: number | Date = getShortcutValue(value);
602
            const singleTinyDate: TinyDate = this.updateHourMinute(new TinyDate(singleDate));
603
            selectedPresetValue = this.getSelectedShortcutPreset(singleTinyDate) as TinyDate;
604
        }
605
        this.setValue(selectedPresetValue);
606
        const shortcutPresetsValue = setValueByTimestampPrecision(shortcutPresets?.value, this.isRange, this.timestampPrecision) as number;
607
        this.dateValueChange.emit({
608
            value: helpers.isArray(value) ? this.selectedValue : selectedPresetValue,
609
            triggerPreset: Object.assign({}, shortcutPresets, { value: shortcutPresetsValue })
610
        });
611
        if (!helpers.isArray(value) && this.showTime && this.showTimePicker) {
612
            this.updateActiveDate();
613
        }
614
    }
615
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc