import { cloneElement } from 'react'; import styled, { type AnyStyledComponent } from 'styled-components'; import { Root, Trigger, Content, ItemIndicator, RadioGroup, RadioItem, Portal, } from '@radix-ui/react-dropdown-menu'; import { type MenuItem } from '@/constants/menus'; import { Icon, IconName } from '@/components/Icon'; import { Tag } from '@/components/Tag'; import { popoverMixins } from '@/styles/popoverMixins'; import { layoutMixins } from '@/styles/layoutMixins'; type ElementProps = { disabled?: boolean; items: MenuItem[]; value: MenuItemValue; onValueChange: (value: MenuItemValue) => void; children?: React.ReactNode; slotTrigger?: JSX.Element; }; type StyleProps = { align?: 'center' | 'start' | 'end'; sideOffset?: number; className?: string; }; export const DropdownSelectMenu = ({ items, value, onValueChange, slotTrigger, children = (() => { const currentItem = items.find((item) => value === item.value); return ( <> {currentItem?.slotBefore} {currentItem?.label ?? value} ); })(), align = 'start', sideOffset = 1, className, disabled, }: ElementProps & StyleProps) => { const triggerContent = ( <> {children} ); return ( {slotTrigger ? cloneElement(slotTrigger, { children: triggerContent }) : triggerContent} onValueChange(value as MenuItemValue)} > {items.map(({ value, label, slotBefore, slotAfter, tag, disabled }) => ( {slotBefore} {label} {tag && ( <> {' '} {tag} )} {slotAfter} ✔{/* */} ))} ); }; const Styled: Record = {}; Styled.Trigger = styled(Trigger)` ${layoutMixins.row} gap: 1rem; ${popoverMixins.trigger} ${popoverMixins.backdropOverlay} `; Styled.DropdownIcon = styled.span` display: inline-flex; transition: transform 0.3s var(--ease-out-expo); font-size: 0.375em; ${Styled.Trigger}[data-state='open'] & { transform: scaleY(-1); } `; Styled.Content = styled(Content)` ${popoverMixins.popover} ${popoverMixins.popoverAnimation} `; Styled.RadioItem = styled(RadioItem)` ${popoverMixins.item} `; Styled.ItemLabel = styled.span` flex: 1; ${layoutMixins.inlineRow} `; Styled.ItemIndicator = styled(ItemIndicator)` margin-left: auto; display: inline-flex; transition: transform 0.3s var(--ease-out-expo); `;