feat: add available range prop to SingleDatePicker for date selection constraints

This commit is contained in:
Astrian Zheng 2025-02-24 14:32:26 +11:00
parent bd4dd671ef
commit 13a55d7eda
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
2 changed files with 54 additions and 4 deletions

View File

@ -8,7 +8,7 @@ const date = ref(new Date())
<template>
<div>{{date.toDateString()}}</div>
<div class="container">
<SingleDatePicker v-model="date" localization="zh-CN" @close="() => {}" />
<SingleDatePicker :available-range="[new Date(2025, 0, 1), null]" v-model="date" />
</div>
</template>

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, defineProps, watch, onMounted, toRefs, getCurrentInstance } from 'vue'
import { ref, defineProps, watch, onMounted, toRefs, getCurrentInstance, PropType } from 'vue'
import { generateUniqueId, applyColor, getL10Weekday, getCalendarDates } from '../utils'
interface SingleDatePickerPropsColorScheme {
@ -10,6 +10,8 @@
reversedColor: string
}
type SingleDatePickerPropsAvailableDates = [Date | null, Date | null]
const props = defineProps({
colorScheme: {
type: Object as () => SingleDatePickerPropsColorScheme,
@ -29,6 +31,10 @@
modelValue: {
type: Date,
required: false,
},
availableRange: {
type: Array as unknown as PropType<SingleDatePickerPropsAvailableDates>,
required: false,
}
})
@ -40,6 +46,8 @@
const l10nDays = ref<string[]>([])
const dates = ref<Date[]>([])
const hasCloseListener = getCurrentInstance()?.vnode?.props?.onClose !== undefined
const availableRangeStart = ref<Date | null>(null)
const availableRangeEnd = ref<Date | null>(null)
const { colorScheme, localization } = toRefs(props)
@ -51,6 +59,10 @@
dates.value = getCalendarDates(currentMonth.value, currentYear.value)
})
watch([props.availableRange], () => {
calculateAvailableRange()
})
onMounted(() => {
applyColor(uniqueId, colorScheme.value)
l10nDays.value = getL10Weekday(localization?.value || navigator.languages[0])
@ -63,6 +75,8 @@
currentYear.value = new Date().getFullYear()
}
dates.value = getCalendarDates(currentMonth.value, currentYear.value)
calculateAvailableRange()
})
function goToLastMonth() {
@ -83,8 +97,8 @@
}
}
function notAvailable(date: Date) {
return currentMonth.value !== date.getMonth() //TODO: available date ranges
function notAvailable(date: Date): boolean {
return currentMonth.value !== date.getMonth() || (availableRangeStart.value !== null && date < availableRangeStart.value) || (availableRangeEnd.value !== null && date > availableRangeEnd.value)
}
function selectDate(date: Date) {
@ -109,6 +123,42 @@
emit('close')
}
function calculateAvailableRange() {
if (!props.availableRange) {
availableRangeStart.value = null
availableRangeEnd.value = null
return
}
if (props.availableRange.length !== 2) {
console.warn('Invalid availableRange: The length of the array should be 2. The parameter will be ignored.')
availableRangeStart.value = null
availableRangeEnd.value = null
return
}
const [start, end] = props.availableRange
if (start && end) {
if (start > end) {
availableRangeStart.value = end
availableRangeEnd.value = start
} else {
availableRangeStart.value = start
availableRangeEnd.value = end
}
} else if (start && !end) {
availableRangeStart.value = start
availableRangeEnd.value = null
} else if (!start && end) {
availableRangeStart.value = null
availableRangeEnd.value = end
} else {
availableRangeStart.value = null
availableRangeEnd.value = null
}
}
</script>
<template>