"use client" import * as React from "react" import { cn } from "@/lib/utils" export type SegmentedControlOption = { value: TValue label: React.ReactNode icon?: React.ReactNode disabled?: boolean } export type SegmentedControlProps = Omit, "onChange"> & { value?: TValue defaultValue?: TValue onValueChange?: (value: TValue) => void options: SegmentedControlOption[] size?: "sm" | "md" | "lg" fullWidth?: boolean equalWidth?: boolean } const sizeClassName = { sm: "min-h-8 px-2.5 text-xs", md: "min-h-9 px-3.5 text-sm", lg: "min-h-10 px-4 text-sm", } function SegmentedControl({ value, defaultValue, onValueChange, options, size = "md", fullWidth = false, equalWidth = false, className, ...props }: SegmentedControlProps) { const [internalValue, setInternalValue] = React.useState(defaultValue ?? options[0]?.value) const currentValue = value ?? internalValue const buttonRefs = React.useRef>([]) const selectValue = (nextValue: TValue) => { if (value === undefined) setInternalValue(nextValue) onValueChange?.(nextValue) } const moveFocus = (fromIndex: number, direction: 1 | -1) => { const enabledOptions = options .map((option, index) => ({ option, index })) .filter(({ option }) => !option.disabled) const enabledIndex = enabledOptions.findIndex(({ index }) => index === fromIndex) const next = enabledOptions[(enabledIndex + direction + enabledOptions.length) % enabledOptions.length] buttonRefs.current[next?.index ?? fromIndex]?.focus() } return (
{options.map((option, optionIndex) => { const selected = option.value === currentValue return ( ) })}
) } export { SegmentedControl }