import React, { useState, useRef, useLayoutEffect, useCallback, memo } from 'react'; import { useLocalize } from '~/hooks'; interface Option { value: string; label: string; icon?: React.ReactNode; } interface RadioProps { options: Option[]; value?: string; onChange?: (value: string) => void; disabled?: boolean; className?: string; fullWidth?: boolean; } const Radio = memo(function Radio({ options, value, onChange, disabled = false, className = '', fullWidth = false, }: RadioProps) { const localize = useLocalize(); const [currentValue, setCurrentValue] = useState(value ?? ''); const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]); const [backgroundStyle, setBackgroundStyle] = useState({}); const handleChange = (newValue: string) => { setCurrentValue(newValue); onChange?.(newValue); }; const updateBackgroundStyle = useCallback(() => { const selectedIndex = options.findIndex((opt) => opt.value === currentValue); if (selectedIndex >= 0 && buttonRefs.current[selectedIndex]) { const selectedButton = buttonRefs.current[selectedIndex]; const container = selectedButton?.parentElement; if (selectedButton && container) { const containerRect = container.getBoundingClientRect(); const buttonRect = selectedButton.getBoundingClientRect(); const offsetLeft = buttonRect.left - containerRect.left - 4; setBackgroundStyle({ width: `${buttonRect.width}px`, transform: `translateX(${offsetLeft}px)`, }); } } }, [currentValue, options]); useLayoutEffect(() => { updateBackgroundStyle(); }, [updateBackgroundStyle]); useLayoutEffect(() => { if (value !== undefined) { setCurrentValue(value); } }, [value]); if (options.length === 0) { return (
{localize('com_ui_no_options')}
); } const selectedIndex = options.findIndex((opt) => opt.value === currentValue); return (
{selectedIndex >= 0 && (
)} {options.map((option, index) => ( ))}
); }); export default Radio;