'use client' import * as React from 'react' import { OTPField as BaseOTPField } from '@base-ui/react/otp-field' import { type VariantProps } from 'class-variance-authority' import { cn } from '../../internal/utils' import { inputVariants } from '../input/input-variants' type OTPFieldVariant = NonNullable['variant']> type OTPFieldSize = NonNullable['size']> interface OTPFieldContextValue { variant: OTPFieldVariant size: OTPFieldSize } const OTPFieldContext = React.createContext(null) function useOTPFieldContext() { const ctx = React.useContext(OTPFieldContext) if (!ctx) { throw new Error('OTPField sub-components must be rendered inside ') } return ctx } const INPUT_SQUARE: Record = { sm: 'w-8', md: 'w-10', lg: 'w-12', } const SEPARATOR_SIZE: Record = { sm: 'w-3 [&_svg]:size-3', md: 'w-4 [&_svg]:size-3.5', lg: 'w-5 [&_svg]:size-4.5', } interface OTPFieldProps extends Omit, 'className'> { /** * Slot appearance - bordered or filled. * @default 'outline' */ variant?: OTPFieldVariant /** * Scales every slot. * @default 'md' */ size?: OTPFieldSize /** Extra classes on the root, merged via `tailwind-merge`. */ className?: string } function OTPField({ variant = 'outline', size = 'md', className, children, ...props }: OTPFieldProps) { const ctx = React.useMemo(() => ({ variant, size }), [variant, size]) return ( {children} ) } type OTPFieldInputProps = React.ComponentProps function OTPFieldInput({ className, ...props }: OTPFieldInputProps) { const { variant, size } = useOTPFieldContext() const ariaInvalid = props['aria-invalid'] const invalid = ariaInvalid === true || ariaInvalid === 'true' return ( ) } type OTPFieldSeparatorProps = React.ComponentProps function OTPFieldSeparator({ className, children, ...props }: OTPFieldSeparatorProps) { const { size } = useOTPFieldContext() return ( {children ?? } ) } function SeparatorMark() { return ( ) } export { OTPField, OTPFieldInput, OTPFieldSeparator } export type { OTPFieldProps, OTPFieldInputProps, OTPFieldSeparatorProps }