Skip to content

Commit

Permalink
refactor(VCalendar): updates to core structure and header
Browse files Browse the repository at this point in the history
  • Loading branch information
johnleider committed Nov 27, 2023
1 parent 6f19114 commit c2b26ed
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 142 deletions.
192 changes: 98 additions & 94 deletions packages/vuetify/src/labs/VCalendar/VCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import './VCalendar.sass'

// Composables
import { useDate } from '@/composables/date'
import { getWeek } from '@/composables/date/date'
import { getWeek, useDate } from '@/composables/date/date'

// Utilities
import { computed } from 'vue'
Expand Down Expand Up @@ -66,7 +65,6 @@ export const VCalendar = genericComponent()({
prev: null,
'update:modelValue': null,
},
expose: ['prev', 'next'],

setup (props, { emit, slots }) {
const adapter = useDate()
Expand Down Expand Up @@ -109,7 +107,7 @@ export const VCalendar = genericComponent()({
return weeks
})

const prev = () => {
function onClickPrev () {
if (props.type === 'month') {
emit('update:modelValue', adapter.addMonths(props.modelValue, -1))
}
Expand All @@ -121,7 +119,7 @@ export const VCalendar = genericComponent()({
}
}

const next = () => {
function onClickNext () {
if (props.type === 'month') {
emit('update:modelValue', adapter.addMonths(props.modelValue, 1))
}
Expand All @@ -146,37 +144,39 @@ export const VCalendar = genericComponent()({
const startDate = computed(() => validDates.value[0])
const endDate = computed(() => validDates.value[1])

return days.filter((date: Date, index) => props.weekdays.includes(date.getDay())).map((date, index) => {
const isStart = startDate.value && adapter.isSameDay(date, startDate.value)
const isEnd = endDate.value && adapter.isSameDay(date, endDate.value)
const isAdjacent = !adapter.isSameMonth(date, props.modelValue)
const isSame = validDates.value.length === 2 && adapter.isSameDay(startDate.value, endDate.value)
return days
.filter((date: any) => props.weekdays.includes(date.getDay()))
.map((date, index) => {
const isStart = startDate.value && adapter.isSameDay(date, startDate.value)
const isEnd = endDate.value && adapter.isSameDay(date, endDate.value)
const isAdjacent = !adapter.isSameMonth(date, props.modelValue)
const isSame = validDates.value.length === 2 && adapter.isSameDay(startDate.value, endDate.value)

return {
date,
isoDate: adapter.toISO(date),
formatted: adapter.format(date, 'keyboardDate'),
year: adapter.getYear(date),
month: adapter.getMonth(date),
isWeekStart: index % 7 === 0,
isWeekEnd: index % 7 === 6,
isSelected: isStart || isEnd,
isStart,
isEnd,
isToday: adapter.isSameDay(date, today),
isAdjacent,
isHidden: isAdjacent && !props.showAdjacentMonths,
inRange: isRange &&
!isSame &&
(isStart || isEnd || (validDates.value.length === 2 && adapter.isWithinRange(date, validDates.value as [any, any]))),
// isHovered: props.hoverDate === date,
// inHover: hoverRange.value && isWithinRange(date, hoverRange.value),
isHovered: false,
inHover: false,
localized: adapter.format(date, 'dayOfMonth'),
events: props.events?.filter(event => adapter.isSameDay(event.start, date) || adapter.isSameDay(event.end, date)) ?? [],
}
})
return {
date,
isoDate: adapter.toISO(date),
formatted: adapter.format(date, 'keyboardDate'),
year: adapter.getYear(date),
month: adapter.getMonth(date),
isWeekStart: index % 7 === 0,
isWeekEnd: index % 7 === 6,
isSelected: isStart || isEnd,
isStart,
isEnd,
isToday: adapter.isSameDay(date, today),
isAdjacent,
isHidden: isAdjacent && !props.showAdjacentMonths,
inRange: isRange &&
!isSame &&
(isStart || isEnd || (validDates.value.length === 2 && adapter.isWithinRange(date, validDates.value as [any, any]))),
// isHovered: props.hoverDate === date,
// inHover: hoverRange.value && isWithinRange(date, hoverRange.value),
isHovered: false,
inHover: false,
localized: adapter.format(date, 'dayOfMonth'),
events: props.events?.filter(event => adapter.isSameDay(event.start, date) || adapter.isSameDay(event.end, date)) ?? [],
}
})
})

const weeks = computed(() => {
Expand All @@ -185,6 +185,10 @@ export const VCalendar = genericComponent()({
})
})

const title = computed(() => {
return adapter.format(props.modelValue, 'monthAndYear')
})

useRender(() => (
<div class={[
'v-calendar',
Expand All @@ -196,20 +200,18 @@ export const VCalendar = genericComponent()({
]}
>
<div>
{ !props.hideHeader ? (
{ !props.hideHeader && (
<VCalendarHeader
key="calendarHeader"
title={ props.title }
start={ validDates.value[0] }
end={ validDates.value[1] }
onPrev={ prev }
onNext={ next }
key="calendar-header"
title={ title.value }
onClick:next={ onClickNext }
onClick:prev={ onClickPrev }
/>
) : '' }
)}
</div>

<div class="v-calendar__container">
{ props.type === 'month' && !props.hideDayHeader
? (
{ props.type === 'month' && !props.hideDayHeader && (
<div
class={
[
Expand All @@ -229,41 +231,57 @@ export const VCalendar = genericComponent()({
))
}
</div>
) : ''
}
{ props.type === 'month' ? (
<div
key="VCalendarMonth"
class={
[
'v-calendar-month__days',
`days__${props.weekdays.length}`,
...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : []),
]
}
>
{ chunkArray(daysIn.value, props.weekdays.length).map((week, wi) => (
[
!props.hideWeekNumber ? <div class="v-calendar-month__weeknumber">{ weeks.value[wi] }</div> : '',
week.map(day => (
<VCalendarMonthDay
color={ adapter.isSameDay(new Date(), day.date) ? 'primary' : undefined }
day={ day }
disabled={ day ? props.disabled?.includes(day.date) : false }
title={ day ? adapter.format(day.date, 'dayOfMonth') : 'NaN' }
events={ day.events }
></VCalendarMonthDay>
)),
]
))}
</div>
) : '' }
{ props.type === 'week' ? (
daysIn.value.map((day, i) => (
)}

{ props.type === 'month' && (
<div
key="VCalendarMonth"
class={
[
'v-calendar-month__days',
`days__${props.weekdays.length}`,
...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : []),
]
}
>
{ chunkArray(daysIn.value, props.weekdays.length).map((week, wi) => (
[
!props.hideWeekNumber ? <div class="v-calendar-month__weeknumber">{ weeks.value[wi] }</div> : '',
week.map(day => (
<VCalendarMonthDay
color={ adapter.isSameDay(new Date(), day.date) ? 'primary' : undefined }
day={ day }
disabled={ day ? props.disabled?.includes(day.date) : false }
title={ day ? adapter.format(day.date, 'dayOfMonth') : 'NaN' }
events={ day.events }
></VCalendarMonthDay>
)),
]
))}
</div>
)}

{ props.type === 'week' && (
daysIn.value.map((day, i) => (
<VCalendarDay
day={ day }
dayIndex={ i }
events={ day.events }
hideDayHeader={ props.hideDayHeader }
intervalDivisions={ props.intervalDivisions }
intervalDuration={ props.intervalDuration }
intervalHeight={ props.intervalHeight }
intervalLabel={ props.intervalLabel }
intervals={ props.intervals }
intervalStart={ props.intervalStart }
></VCalendarDay>
))
)}

{ props.type === 'day' && (
<VCalendarDay
day={ day }
dayIndex={ i }
events={ day.events }
day={ daysIn.value[0] }
events={ daysIn.value[0].events }
hideDayHeader={ props.hideDayHeader }
intervalDivisions={ props.intervalDivisions }
intervalDuration={ props.intervalDuration }
Expand All @@ -272,21 +290,7 @@ export const VCalendar = genericComponent()({
intervals={ props.intervals }
intervalStart={ props.intervalStart }
></VCalendarDay>
))
) : '' }
{ props.type === 'day' ? (
<VCalendarDay
day={ daysIn.value[0] }
events={ daysIn.value[0].events }
hideDayHeader={ props.hideDayHeader }
intervalDivisions={ props.intervalDivisions }
intervalDuration={ props.intervalDuration }
intervalHeight={ props.intervalHeight }
intervalLabel={ props.intervalLabel }
intervals={ props.intervals }
intervalStart={ props.intervalStart }
></VCalendarDay>
) : '' }
)}
</div>
</div>
))
Expand Down
11 changes: 11 additions & 0 deletions packages/vuetify/src/labs/VCalendar/VCalendarHeader.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.v-calendar-header
align-items: center
display: flex
min-height: 64px

.v-calendar-header__today
margin-inline-end: 24px

.v-calendar-header__title
font-size: 1.5rem
margin-inline-start: 24px
Loading

0 comments on commit c2b26ed

Please sign in to comment.