File: //home/arjun/projects/buyercall/node_modules/vue3-datepicker/src/datepicker/DayPicker.vue
<template>
<picker-popup
headingClickable
:leftDisabled="leftDisabled"
:rightDisabled="rightDisabled"
:items="days"
viewMode="day"
@left="previousPage"
@right="nextPage"
@heading="$emit('back')"
@elementClick="$emit('select', $event)"
>
<template #heading>{{ heading }}</template>
<template #subheading>
<span
v-for="(day, index) in weekDays"
:key="day"
:class="`v3dp__subheading__weekday__${index}`"
>
{{ day }}
</span>
</template>
</picker-popup>
</template>
<script lang="ts">
import { defineComponent, computed, ref, watchEffect, PropType } from 'vue'
import {
startOfMonth,
endOfMonth,
eachDayOfInterval,
subMonths,
addMonths,
startOfWeek,
endOfWeek,
isSameDay,
setDay,
isWithinInterval,
isBefore,
isAfter,
isSameMonth,
endOfDay,
startOfDay,
isValid,
format as formatDate,
} from 'date-fns'
import PickerPopup, { Item } from './PickerPopup.vue'
export default defineComponent({
components: {
PickerPopup,
},
emits: {
'update:pageDate': (date: Date) => isValid(date),
select: (date: Date) => isValid(date),
back: () => true,
},
props: {
selected: {
type: Date as PropType<Date>,
required: false,
},
pageDate: {
type: Date as PropType<Date>,
required: true,
},
format: {
type: String,
required: false,
default: 'dd',
},
headingFormat: {
type: String,
required: false,
default: 'LLLL yyyy',
},
weekdayFormat: {
type: String,
required: false,
default: 'EE',
},
locale: {
type: Object as PropType<Locale>,
required: false,
},
weekStartsOn: {
type: Number as PropType<1 | 2 | 3 | 4 | 5 | 6 | 0>,
required: false,
default: 1,
validator: (i: unknown): boolean =>
typeof i === 'number' && Number.isInteger(i) && i >= 0 && i <= 6,
},
lowerLimit: {
type: Date as PropType<Date>,
required: false,
},
upperLimit: {
type: Date as PropType<Date>,
required: false,
},
disabledDates: {
type: Object as PropType<{
dates?: Date[]
predicate?: (target: Date) => boolean
}>,
required: false,
},
allowOutsideInterval: {
type: Boolean,
required: false,
default: false,
},
},
setup(props, { emit }) {
const format = computed(
() => (format: string) => (value: Date | number) =>
formatDate(value, format, {
locale: props.locale,
weekStartsOn: props.weekStartsOn,
})
)
const monthStart = computed(() => startOfMonth(props.pageDate))
const monthEnd = computed(() => endOfMonth(props.pageDate))
const currentMonth = computed(() => ({
start: monthStart.value,
end: monthEnd.value,
}))
const displayedInterval = computed(() => ({
start: startOfWeek(monthStart.value, {
weekStartsOn: props.weekStartsOn,
}),
end: endOfWeek(monthEnd.value, {
weekStartsOn: props.weekStartsOn,
}),
}))
const weekDays = computed(() => {
const initial = props.weekStartsOn
const dayFormat = format.value(props.weekdayFormat)
return Array.from(Array(7))
.map((_, i) => (initial + i) % 7)
.map((v) =>
setDay(new Date(), v, {
weekStartsOn: props.weekStartsOn,
})
)
.map(dayFormat)
})
const isEnabled = (
target: Date,
lower?: Date,
upper?: Date,
disabledDates?: { dates?: Date[]; predicate?: (target: Date) => boolean }
): boolean => {
if (disabledDates?.dates?.some((date) => isSameDay(target, date)))
return false
if (disabledDates?.predicate?.(target)) return false
if (!lower && !upper) return true
if (lower && isBefore(target, startOfDay(lower))) return false
if (upper && isAfter(target, endOfDay(upper))) return false
return true
}
const days = computed(() => {
const today = new Date()
const dayFormat = format.value(props.format)
return eachDayOfInterval(displayedInterval.value).map(
(value): Item => ({
value,
display: dayFormat(value),
selected: !!props.selected && isSameDay(props.selected, value),
current: isSameDay(today, value),
disabled:
(!props.allowOutsideInterval &&
!isWithinInterval(value, currentMonth.value)) ||
!isEnabled(
value,
props.lowerLimit,
props.upperLimit,
props.disabledDates
),
key: format.value('yyyy-MM-dd')(value),
})
)
})
const heading = computed(() =>
format.value(props.headingFormat)(props.pageDate)
)
const leftDisabled = computed(
() =>
props.lowerLimit &&
(isSameMonth(props.lowerLimit, props.pageDate) ||
isBefore(props.pageDate, props.lowerLimit))
)
const rightDisabled = computed(
() =>
props.upperLimit &&
(isSameMonth(props.upperLimit, props.pageDate) ||
isAfter(props.pageDate, props.upperLimit))
)
const previousPage = () =>
emit('update:pageDate', subMonths(props.pageDate, 1))
const nextPage = () => emit('update:pageDate', addMonths(props.pageDate, 1))
return {
weekDays,
days,
heading,
leftDisabled,
rightDisabled,
previousPage,
nextPage,
}
},
})
</script>
<style></style>