vueless 1.0.2-beta.52 → 1.0.2-beta.54
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/package.json +1 -1
- package/ui.form-calendar/UCalendar.vue +38 -42
- package/ui.form-calendar/UCalendarDayView.vue +10 -14
- package/ui.form-calendar/UCalendarMonthView.vue +6 -15
- package/ui.form-calendar/UCalendarYearView.vue +29 -53
- package/ui.form-calendar/types.ts +2 -2
- package/ui.form-calendar/utilCalendar.ts +3 -7
- package/ui.image-icon/storybook/stories.ts +1 -1
package/package.json
CHANGED
|
@@ -10,9 +10,9 @@ import UButton from "../ui.button/UButton.vue";
|
|
|
10
10
|
import {
|
|
11
11
|
parseDate,
|
|
12
12
|
formatDate,
|
|
13
|
-
getYearsRange,
|
|
14
13
|
dateIsOutOfRange,
|
|
15
14
|
isNumeric,
|
|
15
|
+
getYearsRangeLabel,
|
|
16
16
|
} from "./utilCalendar.ts";
|
|
17
17
|
|
|
18
18
|
import { getDateWithoutTime, addMonths, addDays, addYears, getSortedLocale } from "./utilDate.ts";
|
|
@@ -39,7 +39,6 @@ import {
|
|
|
39
39
|
import defaultConfig from "./config.ts";
|
|
40
40
|
|
|
41
41
|
import type { Props, DateValue, RangeDate, Locale, Config } from "./types.ts";
|
|
42
|
-
import type { Ref } from "vue";
|
|
43
42
|
import type { DateLocale } from "./utilFormatting.ts";
|
|
44
43
|
import type { ComponentExposed } from "../types.ts";
|
|
45
44
|
|
|
@@ -99,11 +98,12 @@ const minutesRef = useTemplateRef<HTMLInputElement>("minutes-input");
|
|
|
99
98
|
const secondsRef = useTemplateRef<HTMLInputElement>("seconds-input");
|
|
100
99
|
const okButton = useTemplateRef<ComponentExposed<typeof UButton>>("ok-button");
|
|
101
100
|
const dayViewRef = useTemplateRef<ComponentExposed<typeof DayView>>("day-view");
|
|
101
|
+
const yearViewRef = useTemplateRef<ComponentExposed<typeof YearView>>("year-view");
|
|
102
102
|
|
|
103
|
-
const activeDate
|
|
104
|
-
const activeMonth: Ref<Date | null> = ref(null);
|
|
103
|
+
const activeDate = ref(getDateWithoutTime());
|
|
105
104
|
|
|
106
105
|
const currentView = ref(props.view);
|
|
106
|
+
const isArrowKeyDirty = ref(false);
|
|
107
107
|
|
|
108
108
|
watch(
|
|
109
109
|
() => props.view,
|
|
@@ -292,13 +292,10 @@ const userFormattedDate = computed(() => {
|
|
|
292
292
|
});
|
|
293
293
|
|
|
294
294
|
const viewSwitchLabel = computed(() => {
|
|
295
|
-
const localValue =
|
|
296
|
-
activeDate.value || activeMonth.value || selectedDate.value || getDateWithoutTime();
|
|
297
|
-
|
|
298
295
|
return {
|
|
299
|
-
year: formatDate(
|
|
300
|
-
month: formatDate(
|
|
301
|
-
yearsRange:
|
|
296
|
+
year: formatDate(activeDate.value, "Y", locale.value),
|
|
297
|
+
month: formatDate(activeDate.value, "F", locale.value),
|
|
298
|
+
yearsRange: getYearsRangeLabel(yearViewRef.value?.years || []),
|
|
302
299
|
};
|
|
303
300
|
});
|
|
304
301
|
|
|
@@ -398,7 +395,7 @@ watch(
|
|
|
398
395
|
);
|
|
399
396
|
|
|
400
397
|
if (notInView) {
|
|
401
|
-
|
|
398
|
+
activeDate.value = parsedNewDateTo;
|
|
402
399
|
}
|
|
403
400
|
}
|
|
404
401
|
|
|
@@ -412,7 +409,7 @@ watch(
|
|
|
412
409
|
);
|
|
413
410
|
|
|
414
411
|
if (notInView) {
|
|
415
|
-
|
|
412
|
+
activeDate.value = parsedNewValueFrom;
|
|
416
413
|
}
|
|
417
414
|
}
|
|
418
415
|
},
|
|
@@ -439,8 +436,7 @@ function onInputDate(newDate: Date | null) {
|
|
|
439
436
|
if (newDate === null) {
|
|
440
437
|
localValue.value = newDate;
|
|
441
438
|
|
|
442
|
-
activeDate.value =
|
|
443
|
-
activeMonth.value = null;
|
|
439
|
+
activeDate.value = getDateWithoutTime();
|
|
444
440
|
|
|
445
441
|
emit("input", localValue.value);
|
|
446
442
|
|
|
@@ -467,8 +463,7 @@ function onInputDate(newDate: Date | null) {
|
|
|
467
463
|
}
|
|
468
464
|
|
|
469
465
|
if (!props.range) {
|
|
470
|
-
activeDate.value =
|
|
471
|
-
activeMonth.value = null;
|
|
466
|
+
activeDate.value = newDate;
|
|
472
467
|
}
|
|
473
468
|
|
|
474
469
|
wrapperRef.value?.focus();
|
|
@@ -487,6 +482,8 @@ function onKeydown(event: KeyboardEvent) {
|
|
|
487
482
|
minutesRef.value?.blur();
|
|
488
483
|
hoursRef.value?.blur();
|
|
489
484
|
secondsRef.value?.blur();
|
|
485
|
+
|
|
486
|
+
isArrowKeyDirty.value = true;
|
|
490
487
|
}
|
|
491
488
|
|
|
492
489
|
if (event.code === KeyCode.Enter) {
|
|
@@ -504,16 +501,14 @@ function onKeydown(event: KeyboardEvent) {
|
|
|
504
501
|
}
|
|
505
502
|
|
|
506
503
|
function onInput(date: Date | null): void {
|
|
507
|
-
activeDate.value =
|
|
508
|
-
activeMonth.value = date;
|
|
504
|
+
activeDate.value = date || getDateWithoutTime();
|
|
509
505
|
|
|
510
506
|
if (isCurrentView.value.month) currentView.value = View.Day;
|
|
511
507
|
if (isCurrentView.value.year) currentView.value = View.Month;
|
|
512
508
|
}
|
|
513
509
|
|
|
514
510
|
function arrowKeyHandler(event: KeyboardEvent) {
|
|
515
|
-
const currentActiveDate =
|
|
516
|
-
activeDate.value || activeMonth.value || selectedDate.value || getDateWithoutTime();
|
|
511
|
+
const currentActiveDate = activeDate.value || selectedDate.value || getDateWithoutTime();
|
|
517
512
|
|
|
518
513
|
let newActiveDate;
|
|
519
514
|
|
|
@@ -561,57 +556,53 @@ function arrowKeyHandler(event: KeyboardEvent) {
|
|
|
561
556
|
|
|
562
557
|
if (newActiveDate && !isOutOfRange) {
|
|
563
558
|
activeDate.value = newActiveDate;
|
|
564
|
-
activeMonth.value = newActiveDate;
|
|
565
559
|
}
|
|
566
560
|
}
|
|
567
561
|
|
|
568
562
|
function addActiveMonth(amount: number) {
|
|
569
|
-
const currentActiveMonth =
|
|
563
|
+
const currentActiveMonth = activeDate.value || selectedDate.value || getDateWithoutTime();
|
|
570
564
|
|
|
571
|
-
|
|
565
|
+
activeDate.value = addMonths(currentActiveMonth, amount);
|
|
572
566
|
}
|
|
573
567
|
|
|
574
568
|
function addActiveYear(amount: number) {
|
|
575
|
-
const currentActiveMonth =
|
|
569
|
+
const currentActiveMonth = activeDate.value || selectedDate.value || getDateWithoutTime();
|
|
576
570
|
|
|
577
|
-
|
|
571
|
+
activeDate.value = addYears(currentActiveMonth, amount);
|
|
578
572
|
}
|
|
579
573
|
|
|
580
574
|
function onClickNextButton() {
|
|
581
|
-
activeDate.value = null;
|
|
582
|
-
|
|
583
575
|
if (isCurrentView.value.day) addActiveMonth(1);
|
|
584
576
|
if (isCurrentView.value.month) addActiveYear(1);
|
|
585
577
|
if (isCurrentView.value.year) addActiveYear(YEARS_PER_VIEW);
|
|
578
|
+
|
|
579
|
+
isArrowKeyDirty.value = false;
|
|
586
580
|
}
|
|
587
581
|
|
|
588
582
|
function onClickNextYearButton() {
|
|
589
|
-
activeDate.value = null;
|
|
590
|
-
|
|
591
583
|
addActiveYear(1);
|
|
584
|
+
|
|
585
|
+
isArrowKeyDirty.value = false;
|
|
592
586
|
}
|
|
593
587
|
|
|
594
588
|
function onClickPrevButton() {
|
|
595
|
-
activeDate.value = null;
|
|
596
|
-
|
|
597
589
|
if (isCurrentView.value.day) addActiveMonth(-1);
|
|
598
590
|
if (isCurrentView.value.month) addActiveYear(-1);
|
|
599
591
|
if (isCurrentView.value.year) addActiveYear(YEARS_PER_VIEW * -1);
|
|
592
|
+
|
|
593
|
+
isArrowKeyDirty.value = false;
|
|
600
594
|
}
|
|
601
595
|
|
|
602
596
|
function onClickPrevYearButton() {
|
|
603
|
-
activeDate.value = null;
|
|
604
|
-
|
|
605
597
|
addActiveYear(-1);
|
|
598
|
+
|
|
599
|
+
isArrowKeyDirty.value = false;
|
|
606
600
|
}
|
|
607
601
|
|
|
608
602
|
function enterKeyHandler() {
|
|
609
603
|
if (activeDate.value !== null && isCurrentView.value.day) {
|
|
610
604
|
localValue.value = activeDate.value;
|
|
611
605
|
|
|
612
|
-
activeDate.value = null;
|
|
613
|
-
activeMonth.value = null;
|
|
614
|
-
|
|
615
606
|
emit("input", localValue.value);
|
|
616
607
|
emit("submit");
|
|
617
608
|
}
|
|
@@ -625,9 +616,11 @@ function onClickViewSwitch() {
|
|
|
625
616
|
const currentViewIndex = views.indexOf(currentView.value);
|
|
626
617
|
const nextViewIndex = currentViewIndex + 1;
|
|
627
618
|
|
|
628
|
-
activeDate.value = null;
|
|
629
|
-
|
|
630
619
|
currentView.value = (views[nextViewIndex] || views.at(0)) as View;
|
|
620
|
+
|
|
621
|
+
nextTick(() => {
|
|
622
|
+
wrapperRef.value!.focus();
|
|
623
|
+
});
|
|
631
624
|
}
|
|
632
625
|
|
|
633
626
|
let lastValidHourValue: string | number = "";
|
|
@@ -636,7 +629,7 @@ let lastValidSecondValue: string | number = "";
|
|
|
636
629
|
|
|
637
630
|
function onTimeKeydown(event: KeyboardEvent) {
|
|
638
631
|
if (ARROW_KEYS.includes(event.code)) {
|
|
639
|
-
wrapperRef.value
|
|
632
|
+
wrapperRef.value!.focus();
|
|
640
633
|
|
|
641
634
|
return;
|
|
642
635
|
}
|
|
@@ -822,6 +815,7 @@ const {
|
|
|
822
815
|
>
|
|
823
816
|
<div v-bind="navigationAttrs" :data-test="getDataTest('navigation')">
|
|
824
817
|
<UButton
|
|
818
|
+
v-if="isCurrentView.day"
|
|
825
819
|
square
|
|
826
820
|
size="sm"
|
|
827
821
|
color="grayscale"
|
|
@@ -871,6 +865,7 @@ const {
|
|
|
871
865
|
/>
|
|
872
866
|
|
|
873
867
|
<UButton
|
|
868
|
+
v-if="isCurrentView.day"
|
|
874
869
|
square
|
|
875
870
|
size="sm"
|
|
876
871
|
color="grayscale"
|
|
@@ -889,13 +884,13 @@ const {
|
|
|
889
884
|
:selected-date="selectedDate"
|
|
890
885
|
:selected-date-to="selectedDateTo"
|
|
891
886
|
:range="range"
|
|
892
|
-
:active-month="activeMonth"
|
|
893
887
|
:active-date="activeDate"
|
|
894
888
|
:min-date="minDate"
|
|
895
889
|
:max-date="maxDate"
|
|
896
890
|
:date-format="actualDateFormat"
|
|
897
891
|
:locale="locale"
|
|
898
892
|
:config="config"
|
|
893
|
+
:is-arrow-key-dirty="isArrowKeyDirty"
|
|
899
894
|
:data-test="getDataTest('day-view')"
|
|
900
895
|
@input="onInputDate"
|
|
901
896
|
/>
|
|
@@ -905,29 +900,30 @@ const {
|
|
|
905
900
|
:selected-date="selectedDate"
|
|
906
901
|
:selected-date-to="selectedDateTo"
|
|
907
902
|
:range="range"
|
|
908
|
-
:active-month="activeMonth"
|
|
909
903
|
:active-date="activeDate"
|
|
910
904
|
:min-date="minDate"
|
|
911
905
|
:max-date="maxDate"
|
|
912
906
|
:date-format="actualDateFormat"
|
|
913
907
|
:locale="locale"
|
|
914
908
|
:config="config"
|
|
909
|
+
:is-arrow-key-dirty="isArrowKeyDirty"
|
|
915
910
|
:data-test="getDataTest('month-view')"
|
|
916
911
|
@input="onInput"
|
|
917
912
|
/>
|
|
918
913
|
|
|
919
914
|
<YearView
|
|
920
915
|
v-if="isCurrentView.year"
|
|
916
|
+
ref="year-view"
|
|
921
917
|
:selected-date="selectedDate"
|
|
922
918
|
:selected-date-to="selectedDateTo"
|
|
923
919
|
:range="range"
|
|
924
|
-
:active-month="activeMonth"
|
|
925
920
|
:active-date="activeDate"
|
|
926
921
|
:min-date="minDate"
|
|
927
922
|
:max-date="maxDate"
|
|
928
923
|
:date-format="actualDateFormat"
|
|
929
924
|
:locale="locale"
|
|
930
925
|
:config="config"
|
|
926
|
+
:is-arrow-key-dirty="isArrowKeyDirty"
|
|
931
927
|
:data-test="getDataTest('year-view')"
|
|
932
928
|
@input="onInput"
|
|
933
929
|
/>
|
|
@@ -34,12 +34,8 @@ const localSelectedDate = computed(() => {
|
|
|
34
34
|
return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
const activeMonthDate = computed(() => {
|
|
38
|
-
return props.activeMonth || localSelectedDate.value;
|
|
39
|
-
});
|
|
40
|
-
|
|
41
37
|
const firstDayOfMonth = computed(() => {
|
|
42
|
-
const date = new Date(
|
|
38
|
+
const date = new Date(props.activeDate.valueOf());
|
|
43
39
|
|
|
44
40
|
date.setDate(1);
|
|
45
41
|
|
|
@@ -47,17 +43,17 @@ const firstDayOfMonth = computed(() => {
|
|
|
47
43
|
});
|
|
48
44
|
|
|
49
45
|
const lastDayOfMonth = computed(() => {
|
|
50
|
-
return getLastDayOfMonth(
|
|
46
|
+
return getLastDayOfMonth(props.activeDate);
|
|
51
47
|
});
|
|
52
48
|
|
|
53
49
|
const firstDayOfPrevMonth = computed(() => {
|
|
54
|
-
const prevMonth =
|
|
50
|
+
const prevMonth = props.activeDate.getMonth() - 1;
|
|
55
51
|
|
|
56
|
-
return new Date(
|
|
52
|
+
return new Date(props.activeDate.getFullYear(), prevMonth, 1);
|
|
57
53
|
});
|
|
58
54
|
|
|
59
55
|
const lastDayOfPrevMonth = computed(() => {
|
|
60
|
-
const date = new Date(
|
|
56
|
+
const date = new Date(props.activeDate.valueOf());
|
|
61
57
|
|
|
62
58
|
date.setDate(0);
|
|
63
59
|
|
|
@@ -65,8 +61,8 @@ const lastDayOfPrevMonth = computed(() => {
|
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
const firstDayOfNextMonth = computed(() => {
|
|
68
|
-
const date = new Date(
|
|
69
|
-
const nextMonth =
|
|
64
|
+
const date = new Date(props.activeDate.valueOf());
|
|
65
|
+
const nextMonth = props.activeDate.getMonth() + 1;
|
|
70
66
|
|
|
71
67
|
date.setDate(1);
|
|
72
68
|
date.setMonth(nextMonth);
|
|
@@ -78,7 +74,7 @@ const monthDays = computed(() => {
|
|
|
78
74
|
const dayNumber = lastDayOfMonth.value.getDate();
|
|
79
75
|
|
|
80
76
|
return Array.from({ length: dayNumber }, (_, index) => dayNumber - index)
|
|
81
|
-
.map((day) => getDay(
|
|
77
|
+
.map((day) => getDay(props.activeDate, day))
|
|
82
78
|
.reverse();
|
|
83
79
|
});
|
|
84
80
|
|
|
@@ -152,7 +148,7 @@ function getDayState(day: Date) {
|
|
|
152
148
|
|
|
153
149
|
const isSelectedDay = isSameDay(day, localSelectedDate.value) && props.selectedDate !== null;
|
|
154
150
|
const isCurrentDay = isToday(day);
|
|
155
|
-
const isAnotherMonthDay = isAnotherMothDay(day,
|
|
151
|
+
const isAnotherMonthDay = isAnotherMothDay(day, props.activeDate);
|
|
156
152
|
const isAnotherMonthDayInRange = isAnotherMonthDay && isDayInRange;
|
|
157
153
|
const isFirstDayInRange = props.selectedDate && props.range && isSameDay(day, props.selectedDate);
|
|
158
154
|
const isRangeSameDay =
|
|
@@ -164,7 +160,7 @@ function getDayState(day: Date) {
|
|
|
164
160
|
props.selectedDateTo && props.range && isSameDay(day, props.selectedDateTo);
|
|
165
161
|
const isAnotherMonthFirstDayInRange = isFirstDayInRange && isAnotherMonthDay;
|
|
166
162
|
const isAnotherMonthLastDayInRange = isLastDayInRange && isAnotherMonthDay;
|
|
167
|
-
const isActiveDay = props.
|
|
163
|
+
const isActiveDay = props.isArrowKeyDirty && isSameDay(props.activeDate, day) && !props.range;
|
|
168
164
|
const isInRangePreview =
|
|
169
165
|
props.range &&
|
|
170
166
|
props.selectedDate &&
|
|
@@ -4,7 +4,7 @@ import { computed } from "vue";
|
|
|
4
4
|
import useUI from "../composables/useUI.ts";
|
|
5
5
|
|
|
6
6
|
import { formatDate, dateIsOutOfRange } from "./utilCalendar.ts";
|
|
7
|
-
import { isSameMonth,
|
|
7
|
+
import { isSameMonth, isCurrentMonth } from "./utilDate.ts";
|
|
8
8
|
|
|
9
9
|
import defaultConfig from "./config.ts";
|
|
10
10
|
import { MONTHS_PER_VIEW } from "./constants.ts";
|
|
@@ -19,26 +19,18 @@ const props = defineProps<UCalendarViewProps>();
|
|
|
19
19
|
|
|
20
20
|
const emit = defineEmits(["input"]);
|
|
21
21
|
|
|
22
|
-
const localSelectedDate = computed(() => {
|
|
23
|
-
return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const localActiveMonth = computed(
|
|
27
|
-
() => props.activeMonth || props.activeDate || localSelectedDate.value,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
22
|
const months = computed(() =>
|
|
31
23
|
Array.from({ length: MONTHS_PER_VIEW }, (_, i) => i).map((monthNumber) => getMonth(monthNumber)),
|
|
32
24
|
);
|
|
33
25
|
|
|
34
26
|
function getMonth(monthNumber: number) {
|
|
35
|
-
let newDate = new Date(
|
|
27
|
+
let newDate = new Date(props.activeDate.valueOf());
|
|
36
28
|
|
|
37
29
|
newDate.setMonth(monthNumber);
|
|
38
30
|
|
|
39
31
|
// Means the current day has less days so the extra month is
|
|
40
32
|
// in the following month
|
|
41
|
-
if (newDate.getDate() !==
|
|
33
|
+
if (newDate.getDate() !== props.activeDate.getDate()) {
|
|
42
34
|
// Assign the last day of previous month
|
|
43
35
|
newDate = new Date(newDate.getFullYear(), newDate.getMonth(), 0);
|
|
44
36
|
}
|
|
@@ -47,8 +39,7 @@ function getMonth(monthNumber: number) {
|
|
|
47
39
|
}
|
|
48
40
|
|
|
49
41
|
function getMonthState(month: Date) {
|
|
50
|
-
const isSelectedMonth =
|
|
51
|
-
isSameMonth(month, localSelectedDate.value) && props.selectedDate !== null;
|
|
42
|
+
const isSelectedMonth = props.selectedDate && isSameMonth(month, props.selectedDate);
|
|
52
43
|
const isPresentMonth = isCurrentMonth(month);
|
|
53
44
|
const isMoreThanOneMonthRange =
|
|
54
45
|
props.range &&
|
|
@@ -57,8 +48,8 @@ function getMonthState(month: Date) {
|
|
|
57
48
|
isMoreThanOneMonthDiff(props.selectedDate, props.selectedDateTo);
|
|
58
49
|
|
|
59
50
|
const isActiveMonth =
|
|
60
|
-
props.
|
|
61
|
-
isSameMonth(props.
|
|
51
|
+
props.isArrowKeyDirty &&
|
|
52
|
+
isSameMonth(props.activeDate, month) &&
|
|
62
53
|
!props.range &&
|
|
63
54
|
!dateIsOutOfRange(month, props.minDate, props.maxDate, props.locale, props.dateFormat);
|
|
64
55
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { ref, watch } from "vue";
|
|
3
3
|
|
|
4
4
|
import useUI from "../composables/useUI.ts";
|
|
5
5
|
|
|
6
|
-
import { formatDate,
|
|
7
|
-
import { isSameMonth,
|
|
6
|
+
import { formatDate, dateIsOutOfRange } from "./utilCalendar.ts";
|
|
7
|
+
import { isSameMonth, isCurrentYear } from "./utilDate.ts";
|
|
8
8
|
|
|
9
9
|
import defaultConfig from "./config.ts";
|
|
10
10
|
import { YEARS_PER_VIEW } from "./constants.ts";
|
|
@@ -19,32 +19,10 @@ const props = defineProps<UCalendarViewProps>();
|
|
|
19
19
|
|
|
20
20
|
const emit = defineEmits(["input"]);
|
|
21
21
|
|
|
22
|
-
const isFirstRender = ref(true);
|
|
23
22
|
const years = ref<Date[]>([]);
|
|
24
23
|
|
|
25
|
-
const localSelectedDate = computed(() => {
|
|
26
|
-
return props.selectedDate === null ? getDateWithoutTime() : props.selectedDate;
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const localActiveMonth = computed(
|
|
30
|
-
() => props.activeMonth || props.activeDate || localSelectedDate.value,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
// Initialize years on component creation
|
|
34
|
-
updateYears();
|
|
35
|
-
|
|
36
24
|
// Watch for changes to active month and update years when needed
|
|
37
|
-
watch(
|
|
38
|
-
localActiveMonth,
|
|
39
|
-
() => {
|
|
40
|
-
if (isFirstRender.value) {
|
|
41
|
-
isFirstRender.value = false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
updateYears();
|
|
45
|
-
},
|
|
46
|
-
{ deep: true },
|
|
47
|
-
);
|
|
25
|
+
watch(() => props.activeDate, updateYears, { deep: true, immediate: true });
|
|
48
26
|
|
|
49
27
|
// Update years array based on active date;
|
|
50
28
|
function updateYears() {
|
|
@@ -58,11 +36,11 @@ function updateYears() {
|
|
|
58
36
|
}
|
|
59
37
|
|
|
60
38
|
function isActiveDateWithinCurrentRange(): boolean {
|
|
61
|
-
if (
|
|
39
|
+
if (!years.value.length) {
|
|
62
40
|
return false;
|
|
63
41
|
}
|
|
64
42
|
|
|
65
|
-
const activeYear =
|
|
43
|
+
const activeYear = props.activeDate.getFullYear();
|
|
66
44
|
const firstYear = years.value.at(0)!.getFullYear();
|
|
67
45
|
const lastYear = years.value.at(-1)!.getFullYear();
|
|
68
46
|
|
|
@@ -70,35 +48,25 @@ function isActiveDateWithinCurrentRange(): boolean {
|
|
|
70
48
|
}
|
|
71
49
|
|
|
72
50
|
function calculateInitialYear() {
|
|
73
|
-
const activeYear =
|
|
51
|
+
const activeYear = props.activeDate.getFullYear();
|
|
74
52
|
|
|
75
53
|
// First render - position selected date as the 5th element
|
|
76
|
-
if (
|
|
54
|
+
if (!years.value.length) {
|
|
77
55
|
const selectedYear = props.selectedDate?.getFullYear() || activeYear;
|
|
78
56
|
|
|
79
57
|
return selectedYear - 4;
|
|
80
58
|
}
|
|
81
59
|
|
|
82
60
|
// If we have existing years, check if we need to adjust the range
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const lastYear = years.value.at(1)!.getFullYear();
|
|
86
|
-
|
|
87
|
-
// Active year before range - position at end
|
|
88
|
-
if (activeYear < firstYear) {
|
|
89
|
-
return activeYear - (YEARS_PER_VIEW - 1);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Active year after range - position at beginning
|
|
93
|
-
if (activeYear > lastYear) {
|
|
94
|
-
return activeYear;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Default calculation for initial render or when range is empty
|
|
99
|
-
const [standardInitialYear] = getYearsRange(localActiveMonth.value);
|
|
61
|
+
const firstYear = years.value.at(0)!.getFullYear();
|
|
62
|
+
const lastYear = years.value.at(-1)!.getFullYear();
|
|
100
63
|
|
|
101
|
-
|
|
64
|
+
// Active year before range - position at end
|
|
65
|
+
if (activeYear < firstYear) {
|
|
66
|
+
return firstYear - YEARS_PER_VIEW;
|
|
67
|
+
} else {
|
|
68
|
+
return lastYear + 1;
|
|
69
|
+
}
|
|
102
70
|
}
|
|
103
71
|
|
|
104
72
|
function getYears(initialYear: number): Date[] {
|
|
@@ -106,13 +74,13 @@ function getYears(initialYear: number): Date[] {
|
|
|
106
74
|
}
|
|
107
75
|
|
|
108
76
|
function getYear(year: number) {
|
|
109
|
-
let newDate = new Date(
|
|
77
|
+
let newDate = new Date(props.activeDate.valueOf());
|
|
110
78
|
|
|
111
79
|
newDate.setFullYear(year);
|
|
112
80
|
|
|
113
81
|
// Means the current day has less days so the extra month is
|
|
114
82
|
// in the following month
|
|
115
|
-
if (newDate.getDate() !==
|
|
83
|
+
if (newDate.getDate() !== props.activeDate.getDate()) {
|
|
116
84
|
// Assign the last day of previous month
|
|
117
85
|
newDate = new Date(newDate.getFullYear(), newDate.getMonth(), 0);
|
|
118
86
|
}
|
|
@@ -121,7 +89,7 @@ function getYear(year: number) {
|
|
|
121
89
|
}
|
|
122
90
|
|
|
123
91
|
function getYearState(year: Date) {
|
|
124
|
-
const isSelectedYear = isSameMonth(year,
|
|
92
|
+
const isSelectedYear = props.selectedDate && isSameMonth(year, props.selectedDate);
|
|
125
93
|
const isPresentYear = isCurrentYear(year);
|
|
126
94
|
const isMoreThanOneYearRange =
|
|
127
95
|
props.selectedDateTo &&
|
|
@@ -129,8 +97,8 @@ function getYearState(year: Date) {
|
|
|
129
97
|
props.selectedDateTo.getFullYear() - props.selectedDate.getFullYear() >= 1;
|
|
130
98
|
|
|
131
99
|
const isActiveYear =
|
|
132
|
-
props.
|
|
133
|
-
isSameMonth(props.
|
|
100
|
+
props.isArrowKeyDirty &&
|
|
101
|
+
isSameMonth(props.activeDate, year) &&
|
|
134
102
|
!props.range &&
|
|
135
103
|
!dateIsOutOfRange(year, props.minDate, props.maxDate, props.locale, props.dateFormat);
|
|
136
104
|
|
|
@@ -152,6 +120,14 @@ function onClickYear(year: Date) {
|
|
|
152
120
|
*/
|
|
153
121
|
const { yearViewAttrs, yearAttrs, currentYearAttrs, selectedYearAttrs, activeYearAttrs } =
|
|
154
122
|
useUI<Config>(defaultConfig);
|
|
123
|
+
|
|
124
|
+
defineExpose({
|
|
125
|
+
/**
|
|
126
|
+
* List of years to display in the calendar view.
|
|
127
|
+
* @property {Date[]}
|
|
128
|
+
*/
|
|
129
|
+
years,
|
|
130
|
+
});
|
|
155
131
|
</script>
|
|
156
132
|
|
|
157
133
|
<template>
|
|
@@ -86,11 +86,11 @@ export interface Props<TModelValue extends DateValue> {
|
|
|
86
86
|
export interface UCalendarViewProps {
|
|
87
87
|
selectedDate: Date | null;
|
|
88
88
|
selectedDateTo: Date | null;
|
|
89
|
-
activeDate: Date
|
|
90
|
-
activeMonth: Date | null;
|
|
89
|
+
activeDate: Date;
|
|
91
90
|
locale: DateLocale;
|
|
92
91
|
dateFormat?: string;
|
|
93
92
|
range: boolean;
|
|
93
|
+
isArrowKeyDirty: boolean;
|
|
94
94
|
maxDate?: Date | string;
|
|
95
95
|
minDate?: Date | string;
|
|
96
96
|
config: Config;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { revFormat, formats } from "./utilFormatting.ts";
|
|
2
2
|
import { getDateFromUnixTimestamp } from "./utilDate.ts";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { SEPARATOR, TOKEN_REG_EXP } from "./constants.ts";
|
|
5
5
|
|
|
6
6
|
import type { DateLocale } from "./utilFormatting.ts";
|
|
7
7
|
|
|
@@ -182,10 +182,6 @@ export function dateIsOutOfRange<TLocale extends DateLocale>(
|
|
|
182
182
|
return false;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
export function
|
|
186
|
-
|
|
187
|
-
const from = currentYear - Math.floor(currentYear % YEARS_PER_VIEW);
|
|
188
|
-
const to = from + YEARS_PER_VIEW - 1;
|
|
189
|
-
|
|
190
|
-
return [from, to];
|
|
185
|
+
export function getYearsRangeLabel(years: Date[]) {
|
|
186
|
+
return `${years.at(0)?.getFullYear()} ${SEPARATOR} ${years.at(-1)?.getFullYear()}`;
|
|
191
187
|
}
|