"use client" import { cn } from "@/lib/utils" import { Check, Minus, Plus } from "lucide-react" import type React from "react" import { forwardRef, useEffect, useId, useRef, useState } from "react" /* ------------------------------------------------------------------ */ /* Debounce hook */ /* ------------------------------------------------------------------ */ export function useDebouncedValue(value: T, delay = 250): T { const [debounced, setDebounced] = useState(value) useEffect(() => { const t = setTimeout(() => setDebounced(value), delay) return () => clearTimeout(t) }, [value, delay]) return debounced } /* ------------------------------------------------------------------ */ /* Field wrapper */ /* ------------------------------------------------------------------ */ export function Field({ label, hint, error, optional, htmlFor, children, className, }: { label?: string hint?: string error?: string | null optional?: boolean htmlFor?: string children: React.ReactNode className?: string }) { return (
{label ? ( ) : null} {children} {hint && !error ?

{hint}

: null} {error ? (

{error}

) : null}
) } /* ------------------------------------------------------------------ */ /* Text input / textarea / native select */ /* ------------------------------------------------------------------ */ const controlBase = "w-full rounded-lg border bg-[var(--nr-surface-2)] px-3 text-[16px] text-[var(--nr-ink)] outline-none transition-colors placeholder:text-[var(--nr-faint)] focus-visible:border-[var(--nr-accent)] focus-visible:ring-4 focus-visible:ring-[var(--nr-accent-ring)]/40 disabled:opacity-50" export const TextInput = forwardRef & { invalid?: boolean }>( ({ className, invalid, ...props }, ref) => ( ), ) TextInput.displayName = "TextInput" export const TextArea = ({ className, ...props }: React.TextareaHTMLAttributes) => (