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

atinc / ngx-tethys / 5fa9630c-19a1-4ee7-af3d-6a0c3535952a

08 Oct 2024 08:24AM UTC coverage: 90.438% (+0.007%) from 90.431%
5fa9630c-19a1-4ee7-af3d-6a0c3535952a

push

circleci

minlovehua
refactor: refactor all control-flow directives to new control-flow #TINFR-381

5511 of 6738 branches covered (81.79%)

Branch coverage included in aggregate %.

98 of 104 new or added lines in 58 files covered. (94.23%)

113 existing lines in 17 files now uncovered.

13253 of 14010 relevant lines covered (94.6%)

991.73 hits per line

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

90.64
/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
    numberAttribute,
11
    OnChanges,
12
    OnInit,
13
    Output,
14
    SimpleChanges,
15
    TemplateRef
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';
1✔
21
import { ThyNav, ThyNavItemDirective } from 'ngx-tethys/nav';
22
import { ThyDatePickerConfigService } from '../../date-picker.service';
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
150✔
36
} from '../../standard-types';
150✔
37
import { CalendarFooter } from '../calendar/calendar-footer.component';
150✔
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,
×
NEW
51
    imports: [ThyNav, ThyNavItemDirective, ThyButtonIcon, DateCarousel, FormsModule, NgTemplateOutlet, InnerPopup, CalendarFooter]
×
52
})
53
export class DatePopup implements OnChanges, OnInit {
149✔
54
    @Input() isRange: boolean;
149✔
55
    @Input() showWeek: boolean;
149✔
56

8✔
57
    @Input() format: string;
58
    @Input() disabledDate: DisabledDateFn;
59
    @Input() minDate: Date | number;
60
    @Input() maxDate: Date | number;
61
    @Input() showToday: boolean;
62

63
    /**
64
     * 是否支持设置时间(时、分)
307✔
65
     */
149✔
66
    @Input() showTime: SupportTimeOptions | boolean;
59✔
67

68
    /**
69
     * 是否展示时间(时、分)
90✔
70
     */
71
    @Input() mustShowTime: boolean;
72

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

79
    @Input() showShortcut: boolean;
80

149✔
81
    @Input() shortcutPresets: CompatiblePresets;
149✔
82

414✔
83
    @Input() shortcutPosition: ThyShortcutPosition;
84

85
    @Input() flexible: boolean;
149✔
86

94✔
87
    @Input() flexibleDateGranularity: ThyDateGranularity;
91✔
88

89
    @Input() timestampPrecision: 'seconds' | 'milliseconds';
94✔
90

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

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

105
    advancedSelectedValue: RangeAdvancedValue; // advanced ONLY
104✔
106

107
    flexibleActiveTab: DatePickerFlexibleTab = 'advanced';
108

109
    get hasTimePicker(): boolean {
110
        return !!this.showTime;
64✔
111
    }
133✔
112
    private partTypeMap: { [key: string]: number } = { left: 0, right: 1 };
133✔
113

133✔
114
    [property: string]: any;
11✔
115

116
    endPanelMode: ThyPanelMode | ThyPanelMode[];
117

122✔
118
    innerShortcutPresets: ThyShortcutPreset[];
119

120
    disableTimeConfirm = false;
121

122
    constructor(
123
        private cdr: ChangeDetectorRef,
124
        private datePickerConfigService: ThyDatePickerConfigService
125
    ) {}
497✔
126

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

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

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

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

149✔
172
        this.showShortcut =
6✔
173
            ['date', 'date,date'].includes(this.panelMode.toString()) && isUndefinedOrNull(this.showShortcut)
174
                ? showShortcut
149✔
175
                : this.showShortcut;
21,394✔
176

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

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

187
                const minTime = minDate ? minDate.getTime() : null;
188
                const maxTime = maxDate ? maxDate.getTime() : null;
189

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

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

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

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

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

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

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

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

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

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

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

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

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

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

266✔
340
    selectTab(active: DatePickerFlexibleTab) {
341
        this.flexibleActiveTab = active;
342
    }
227✔
343

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

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

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

372
            const [left, right] = this.selectedValue as TinyDate[];
373

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

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

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

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

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

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

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

461
    getPartTypeIndex(partType: RangePartType = 'left'): number {
21✔
462
        return this.partTypeMap[partType];
10✔
463
    }
10✔
464

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

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

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

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

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

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

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

1✔
521
    private isDisableTimeConfirm() {
522
        if (this.isRange || !this.showTime) {
523
            return;
524
        }
525

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

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

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

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

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

548
            const startTime: number = startDate.getTime();
549
            const endTime: number = endDate.getTime();
550

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

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

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

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

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

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

575
            return date;
576
        }
577
    }
578

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

584
        const { value } = shortcutPresets;
585
        if (!value) {
586
            return;
587
        }
588

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

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

600
                selectedPresetValue = this.cloneRangeDate(this.selectedValue);
601
            }
602
        } else {
603
            const singleDate: number | Date = getShortcutValue(value);
604
            const singleTinyDate: TinyDate = this.updateHourMinute(new TinyDate(singleDate));
605
            selectedPresetValue = this.getSelectedShortcutPreset(singleTinyDate) as TinyDate;
606
        }
607
        this.setValue(selectedPresetValue);
608
        const shortcutPresetsValue = setValueByTimestampPrecision(shortcutPresets?.value, this.isRange, this.timestampPrecision) as number;
609
        this.dateValueChange.emit({
610
            value: helpers.isArray(value) ? this.selectedValue : selectedPresetValue,
611
            triggerPreset: Object.assign({}, shortcutPresets, { value: shortcutPresetsValue })
612
        });
613
        if (!helpers.isArray(value) && this.showTime && this.showTimePicker) {
614
            this.updateActiveDate();
615
        }
616
    }
617
}
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