"use client" import { createContext, ReactNode, useContext, useId } from "react" import { NumberField as NumberFieldPrimitive } from "@base-ui/react/number-field" import { cva, VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" import { Label } from "@/components/ui/label" import { MinusIcon, PlusIcon } from "lucide-react" const NumberFieldContext = createContext<{ fieldId: string size: "sm" | "default" | "lg" } | null>(null) const numberFieldGroupVariants = cva( "relative flex w-full justify-between border border-input data-disabled:pointer-events-none data-disabled:opacity-50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive focus-within:has-aria-invalid:border-destructive focus-within:has-aria-invalid:ring-destructive/20 dark:focus-within:has-aria-invalid:ring-destructive/40 rounded-lg bg-transparent dark:bg-input/30 transition-colors focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-3", { variants: { size: { sm: "h-7 text-sm", default: "h-8 text-sm", lg: "h-9 text-sm", }, }, defaultVariants: { size: "default", }, } ) const numberFieldButtonVariants = cva( "relative flex shrink-0 cursor-pointer items-center justify-center transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent", { variants: { size: { sm: "px-1.5 [&_svg:not([class*='size-'])]:size-3.5", default: "px-2 [&_svg:not([class*='size-'])]:size-4", lg: "px-2.5 [&_svg:not([class*='size-'])]:size-4", }, }, defaultVariants: { size: "default", }, } ) const numberFieldInputVariants = cva( "w-full min-w-0 flex-1 bg-transparent text-center tabular-nums outline-none", { variants: { size: { sm: "px-2 py-0.5", default: "px-2.5 py-1", lg: "px-2.5 py-1.5", }, }, defaultVariants: { size: "default", }, } ) function NumberField({ id, className, size = "default", ...props }: NumberFieldPrimitive.Root.Props & VariantProps) { const generatedId = useId() const fieldId = id ?? generatedId const sizeValue = size ?? "default" return ( ) } function NumberFieldGroup({ className, size: sizeProp, ...props }: NumberFieldPrimitive.Group.Props & Partial>) { const context = useContext(NumberFieldContext) if (!context) { throw new Error( "NumberFieldGroup must be used within a NumberField component." ) } const size = sizeProp ?? context.size return ( ) } function NumberFieldDecrement({ className, size: sizeProp, children, ...props }: NumberFieldPrimitive.Decrement.Props & Partial> & { children?: React.ReactNode }) { const context = useContext(NumberFieldContext) if (!context) { throw new Error( "NumberFieldDecrement must be used within a NumberField component." ) } const size = sizeProp ?? context.size return ( {children ?? ( )} ) } function NumberFieldIncrement({ className, size: sizeProp, children, ...props }: NumberFieldPrimitive.Increment.Props & Partial> & { children?: ReactNode }) { const context = useContext(NumberFieldContext) if (!context) { throw new Error( "NumberFieldIncrement must be used within a NumberField component." ) } const size = sizeProp ?? context.size return ( {children ?? ( )} ) } function NumberFieldInput({ className, size: sizeProp, ...props }: NumberFieldPrimitive.Input.Props & Partial>) { const context = useContext(NumberFieldContext) if (!context) { throw new Error( "NumberFieldInput must be used within a NumberField component." ) } const size = sizeProp ?? context.size return ( ) } function NumberFieldScrubArea({ className, label, ...props }: NumberFieldPrimitive.ScrubArea.Props & { label: string }) { const context = useContext(NumberFieldContext) if (!context) { throw new Error( "NumberFieldScrubArea must be used within a NumberField component for accessibility." ) } return ( ) } function CursorGrowIcon(props: React.ComponentProps<"svg">) { return ( ) } export { NumberField, NumberFieldScrubArea, NumberFieldDecrement, NumberFieldIncrement, NumberFieldGroup, NumberFieldInput, }