import { forwardRef, useRef, useState, useEffect, useCallback } from 'react' import * as RadixMenu from '@radix-ui/react-dropdown-menu' import { Check } from 'lucide-react' import Block from '../Primitives/Block/Block' import PrimitiveText from '../Primitives/PrimitiveText/PrimitiveText' import { Checkbox } from '../Checkbox' import { Tooltip, TooltipSide } from '../Tooltip' import { checkIfTruncated } from '../Select/SelectItem/utils' import SelectItemIndicator from './SelectItemIndicator' import type { SelectItemV2Props } from './types' const SlotWrapper = ({ slot }: { slot: React.ReactNode }) => ( {slot} ) const SelectItemV2 = forwardRef( (props, ref) => { const { item, onSelect, itemTokens, index = 0, selectedPosition = 'none', className, asMenuItem = true, focusIdentityValue, role, tabIndex, ariaSelected, ariaSetSize, ariaPosInSet, ariaDescription, decorativeIndicator = false, } = props const textRef = useRef(null) const subLabelRef = useRef(null) const [showTooltip, setShowTooltip] = useState(false) const [showSubLabelTooltip, setShowSubLabelTooltip] = useState(false) const resizeObserverRef = useRef(null) const rafRef = useRef(null) const isSelected = props.mode === 'single' ? props.selected === item.value : props.selectedValues.includes(item.value) const isMulti = props.mode === 'multi' const showCheckmark = props.mode === 'single' ? (props.showCheckmark ?? true) : false const resolvedRole = role ?? (isMulti ? 'option' : 'menuitem') const isListRow = role !== undefined const checkTruncation = useCallback(() => { if (rafRef.current !== null) cancelAnimationFrame(rafRef.current) resizeObserverRef.current?.disconnect() rafRef.current = requestAnimationFrame(() => { let nextShow = false let nextSub = false if (textRef.current) nextShow = checkIfTruncated(textRef.current) if (item.subLabel && subLabelRef.current) nextSub = checkIfTruncated(subLabelRef.current) setShowTooltip((p) => (p !== nextShow ? nextShow : p)) setShowSubLabelTooltip((p) => (p !== nextSub ? nextSub : p)) requestAnimationFrame(() => { const ro = resizeObserverRef.current if (!ro) return if (textRef.current) ro.observe(textRef.current) if (subLabelRef.current) ro.observe(subLabelRef.current) }) rafRef.current = null }) }, [item.subLabel]) useEffect(() => { if (item.disableTruncation) return resizeObserverRef.current = new ResizeObserver(() => checkTruncation() ) checkTruncation() return () => { resizeObserverRef.current?.disconnect() resizeObserverRef.current = null if (rafRef.current !== null) cancelAnimationFrame(rafRef.current) } }, [item.label, item.subLabel, item.disableTruncation, checkTruncation]) const handleSelect = (e: Event) => { if (item.disabled) { e.preventDefault() return } if (isMulti) e.preventDefault() onSelect(item.value) } const handleClick = () => { if (item.disabled) return onSelect(item.value) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key !== 'Enter' && e.key !== ' ') return e.preventDefault() handleClick() } const hasTooltip = (showTooltip && !!item.label) || (showSubLabelTooltip && !!item.subLabel) || !!item.tooltip const tooltipContent = item.tooltip ?? ( <> {showTooltip && item.label && {item.label}} {showSubLabelTooltip && item.subLabel && ( {item.subLabel} )} ) const defaultRadius = String(itemTokens.borderRadius ?? '') const getBorderRadius = (): string => { if (!isSelected || selectedPosition === 'none') return defaultRadius switch (selectedPosition) { case 'first': return `${defaultRadius} ${defaultRadius} 0 0` case 'middle': return '0' case 'last': return `0 0 ${defaultRadius} ${defaultRadius}` default: return defaultRadius } } const colorState = item.disabled ? 'disabled' : isSelected ? 'selected' : 'default' const itemBlock = ( {item.slot1 && } {item.label} {item.slot2 && } {item.slot3 && } {item.slot4 && } {showCheckmark && isSelected && ( )} {isMulti && (decorativeIndicator ? ( ) : ( ))} {item.subLabel && ( {item.subLabel} )} ) const itemContent = asMenuItem ? ( {itemBlock} ) : ( itemBlock ) if (hasTooltip) { return ( {itemContent} ) } return itemContent } ) SelectItemV2.displayName = 'SelectItemV2' export default SelectItemV2