|
7 | 7 |
|
8 | 8 | const dispatch = createEventDispatcher<{ select: undefined }>() |
9 | 9 |
|
10 | | - /** Date value */ |
11 | | - export let value = new Date() |
| 10 | + /** Date value. It's `null` if no date is selected */ |
| 11 | + export let value: Date | null = null |
12 | 12 | function setValue(d: Date) { |
13 | | - if (d.getTime() !== value.getTime()) value = d |
| 13 | + if (d.getTime() !== value?.getTime()) { |
| 14 | + value = d |
| 15 | + } |
14 | 16 | } |
15 | 17 | function updateValue(updater: (date: Date) => Date) { |
16 | | - let d = updater(new Date(value.getTime())) |
17 | | - setValue(d) |
| 18 | + const newValue = updater(new Date(shownDate.getTime())) |
| 19 | + setValue(newValue) |
18 | 20 | } |
| 21 | +
|
| 22 | + /** Default Date to use */ |
| 23 | + const defaultDate = new Date() |
| 24 | +
|
| 25 | + /** The date shown in the popup, for when `value` is null */ |
| 26 | + let shownDate = value ?? defaultDate |
| 27 | + $: if (value) shownDate = value |
| 28 | +
|
| 29 | + /** Update the shownDate. The date is only selected if a date is already selected */ |
| 30 | + function updateShownDate(updater: (date: Date) => Date) { |
| 31 | + shownDate = updater(new Date(shownDate.getTime())) |
| 32 | + if (value && shownDate.getTime() !== value.getTime()) { |
| 33 | + setValue(shownDate) |
| 34 | + } |
| 35 | + } |
| 36 | +
|
19 | 37 | /** The earliest year the user can select */ |
20 | | - export let min = new Date(new Date().getFullYear() - 20, 0, 1) |
| 38 | + export let min = new Date(defaultDate.getFullYear() - 20, 0, 1) |
21 | 39 | /** The latest year the user can select */ |
22 | | - export let max = new Date(new Date().getFullYear(), 11, 31, 23, 59, 59, 999) |
| 40 | + export let max = new Date(defaultDate.getFullYear(), 11, 31, 23, 59, 59, 999) |
23 | 41 | let years = getYears(min, max) |
24 | 42 | $: years = getYears(min, max) |
25 | 43 | function getYears(min: Date, max: Date) { |
|
29 | 47 | } |
30 | 48 | return years |
31 | 49 | } |
32 | | - $: if (value > max) { |
33 | | - setValue(max) |
34 | | - } else if (value < min) { |
35 | | - setValue(min) |
| 50 | +
|
| 51 | + $: if (shownDate > max) { |
| 52 | + updateShownDate(() => max) |
| 53 | + } else if (shownDate < min) { |
| 54 | + updateShownDate(() => min) |
36 | 55 | } |
37 | 56 |
|
38 | 57 | /** Locale object for internationalization */ |
39 | 58 | export let locale: Locale = {} |
40 | 59 | $: iLocale = getInnerLocale(locale) |
41 | 60 |
|
42 | | - let year = value.getFullYear() |
43 | | - const getYear = (value: Date) => (year = value.getFullYear()) |
| 61 | + let year = shownDate.getFullYear() |
| 62 | + const getYear = (tmpPickerDate: Date) => (year = tmpPickerDate.getFullYear()) |
44 | 63 | function setYear(year: number) { |
45 | | - updateValue((value) => { |
46 | | - value.setFullYear(year) |
47 | | - return value |
| 64 | + updateShownDate((tmpPickerDate) => { |
| 65 | + tmpPickerDate.setFullYear(year) |
| 66 | + return tmpPickerDate |
48 | 67 | }) |
49 | 68 | } |
50 | | - $: getYear(value) |
| 69 | + $: getYear(shownDate) |
51 | 70 | $: setYear(year) |
52 | 71 |
|
53 | | - let month = value.getMonth() |
54 | | - const getMonth = (value: Date) => (month = value.getMonth()) |
| 72 | + let month = shownDate.getMonth() |
| 73 | + const getMonth = (tmpPickerDate: Date) => (month = tmpPickerDate.getMonth()) |
55 | 74 | function setMonth(month: number) { |
56 | 75 | let newYear = year |
57 | 76 | let newMonth = month |
|
64 | 83 | } |
65 | 84 |
|
66 | 85 | const maxDate = getMonthLength(newYear, newMonth) |
67 | | - const newDate = Math.min(value.getDate(), maxDate) |
68 | | - setValue( |
69 | | - new Date( |
| 86 | + const newDate = Math.min(shownDate.getDate(), maxDate) |
| 87 | + updateShownDate((date) => { |
| 88 | + return new Date( |
70 | 89 | newYear, |
71 | 90 | newMonth, |
72 | 91 | newDate, |
73 | | - value.getHours(), |
74 | | - value.getMinutes(), |
75 | | - value.getSeconds(), |
76 | | - value.getMilliseconds() |
| 92 | + date.getHours(), |
| 93 | + date.getMinutes(), |
| 94 | + date.getSeconds(), |
| 95 | + date.getMilliseconds() |
77 | 96 | ) |
78 | | - ) |
| 97 | + }) |
79 | 98 | } |
80 | | - $: getMonth(value) |
| 99 | + $: getMonth(shownDate) |
81 | 100 | $: setMonth(month) |
82 | 101 |
|
83 | | - let dayOfMonth = value.getDate() |
84 | | - $: dayOfMonth = value.getDate() |
| 102 | + let dayOfMonth = value?.getDate() || null |
| 103 | + $: dayOfMonth = value?.getDate() || null |
85 | 104 |
|
86 | | - $: calendarDays = getCalendarDays(value, iLocale.weekStartsOn) |
| 105 | + $: calendarDays = getCalendarDays(shownDate, iLocale.weekStartsOn) |
87 | 106 |
|
88 | 107 | function setDay(calendarDay: CalendarDay) { |
89 | 108 | if (dayIsInRange(calendarDay, min, max)) { |
|
0 commit comments