From be276cd9fe8a4a596cd80bb824afc700f2fc7f1e Mon Sep 17 00:00:00 2001 From: John Leider Date: Sat, 27 Apr 2024 13:42:04 -0500 Subject: [PATCH] feat(VTimeInput): add new component --- packages/vuetify/src/iconsets/mdi.ts | 1 + .../src/labs/VTimeInput/VTimeInput.tsx | 146 ++++++++++++++++++ packages/vuetify/src/labs/VTimeInput/index.ts | 1 + 3 files changed, 148 insertions(+) create mode 100644 packages/vuetify/src/labs/VTimeInput/VTimeInput.tsx create mode 100644 packages/vuetify/src/labs/VTimeInput/index.ts diff --git a/packages/vuetify/src/iconsets/mdi.ts b/packages/vuetify/src/iconsets/mdi.ts index d1a9e788062..3392250c769 100644 --- a/packages/vuetify/src/iconsets/mdi.ts +++ b/packages/vuetify/src/iconsets/mdi.ts @@ -23,6 +23,7 @@ const aliases: IconAliases = { checkboxOn: 'mdi-checkbox-marked', checkboxOff: 'mdi-checkbox-blank-outline', checkboxIndeterminate: 'mdi-minus-box', + clock: 'mdi-clock', delimiter: 'mdi-circle', // for carousel sortAsc: 'mdi-arrow-up', sortDesc: 'mdi-arrow-down', diff --git a/packages/vuetify/src/labs/VTimeInput/VTimeInput.tsx b/packages/vuetify/src/labs/VTimeInput/VTimeInput.tsx new file mode 100644 index 00000000000..96b289a8556 --- /dev/null +++ b/packages/vuetify/src/labs/VTimeInput/VTimeInput.tsx @@ -0,0 +1,146 @@ +// Components +import { VMenu } from '@/components/VMenu/VMenu' +import { makeVTextFieldProps, VTextField } from '@/components/VTextField/VTextField' +import { makeVConfirmEditProps, VConfirmEdit } from '@/labs/VConfirmEdit/VConfirmEdit' +import { makeVTimePickerProps, VTimePicker } from '@/labs/VTimePicker/VTimePicker' + +// Composables +import { useDate } from '@/composables/date' +import { makeFocusProps, useFocus } from '@/composables/focus' +import { useLocale } from '@/composables/locale' +import { useProxiedModel } from '@/composables/proxiedModel' + +// Utilities +import { computed, shallowRef } from 'vue' +import { genericComponent, omit, propsFactory, useRender, wrapInArray } from '@/util' + +// Types +export interface VTimeInputSlots { + default: never +} + +export const makeVTimeInputProps = propsFactory({ + hideActions: Boolean, + + ...makeFocusProps(), + ...makeVConfirmEditProps(), + ...makeVTextFieldProps({ + placeholder: 'hh:mm', + prependIcon: '$clock', + }), + ...omit(makeVTimePickerProps({ + weeksInMonth: 'dynamic' as const, + hideHeader: true, + }), ['active']), +}, 'VTimeInput') + +export const VTimeInput = genericComponent()({ + name: 'VTimeInput', + + props: makeVTimeInputProps(), + + emits: { + 'update:modelValue': (val: string) => true, + }, + + setup (props, { slots }) { + const { t } = useLocale() + const adapter = useDate() + const { isFocused, focus, blur } = useFocus(props) + const model = useProxiedModel(props, 'modelValue', props.multiple ? [] : null) + const menu = shallowRef(false) + + const display = computed(() => { + const value = wrapInArray(model.value) + + if (!value.length) return null + + return adapter.isValid(model.value) ? adapter.format(model.value, 'keyboardDate') : '' + }) + + function onKeydown (e: KeyboardEvent) { + if (e.key !== 'Enter') return + + if (!menu.value || !isFocused.value) { + menu.value = true + + return + } + + const target = e.target as HTMLInputElement + + model.value = adapter.date(target.value) + } + + function onClick (e: MouseEvent) { + e.preventDefault() + e.stopPropagation() + + menu.value = true + } + + function onSave () { + menu.value = false + } + + useRender(() => { + const confirmEditProps = VConfirmEdit.filterProps(props) + const timePickerProps = VTimePicker.filterProps(omit(props, ['active'])) + const textFieldProps = VTextField.filterProps(props) + + return ( + + + + {{ + default: ({ actions, model: proxyModel }) => { + return ( + { + if (!props.hideActions) { + proxyModel.value = val + } else { + model.value = val + } + }} + onMousedown={ (e: MouseEvent) => e.preventDefault() } + > + {{ + actions: !props.hideActions ? () => actions : undefined, + }} + + ) + }, + }} + + + + { slots.default?.() } + + ) + }) + }, +}) + +export type VTimeInput = InstanceType diff --git a/packages/vuetify/src/labs/VTimeInput/index.ts b/packages/vuetify/src/labs/VTimeInput/index.ts new file mode 100644 index 00000000000..7d898041ef2 --- /dev/null +++ b/packages/vuetify/src/labs/VTimeInput/index.ts @@ -0,0 +1 @@ +export { VTimeInput } from './VTimeInput'