Skip to content

Commit 3c32eff

Browse files
author
stinger567
committed
added toValidDate to both DateInput and DatePicker
1 parent 8365dea commit 3c32eff

File tree

3 files changed

+59
-50
lines changed

3 files changed

+59
-50
lines changed

src/lib/DateInput.svelte

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import { fly } from 'svelte/transition'
33
import { cubicInOut } from 'svelte/easing'
4-
import { toText } from './date-utils.js'
4+
import { toText, cloneDate, toValidDate } from './date-utils.js'
55
import type { Locale } from './locale.js'
66
import { parse, createFormat, type FormatToken } from './parse.js'
77
import DateTimePicker from './DatePicker.svelte'
@@ -16,10 +16,6 @@
1616
/** Default date to display in picker before value is assigned */
1717
const defaultDate = new Date()
1818
19-
function cloneDate(d: Date) {
20-
return new Date(d.getTime())
21-
}
22-
2319
// inner date value store for preventing value updates (and also
2420
// text updates as a result) when date is unchanged
2521
const innerStore = writable(null as Date | null)
@@ -40,7 +36,7 @@
4036
4137
/** Date value */
4238
export let value: Date | null = null
43-
$: store.set(value)
39+
$: store.set(value ? toValidDate(defaultDate, value, min, max, isDisabledDate) : value)
4440
4541
/** The earliest value the user can select */
4642
export let min = new Date(defaultDate.getFullYear() - 20, 0, 1)

src/lib/DatePicker.svelte

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,19 @@
88
} from './date-utils.js'
99
import { getInnerLocale, type Locale } from './locale.js'
1010
import { createEventDispatcher } from 'svelte'
11+
import { cloneDate, toValidDate } from './date-utils.js'
1112
1213
const dispatch = createEventDispatcher<{
1314
/** Fires when the user selects a new value by clicking on a date or by pressing enter */
1415
select: Date
1516
}>()
1617
17-
function cloneDate(d: Date) {
18-
return new Date(d)
19-
}
20-
2118
/** Date value. It's `null` if no date is selected */
2219
export let value: Date | null = null
2320
2421
function setValue(d: Date) {
2522
if (d.getTime() !== value?.getTime()) {
26-
browseDate = toValidDate(value ?? browseDate, d)
23+
browseDate = toValidDate(value ?? browseDate, d, min, max, isDisabledDate)
2724
applyTimePrecision(browseDate, timePrecision)
2825
value = cloneDate(browseDate)
2926
}
@@ -63,49 +60,13 @@
6360
return isDisabledDate?.(new Date(date.year, date.month, date.number))
6461
}
6562
66-
function toValidDate(oldDate: Date, newDate: Date): Date {
67-
// Don't mutate the original newDate to avoid unintended side effects
68-
let adjustedDate = cloneDate(newDate)
69-
70-
if (oldDate > newDate) {
71-
adjustDate(adjustedDate, -1)
72-
if (adjustedDate < min) {
73-
adjustedDate = cloneDate(min)
74-
// Adjusts the date one more time if the min date is disabled, to ensure a valid, enabled date is selected
75-
adjustDate(adjustedDate, 1)
76-
}
77-
return adjustedDate
78-
}
79-
if (adjustedDate > oldDate) {
80-
adjustDate(adjustedDate, 1)
81-
if (adjustedDate > max) {
82-
adjustedDate = cloneDate(max)
83-
// Adjusts the date one more time if the max date is disabled, to ensure a valid, enabled date is selected
84-
adjustDate(adjustedDate, -1)
85-
}
86-
return adjustedDate
87-
}
88-
return adjustedDate
89-
}
90-
91-
function adjustDate(date: Date, increment: number) {
92-
// Prevents accidental infinite loops
93-
const MAXLOOPS = 36525 // ~100 years, should be large enough
94-
let loopCount = 0
95-
96-
while (isDisabledDate?.(date) && date >= min && date <= max && loopCount <= MAXLOOPS) {
97-
date.setDate(date.getDate() + increment)
98-
loopCount++
99-
}
100-
}
101-
10263
// Prevents a invalid date from being typed into the Dateinput text box
10364
$: if (value && value > max) {
104-
setValue(toValidDate(value, max))
65+
setValue(toValidDate(value, max, min, max, isDisabledDate))
10566
} else if (value && value < min) {
106-
setValue(toValidDate(value, min))
67+
setValue(toValidDate(value, min, min, max, isDisabledDate))
10768
} else if (value && isDisabledDate?.(value)) {
108-
setValue(toValidDate(browseDate, value))
69+
setValue(toValidDate(browseDate, value, min, max, isDisabledDate))
10970
}
11071
function clamp(d: Date, min: Date, max: Date) {
11172
if (d > max) {

src/lib/date-utils.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,55 @@ export function applyTimePrecision(
9696
date.setMilliseconds(0)
9797
}
9898
}
99+
100+
export function cloneDate(d: Date) {
101+
return new Date(d)
102+
}
103+
104+
export function toValidDate(
105+
oldDate: Date,
106+
newDate: Date,
107+
minDate: Date,
108+
maxDate: Date,
109+
isDisabledDate: ((date: Date) => boolean) | null,
110+
): Date {
111+
// Don't mutate the original newDate to avoid unintended side effects
112+
let adjustedDate = cloneDate(newDate)
113+
114+
if (oldDate > newDate) {
115+
adjustDate(adjustedDate, -1, minDate, maxDate, isDisabledDate)
116+
if (adjustedDate < minDate) {
117+
adjustedDate = cloneDate(minDate)
118+
// Adjusts the date one more time if the min date is disabled, to ensure a valid, enabled date is selected
119+
adjustDate(adjustedDate, 1, minDate, maxDate, isDisabledDate)
120+
}
121+
return adjustedDate
122+
}
123+
if (adjustedDate >= oldDate) {
124+
adjustDate(adjustedDate, 1, minDate, maxDate, isDisabledDate)
125+
if (adjustedDate > maxDate) {
126+
adjustedDate = cloneDate(maxDate)
127+
// Adjusts the date one more time if the max date is disabled, to ensure a valid, enabled date is selected
128+
adjustDate(adjustedDate, -1, minDate, maxDate, isDisabledDate)
129+
}
130+
return adjustedDate
131+
}
132+
return adjustedDate
133+
}
134+
135+
function adjustDate(
136+
date: Date,
137+
increment: number,
138+
minDate: Date,
139+
maxDate: Date,
140+
isDisabledDate: ((date: Date) => boolean) | null,
141+
) {
142+
// Prevents accidental infinite loops
143+
const MAXLOOPS = 36525 // ~100 years, should be large enough
144+
let loopCount = 0
145+
146+
while (isDisabledDate?.(date) && date >= minDate && date <= maxDate && loopCount <= MAXLOOPS) {
147+
date.setDate(date.getDate() + increment)
148+
loopCount++
149+
}
150+
}

0 commit comments

Comments
 (0)