Skip to content

Commit

Permalink
fix(VDatePicker): add missing transition between months
Browse files Browse the repository at this point in the history
  • Loading branch information
johnleider committed Mar 30, 2024
1 parent c008ad5 commit 24c53d0
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 70 deletions.
155 changes: 89 additions & 66 deletions packages/vuetify/src/components/VDatePicker/VDatePickerMonth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { VDefaultsProvider } from '@/components/VDefaultsProvider'
// Composables
import { makeCalendarProps, useCalendar } from '@/composables/calendar'
import { useDate } from '@/composables/date/date'
import { MaybeTransition } from '@/composables/transition'

// Utilities
import { computed, ref, shallowRef } from 'vue'
import { computed, ref, shallowRef, watch } from 'vue'
import { genericComponent, propsFactory } from '@/util'

// Types
Expand All @@ -31,6 +32,14 @@ export const makeVDatePickerMonthProps = propsFactory({
hideWeekdays: Boolean,
multiple: [Boolean, Number, String] as PropType<boolean | 'range' | number | (string & {})>,
showWeek: Boolean,
transition: {
type: String,
default: 'picker-transition',
},
reverseTransition: {
type: String,
default: 'picker-reverse-transition',
},

...makeCalendarProps(),
}, 'VDatePickerMonth')
Expand All @@ -54,6 +63,11 @@ export const VDatePickerMonth = genericComponent<VDatePickerMonthSlots>()({

const rangeStart = shallowRef()
const rangeStop = shallowRef()
const isReverse = shallowRef(false)

const transition = computed(() => {
return !isReverse.value ? props.transition : props.reverseTransition
})

if (props.multiple === 'range' && model.value.length > 0) {
rangeStart.value = model.value[0]
Expand All @@ -68,6 +82,12 @@ export const VDatePickerMonth = genericComponent<VDatePickerMonthSlots>()({
return model.value.length >= max
})

watch(daysInMonth, (val, oldVal) => {
if (!oldVal) return

isReverse.value = adapter.isBefore(val[0].date, oldVal[0].date)
})

function onRangeClick (value: unknown) {
const _value = adapter.startOfDay(value)

Expand Down Expand Up @@ -144,75 +164,78 @@ export const VDatePickerMonth = genericComponent<VDatePickerMonthSlots>()({
</div>
)}

<div
ref={ daysRef }
class="v-date-picker-month__days"
>
{ !props.hideWeekdays && adapter.getWeekdays().map(weekDay => (
<div
class={[
'v-date-picker-month__day',
'v-date-picker-month__weekday',
]}
>{ weekDay }</div>
))}

{ daysInMonth.value.map((item, i) => {
const slotProps = {
props: {
onClick: () => onClick(item.date),
},
item,
i,
} as const

if (atMax.value && !item.isSelected) {
item.isDisabled = true
}

return (
<MaybeTransition name={ transition.value }>
<div
ref={ daysRef }
key={ daysInMonth.value[0].date.toString() }
class="v-date-picker-month__days"
>
{ !props.hideWeekdays && adapter.getWeekdays().map(weekDay => (
<div
class={[
'v-date-picker-month__day',
{
'v-date-picker-month__day--adjacent': item.isAdjacent,
'v-date-picker-month__day--hide-adjacent': item.isHidden,
'v-date-picker-month__day--selected': item.isSelected,
'v-date-picker-month__day--week-end': item.isWeekEnd,
'v-date-picker-month__day--week-start': item.isWeekStart,
},
'v-date-picker-month__weekday',
]}
data-v-date={ !item.isDisabled ? item.isoDate : undefined }
>

{ (props.showAdjacentMonths || !item.isAdjacent) && (
<VDefaultsProvider
defaults={{
VBtn: {
class: 'v-date-picker-month__day-btn',
color: (item.isSelected || item.isToday) && !item.isDisabled
? props.color
: undefined,
disabled: item.isDisabled,
icon: true,
ripple: false,
text: item.localized,
variant: item.isDisabled
? item.isToday ? 'outlined' : 'text'
: item.isToday && !item.isSelected ? 'outlined' : 'flat',
onClick: () => onClick(item.date),
},
}}
>
{ slots.day?.(slotProps) ?? (
<VBtn { ...slotProps.props } />
)}
</VDefaultsProvider>
)}
</div>
)
})}
</div>
>{ weekDay }</div>
))}

{ daysInMonth.value.map((item, i) => {
const slotProps = {
props: {
onClick: () => onClick(item.date),
},
item,
i,
} as const

if (atMax.value && !item.isSelected) {
item.isDisabled = true
}

return (
<div
class={[
'v-date-picker-month__day',
{
'v-date-picker-month__day--adjacent': item.isAdjacent,
'v-date-picker-month__day--hide-adjacent': item.isHidden,
'v-date-picker-month__day--selected': item.isSelected,
'v-date-picker-month__day--week-end': item.isWeekEnd,
'v-date-picker-month__day--week-start': item.isWeekStart,
},
]}
data-v-date={ !item.isDisabled ? item.isoDate : undefined }
>

{ (props.showAdjacentMonths || !item.isAdjacent) && (
<VDefaultsProvider
defaults={{
VBtn: {
class: 'v-date-picker-month__day-btn',
color: (item.isSelected || item.isToday) && !item.isDisabled
? props.color
: undefined,
disabled: item.isDisabled,
icon: true,
ripple: false,
text: item.localized,
variant: item.isDisabled
? item.isToday ? 'outlined' : 'text'
: item.isToday && !item.isSelected ? 'outlined' : 'flat',
onClick: () => onClick(item.date),
},
}}
>
{ slots.day?.(slotProps) ?? (
<VBtn { ...slotProps.props } />
)}
</VDefaultsProvider>
)}
</div>
)
})}
</div>
</MaybeTransition>
</div>
)
},
Expand Down
2 changes: 2 additions & 0 deletions packages/vuetify/src/labs/VPicker/VPicker.sass
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

.v-picker__body
grid-area: body
overflow: hidden
position: relative

.v-picker__header
grid-area: header
Expand Down
8 changes: 4 additions & 4 deletions packages/vuetify/src/styles/generic/_transitions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,23 @@
@include transition-default();

&-enter-from {
transform: translate(0, 100%);
transform: translate(100%, 0);
}

&-leave-to {
transform: translate(0, -100%);
transform: translate(-100%, 0);
}
}

.picker-reverse-transition {
@include transition-default();

&-enter-from {
transform: translate(0, -100%);
transform: translate(-100%, 0);
}

&-leave-to {
transform: translate(0, 100%);
transform: translate(100%, 0);
}
}

Expand Down

0 comments on commit 24c53d0

Please sign in to comment.