tsf-datetime-field
shuip/tsf-datetime-fieldFreeComponent
shuip publishes no description for this item.
Live preview
live · rendered by the registry
Rendered by shuip on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://shuip.plvo.dev/r/tsf-datetime-field.jsonSource
1'use client';23import type { Locale } from 'date-fns';4import { format, setHours, setMinutes } from 'date-fns';5import { CalendarIcon } from 'lucide-react';6import * as React from 'react';7import { Button } from '@/components/ui/button';8import { Calendar } from '@/components/ui/calendar';9import { Field, FieldDescription, FieldError, FieldLabel } from '@/components/ui/field';10import { InputGroup, InputGroupInput } from '@/components/ui/input-group';11import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';12import { useFieldContext } from '@/components/ui/shuip/tanstack-form/form-context';13import { cn } from '@/lib/utils';1415export interface DatetimeFieldProps {16 label?: string;17 description?: string;18 placeholder?: string;19 minDate?: Date;20 maxDate?: Date;21 locale?: Locale;22 disabled?: boolean;23 step?: number;24}2526const pad2 = (n: number): string => n.toString().padStart(2, '0');2728const toTimeInputValue = (date: Date | undefined): string =>29 date ? `${pad2(date.getHours())}:${pad2(date.getMinutes())}` : '';3031export function DatetimeField({32 label,33 description,34 placeholder = 'Pick a date & time',35 minDate,36 maxDate,37 locale,38 disabled,39 step = 60,40}: DatetimeFieldProps) {41 const field = useFieldContext<Date | undefined>();42 const { isValid, errors } = field.state.meta;43 const [open, setOpen] = React.useState(false);4445 const value = field.state.value;4647 const handleDateSelect = (next: Date | undefined) => {48 if (!next) {49 field.handleChange(undefined);50 return;51 }52 const hours = value?.getHours() ?? 0;53 const minutes = value?.getMinutes() ?? 0;54 field.handleChange(setMinutes(setHours(next, hours), minutes));55 };5657 const handleTimeChange = (event: React.ChangeEvent<HTMLInputElement>) => {58 if (!value) return;59 const raw = event.target.value;60 if (!raw) return;61 const [h, m] = raw.split(':').map((part) => Number.parseInt(part, 10));62 if (Number.isNaN(h) || Number.isNaN(m)) return;63 field.handleChange(setMinutes(setHours(value, h), m));64 };6566 const triggerLabel = value ? format(value, 'PPp', locale ? { locale } : undefined) : placeholder;6768 return (69 <Field className='gap-2' data-invalid={!isValid}>70 {label && <FieldLabel htmlFor={field.name}>{label}</FieldLabel>}71 <Popover open={open} onOpenChange={setOpen}>72 <PopoverTrigger asChild>73 <Button74 id={field.name}75 type='button'76 variant='outline'77// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from shuip
All 52 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| confirmation-dialogconfirmation-dialog | shuip | Components | Free | 1 dep | |
| copy-buttoncopy-button | shuip | Components | Free | 3 deps | |
| hover-revealhover-reveal | shuip | Components | Free | 1 dep | |
| rhf-address-fieldrhf-address-field | shuip | Components | Free | 5 deps · 2 files | |
| rhf-autocomplete-fieldrhf-autocomplete-field | shuip | Components | Free | 4 deps | |
| rhf-checkbox-fieldrhf-checkbox-field | shuip | Components | Free | 3 deps | |
| rhf-combobox-fieldrhf-combobox-field | shuip | Components | Free | 5 deps | |
| rhf-date-fieldrhf-date-field | shuip | Components | Free | 6 deps |
