Skip to content

Commit

Permalink
fix(DateField): fix hour segment update by dayPeriod (#981)
Browse files Browse the repository at this point in the history
* fix(DateField): properly update hour on dayPeriod change

* chore(DateField): add tests for dayPeriod updates
  • Loading branch information
epr3 authored Jun 1, 2024
1 parent 8f73df3 commit 1b970ec
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 11 deletions.
34 changes: 33 additions & 1 deletion packages/radix-vue/src/DateField/DateField.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ function thisTimeZone(date: string): string {
function setup(props: { dateFieldProps?: DateFieldRootProps, emits?: { 'onUpdate:modelValue'?: (data: DateValue) => void } } = {}) {
const user = userEvent.setup()
const returned = render(DateField, { props })
const value = returned.getByTestId('value')
const month = returned.getByTestId('month')
const day = returned.getByTestId('day')
const year = returned.getByTestId('year')
const input = returned.getByTestId('input')
const label = returned.getByTestId('label')

return { ...returned, user, month, day, year, input, label }
return { ...returned, user, month, day, year, input, label, value }
}

it('should pass axe accessibility tests', async () => {
Expand Down Expand Up @@ -439,6 +440,37 @@ describe('dateField', async () => {
expect(dayPeriod).toHaveFocus()
})

it('updates the hour on the modelValue if the dayPeriod is updated', async () => {
const { getByTestId, user, value, rerender } = setup({
dateFieldProps: {
modelValue: calendarDateTime,
granularity: 'second',
},
emits: {
'onUpdate:modelValue': (data: DateValue) => {
return rerender({
dateFieldProps: {
modelValue: data,
granularity: 'second',
},
})
},
},
})

const dayPeriod = getByTestId('dayPeriod')
expect(value.textContent).toBe(calendarDateTime.toString())
await user.click(dayPeriod)
await user.keyboard('{a}')
expect(getByTestId('value').textContent).toBe(calendarDateTime.subtract({ hours: 12 }).toString())
await user.keyboard('{p}')
expect(getByTestId('value').textContent).toBe(calendarDateTime.toString())
await user.keyboard('{A}')
expect(getByTestId('value').textContent).toBe(calendarDateTime.subtract({ hours: 12 }).toString())
await user.keyboard('{P}')
expect(getByTestId('value').textContent).toBe(calendarDateTime.toString())
})

it('fully overwrites on first click and type - `month`', async () => {
const { user, month } = setup({
dateFieldProps: {
Expand Down
4 changes: 3 additions & 1 deletion packages/radix-vue/src/DateField/story/_DateField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ const props = defineProps<{ dateFieldProps?: DateFieldRootProps, emits?: { 'onUp
<DateFieldRoot
v-bind="props.dateFieldProps"
id="date-field"
v-slot="{ segments }"
v-slot="{ segments, modelValue }"
data-testid="input"
v-on="{ 'update:modelValue': props.emits?.['onUpdate:modelValue'] }"
>
<DateFieldInput v-for="item in segments" :key="item.part" :part="item.part" :data-testid="item.part === 'literal' ? undefined : item.part">
{{ item.value }}
</DateFieldInput>
<span data-testid="value" tabindex="-1" disabled>{{ modelValue }}</span>
</DateFieldRoot>
</template>
12 changes: 3 additions & 9 deletions packages/radix-vue/src/DateField/useDateField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -770,13 +770,13 @@ export function useDateField(props: UseDateFieldProps) {
return
}

if (e.key === 'a') {
if (['a', 'A'].includes(e.key) && props.segmentValues.value.dayPeriod !== 'AM') {
props.segmentValues.value.dayPeriod = 'AM'
props.segmentValues.value.hour = props.segmentValues.value.hour! - 12
return
}

if (e.key === 'p') {
if (['p', 'P'].includes(e.key) && props.segmentValues.value.dayPeriod !== 'PM') {
props.segmentValues.value.dayPeriod = 'PM'
props.segmentValues.value.hour = props.segmentValues.value.hour! + 12
}
Expand Down Expand Up @@ -811,13 +811,7 @@ export function useDateField(props: UseDateFieldProps) {

if (!isSegmentNavigationKey(e.key) && e.key !== kbd.TAB && e.key !== kbd.SHIFT && isAcceptableSegmentKey(e.key)) {
if (Object.values(props.segmentValues.value).every(item => item !== null)) {
let updateObject = { ...props.segmentValues.value as Record<AnyExceptLiteral, number> }
if ('dayPeriod' in props.segmentValues.value) {
updateObject = {
...updateObject,
hour: props.segmentValues.value.dayPeriod === 'PM' && !props.modelValue.value ? props.segmentValues.value.hour! + 12 : props.segmentValues.value.hour!,
}
}
const updateObject = { ...props.segmentValues.value as Record<AnyExceptLiteral, number> }

let dateRef = props.placeholder.value.copy()

Expand Down
4 changes: 4 additions & 0 deletions packages/radix-vue/src/DateField/utils/segment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export function isAcceptableSegmentKey(key: string) {
kbd.ARROW_RIGHT,
kbd.BACKSPACE,
kbd.SPACE,
'a',
'A',
'p',
'P',
]
if (acceptableSegmentKeys.includes(key))
return true
Expand Down

0 comments on commit 1b970ec

Please sign in to comment.