Files
tools/vue/primitives/src/date-picker/DatePickerField.vue
T

73 lines
2.0 KiB
Vue

<script lang="ts">
import type { PrimitiveProps } from '../primitive';
/**
* A text input that renders the selected date and, when `editable`, lets users
* type a date that is parsed and committed back to the picker on blur/Enter.
* Aliased as `DatePickerInput`; defaults to a read-only display of the value.
*/
export interface DatePickerFieldProps extends PrimitiveProps {
/** Allow typing into the field. @default false (read-only display) */
editable?: boolean;
/** Display format for the rendered value. */
format?: Intl.DateTimeFormatOptions;
/** Placeholder text shown when no value is selected. */
placeholderText?: string;
}
</script>
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { formatDate } from '../calendar';
import { useDatePickerRootContext } from './context';
const {
as: _as = 'input',
editable = false,
format = { year: 'numeric', month: '2-digit', day: '2-digit' },
placeholderText,
} = defineProps<DatePickerFieldProps>();
const ctx = useDatePickerRootContext();
const displayValue = computed(() => {
if (!ctx.modelValue.value) return '';
return formatDate(ctx.modelValue.value, format, ctx.locale.value);
});
const draft = ref(displayValue.value);
watch(displayValue, (v) => {
draft.value = v;
});
function commit() {
if (!editable) return;
const text = draft.value.trim();
if (!text) {
ctx.modelValue.value = undefined;
return;
}
const parsed = new Date(text);
if (!Number.isNaN(parsed.getTime()))
ctx.modelValue.value = new Date(parsed.getFullYear(), parsed.getMonth(), parsed.getDate());
else
draft.value = displayValue.value;
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') commit();
}
</script>
<template>
<input
:value="editable ? draft : displayValue"
:readonly="!editable"
:placeholder="placeholderText"
:data-primitives-date-picker-field="''"
@input="(e) => { if (editable) draft = (e.target as HTMLInputElement).value; }"
@blur="commit"
@keydown="handleKeydown"
>
</template>