import React, { type ComponentPropsWithoutRef, type FC, type ReactNode } from 'react'; import { Menu } from '@base-ui/react/menu'; import { cn } from '@wener/console'; import type { FlexRenderable } from '@wener/reaction'; import { flexRender } from '@wener/reaction'; import { clsx } from 'clsx'; import { pick } from 'es-toolkit'; import { match } from 'ts-pattern'; import { isNodeTypeOf } from '../utils/isNodeTypeOf'; export type DaisyDropdownMenuItem = | ({ type?: 'item'; label?: ReactNode; icon?: FlexRenderable; } & ComponentPropsWithoutRef) | ({ type: 'label'; label?: ReactNode } & ComponentPropsWithoutRef) | ({ type: 'separator' } & ComponentPropsWithoutRef); type CompositeProps = { items: DaisyDropdownMenuItem[]; children?: ReactNode; trigger?: ReactNode; portal?: boolean; // root open?: boolean; defaultOpen?: boolean; onOpenChange?(open: boolean): void; modal?: boolean; // className?: string; }; export const DaisyDropdownMenuComposite = ({ items, children, trigger, portal, className, ...props }: CompositeProps) => { trigger ||= children; if (trigger) { if (!isNodeTypeOf(trigger, [Menu.Trigger, DaisyDropdownMenuTrigger])) { let last = trigger; trigger = {last}; } } let content = ( {items.map((item, key) => { return match(item) .with({ type: 'label' }, ({ label, type, className, children, ...props }) => { return ( {label || children} ); }) .with({ type: 'separator' }, ({ type, className, ...props }) => { return ; }) .otherwise(({ label, icon, type, className, children, ...props }) => { return ( {flexRender(icon, { className: 'size-4' })} {label} } /> ); }); })} ); return ( {trigger} {portal && {content}} {!portal && content} ); }; export interface DaisyDropdownMenuTriggerProps extends React.ComponentProps {} export const DaisyDropdownMenuTrigger: FC = ({ className, ...props }) => { return ; }; export const DaisyDropdownMenu: { Composite: typeof DaisyDropdownMenuComposite; Trigger: typeof DaisyDropdownMenuTrigger; Root: typeof Menu.Root; Portal: typeof Menu.Portal; Positioner: typeof Menu.Positioner; Popup: typeof Menu.Popup; Item: typeof Menu.Item; Separator: typeof Menu.Separator; GroupLabel: typeof Menu.GroupLabel; } = { Composite: DaisyDropdownMenuComposite, Trigger: DaisyDropdownMenuTrigger, Root: Menu.Root, Portal: Menu.Portal, Positioner: Menu.Positioner, Popup: Menu.Popup, Item: Menu.Item, Separator: Menu.Separator, GroupLabel: Menu.GroupLabel, }; // Export individual MenuItem type for external use export type { DaisyDropdownMenuItem as MenuItem };