{
  "name": "rhf-time-range",
  "type": "registry:ui",
  "dependencies": [
    "@hookform/lenses",
    "react-hook-form"
  ],
  "registryDependencies": [
    "field",
    "select",
    "time"
  ],
  "files": [
    {
      "path": "./items/react-hook-form/time-range/component.tsx",
      "type": "registry:ui",
      "target": "./components/ui/shuip/react-hook-form/time-range.tsx",
      "content": "'use client';\n\nimport type { Lens } from '@hookform/lenses';\nimport { useController } from 'react-hook-form';\nimport { Field, FieldDescription, FieldError, FieldLabel } from '@/components/ui/field';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';\nimport {\n  addOneHour,\n  HOUR_OPTIONS,\n  isHourDisabled,\n  isMinuteDisabled,\n  joinTime,\n  MINUTE_OPTIONS,\n  nextSlot,\n  splitTime,\n  type TimeRangeValue,\n} from '@/lib/time';\n\ninterface TimePickerProps {\n  id?: string;\n  value: string;\n  onChange: (value: string) => void;\n  min?: string;\n  disabled?: boolean;\n  invalid?: boolean;\n}\n\nfunction TimePicker({ id, value, onChange, min, disabled, invalid }: TimePickerProps) {\n  const { hour, minute } = splitTime(value);\n  const bounds = { min };\n\n  return (\n    <div className='flex items-center gap-2'>\n      <Select value={hour} onValueChange={(h) => onChange(joinTime(h, minute))} disabled={disabled}>\n        <SelectTrigger id={id} aria-invalid={invalid} className='w-full'>\n          <SelectValue placeholder='HH' />\n        </SelectTrigger>\n        <SelectContent>\n          {HOUR_OPTIONS.map((h) => (\n            <SelectItem key={h} value={h} disabled={isHourDisabled(h, bounds)}>\n              {h}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n      <span className='text-muted-foreground'>:</span>\n      <Select value={minute} onValueChange={(m) => onChange(joinTime(hour, m))} disabled={disabled}>\n        <SelectTrigger aria-invalid={invalid} className='w-full'>\n          <SelectValue placeholder='mm' />\n        </SelectTrigger>\n        <SelectContent>\n          {MINUTE_OPTIONS.map((m) => (\n            <SelectItem key={m} value={m} disabled={isMinuteDisabled(m, hour, bounds)}>\n              {m}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n    </div>\n  );\n}\n\nexport interface TimeRangeFieldProps {\n  lens: Lens<TimeRangeValue>;\n  label?: string;\n  description?: string;\n  startLabel?: string;\n  endLabel?: string;\n  disabled?: boolean;\n}\n\nexport function TimeRangeField({\n  lens,\n  label,\n  description,\n  startLabel = 'Start',\n  endLabel = 'End',\n  disabled,\n}: TimeRangeFieldProps) {\n  const { field, fieldState } = useController(lens.interop());\n  const value: TimeRangeValue = field.value ?? { start: '', end: '' };\n\n  return (\n    <Field className='gap-2' data-invalid={fieldState.invalid}>\n      {label && <FieldLabel>{label}</FieldLabel>}\n      <div className='flex flex-col gap-3 sm:flex-row sm:items-end'>\n        <div className='flex flex-1 flex-col gap-1'>\n          <FieldLabel htmlFor={`${field.name}-start`} className='text-xs'>\n            {startLabel}\n          </FieldLabel>\n          <TimePicker\n            id={`${field.name}-start`}\n            value={value.start}\n            onChange={(start) => field.onChange({ start, end: addOneHour(start) })}\n            disabled={disabled}\n            invalid={fieldState.invalid}\n          />\n        </div>\n        <div className='flex flex-1 flex-col gap-1'>\n          <FieldLabel htmlFor={`${field.name}-end`} className='text-xs'>\n            {endLabel}\n          </FieldLabel>\n          <TimePicker\n            id={`${field.name}-end`}\n            value={value.end}\n            onChange={(end) => field.onChange({ ...value, end })}\n            min={value.start ? nextSlot(value.start) : undefined}\n            disabled={disabled}\n            invalid={fieldState.invalid}\n          />\n        </div>\n      </div>\n      {fieldState.invalid && <FieldError className='text-xs text-left' errors={[fieldState.error]} />}\n      {description && <FieldDescription className='text-xs'>{description}</FieldDescription>}\n    </Field>\n  );\n}\n"
    }
  ],
  "$schema": "https://ui.shadcn.com/schema/registry-item.json"
}
