feat : DateTime utilise les molettes au lieu de l'input time natif (MUI-39)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 10:14:17 +02:00
parent b56a306cac
commit 000f2c21bc
2 changed files with 17 additions and 25 deletions
+9 -8
View File
@@ -2,6 +2,7 @@ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
import {mount} from '@vue/test-utils'
import type {DefineComponent} from 'vue'
import DateTime_ from './DateTime.vue'
import TimeWheels from '../time/internal/TimeWheels.vue'
type DateTimeProps = {
id?: string
@@ -49,11 +50,11 @@ describe('MalioDateTime', () => {
})
describe('popover', () => {
it('ouvre la grille et l\'input heure au clic', async () => {
it('ouvre la grille et les molettes au clic', async () => {
const wrapper = mountDateTime()
await wrapper.get('[data-test="date-input"]').trigger('click')
expect(wrapper.find('[data-test="month-grid"]').exists()).toBe(true)
expect(wrapper.find('[data-test="time-input"]').exists()).toBe(true)
expect(wrapper.find('[data-test="time-wheels"]').exists()).toBe(true)
})
})
@@ -69,8 +70,8 @@ describe('MalioDateTime', () => {
it('applique l\'heure réglée avant le clic du jour', async () => {
const wrapper = mountDateTime()
await wrapper.get('[data-test="date-input"]').trigger('click')
await wrapper.get('[data-test="time-input"]').setValue('09:15')
// pas d'émission tant qu'aucun jour n'est choisi
wrapper.findComponent(TimeWheels).vm.$emit('update:modelValue', '09:15')
await wrapper.vm.$nextTick()
expect(wrapper.emitted('update:modelValue')).toBeUndefined()
await wrapper.get('[data-test="day"][data-iso="2026-05-19"]').trigger('click')
expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['2026-05-19T09:15:00'])
@@ -79,15 +80,15 @@ describe('MalioDateTime', () => {
it('met à jour l\'heure quand une date est déjà choisie', async () => {
const wrapper = mountDateTime({modelValue: '2026-05-20T14:30:00'})
await wrapper.get('[data-test="date-input"]').trigger('click')
await wrapper.get('[data-test="time-input"]').setValue('08:45')
wrapper.findComponent(TimeWheels).vm.$emit('update:modelValue', '08:45')
await wrapper.vm.$nextTick()
expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['2026-05-20T08:45:00'])
})
it('initialise l\'input heure depuis la valeur', async () => {
it('initialise les molettes depuis la valeur', async () => {
const wrapper = mountDateTime({modelValue: '2026-05-20T14:30:00'})
await wrapper.get('[data-test="date-input"]').trigger('click')
const time = wrapper.get('[data-test="time-input"]').element as HTMLInputElement
expect(time.value).toBe('14:30')
expect(wrapper.findComponent(TimeWheels).props('modelValue')).toBe('14:30')
})
})
+8 -17
View File
@@ -28,25 +28,21 @@
:max="max?.slice(0, 10)"
@select="onSelectDay"
/>
<!-- Bloc heure intérimaire : input natif, isolé pour remplacement futur par le sélecteur dédié. -->
<div class="mt-[26px] flex-col items-center gap-2">
<input
:id="timeInputId"
data-test="time-input"
type="time"
:value="timeValue"
class="w-full border border-m-muted bg-white px-2 py-1 text-base outline-none focus:border-m-primary"
@input="onTimeInput"
>
<div class="mt-[26px]">
<TimeWheels
:model-value="timeValue || '00:00'"
@update:model-value="onTimeChange"
/>
</div>
</template>
</CalendarField>
</template>
<script setup lang="ts">
import {computed, ref, useId, watch} from 'vue'
import {computed, ref, watch} from 'vue'
import CalendarField from './internal/CalendarField.vue'
import MonthGrid from './internal/MonthGrid.vue'
import TimeWheels from '../time/internal/TimeWheels.vue'
import {composeDateTime, formatIsoDateTimeToDisplay, isValidIsoDateTime, splitDateTime} from './composables/datetimeFormat'
defineOptions({name: 'MalioDateTime', inheritAttrs: false})
@@ -94,9 +90,6 @@ const props = withDefaults(
const emit = defineEmits<{(e: 'update:modelValue', value: string | null): void}>()
const generatedId = useId()
const timeInputId = computed(() => `${props.id || `malio-datetime-${generatedId}`}-time`)
// pendingTime : heure réglée avant qu'un jour ne soit choisi (sinon on ne peut pas émettre).
const pendingTime = ref('')
@@ -110,9 +103,7 @@ function onSelectDay(iso: string) {
emit('update:modelValue', composeDateTime(iso, time))
}
function onTimeInput(e: Event) {
const value = (e.target as HTMLInputElement).value
if (!value) return
function onTimeChange(value: string) {
if (datePart.value) {
emit('update:modelValue', composeDateTime(datePart.value, value))
}